PhoenixKitAI.Request (PhoenixKitAI v0.2.1)

Copy Markdown View Source

AI request schema for PhoenixKit AI system.

Tracks every AI API request for usage history and statistics. Used for monitoring costs, performance, and debugging.

Schema Fields

Request Identity

  • endpoint_uuid: Foreign key to the AI endpoint used
  • endpoint_name: Denormalized endpoint name for historical display
  • prompt_uuid: Foreign key to the AI prompt used (if request used a prompt template)
  • prompt_name: Denormalized prompt name for historical display
  • user_uuid: Foreign key to the user who made the request (nullable if user deleted)
  • slot_index: Which slot was used (deprecated, for backward compatibility)

Request Details

  • model: Model identifier (e.g., "anthropic/claude-3-haiku")
  • request_type: Type of request (e.g., "text_completion", "chat")

Token Usage

  • input_tokens: Number of tokens in the prompt
  • output_tokens: Number of tokens in the response
  • total_tokens: Total tokens used (input + output)

Performance & Cost

  • cost_cents: Estimated cost in nanodollars (when available)
  • latency_ms: Response time in milliseconds
  • status: Request status - "success", "error", or "timeout"
  • error_message: Error details if status is not "success"

Metadata

  • metadata: Additional context (temperature, max_tokens, etc.)

Status Types

  • success - Request completed successfully
  • error - Request failed with an error
  • timeout - Request timed out

Usage Examples

# Log a successful request
{:ok, request} = PhoenixKitAI.create_request(%{
  endpoint_uuid: endpoint.uuid,
  endpoint_name: "Claude Fast",
  user_uuid: user.uuid,
  model: "anthropic/claude-3-haiku",
  request_type: "chat",
  input_tokens: 150,
  output_tokens: 320,
  total_tokens: 470,
  latency_ms: 850,
  status: "success",
  metadata: %{"temperature" => 0.7}
})

# Log a failed request
{:ok, request} = PhoenixKitAI.create_request(%{
  endpoint_uuid: endpoint.uuid,
  endpoint_name: "Claude Fast",
  model: "anthropic/claude-3-haiku",
  status: "error",
  error_message: "Rate limit exceeded"
})

Summary

Functions

Creates a changeset for request creation.

Formats the cost for display.

Formats the latency for display.

Formats the token count for display.

Extracts the model name without provider prefix.

Returns a CSS class for the status badge.

Returns a human-readable, gettext-translated status label.

Returns the list of valid request types.

Returns the list of valid status types.

Types

t()

@type t() :: %PhoenixKitAI.Request{
  __meta__: term(),
  account_uuid: term(),
  cost_cents: term(),
  endpoint: term(),
  endpoint_name: term(),
  endpoint_uuid: term(),
  error_message: term(),
  input_tokens: term(),
  inserted_at: term(),
  latency_ms: term(),
  metadata: term(),
  model: term(),
  output_tokens: term(),
  prompt: term(),
  prompt_name: term(),
  prompt_uuid: term(),
  request_type: term(),
  slot_index: term(),
  status: term(),
  total_tokens: term(),
  updated_at: term(),
  user: term(),
  user_uuid: term(),
  uuid: term()
}

Functions

changeset(request, attrs)

Creates a changeset for request creation.

format_cost(nanodollars)

@spec format_cost(integer() | nil) :: String.t()

Formats the cost for display.

Cost is stored in nanodollars (1/1000000 of a dollar) for precision. Shows appropriate precision based on the amount:

  • = $1.00: 2 decimal places ($1.23)

  • = $0.01: 2 decimal places ($0.05)

  • = $0.0001: 4 decimal places ($0.0012)

  • $0: 6 decimal places ($0.000030)

format_latency(ms)

@spec format_latency(integer() | nil) :: String.t()

Formats the latency for display.

format_tokens(tokens)

@spec format_tokens(integer() | nil) :: String.t()

Formats the token count for display.

short_model_name(model)

Extracts the model name without provider prefix.

status_color(arg1)

@spec status_color(String.t()) :: String.t()

Returns a CSS class for the status badge.

status_label(arg1)

@spec status_label(String.t()) :: String.t()

Returns a human-readable, gettext-translated status label.

Literal-call clauses are required so mix gettext.extract picks the strings up — a gettext(status) call over a variable wouldn't make it into the .pot.

valid_request_types()

@spec valid_request_types() :: [String.t()]

Returns the list of valid request types.

valid_statuses()

@spec valid_statuses() :: [String.t()]

Returns the list of valid status types.