PhoenixKitAI.Request (PhoenixKitAI v0.26.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", "embedding", "tts", "image", "image_edit", "vision")

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: What the call cost in US dollars, a Decimal (when known)
  • 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.)
  • metadata.answered_model: on chat and embedding rows, the model the provider says answered, where it is not the one asked for in model (answered_model/1). Image and vision rows record the answered model in model itself.
  • metadata.provider_error: on a failed call, what the provider said — status, code, message (trimmed, key-shaped words redacted) and retry_after_s for an error that is not about money.

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

The model the provider says answered (metadata.answered_model), where it is not the one asked for; nil otherwise.

The core status_badge status that colours a request's status: green for a success, red for an error, amber for a timeout. The label stays status_label/1.

Creates a changeset for request creation.

Formats a cost in dollars for display, with the precision the amount needs

Formats the latency for display.

Formats the token count for display.

Whether the row is a call the guard refused before any HTTP (metadata.refused). Its status is "error"; the Usage tab marks it and filters on it as "refused".

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(),
  cost: 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

answered_model(request)

@spec answered_model(t()) :: String.t() | nil

The model the provider says answered (metadata.answered_model), where it is not the one asked for; nil otherwise.

badge_status(arg1)

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

The core status_badge status that colours a request's status: green for a success, red for an error, amber for a timeout. The label stays status_label/1.

changeset(request, attrs)

Creates a changeset for request creation.

format_cost(dollars)

@spec format_cost(Decimal.t() | 0 | nil) :: String.t()

Formats a cost in dollars for display, with the precision the amount needs:

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

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

  • = $0.000001: 6 decimal places ($0.000030)

  • $0: at least 10 decimal places, more for an amount that needs them to show three significant digits, up to the column's 18 ($0.0000000400, $0.00000000000141)

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.

refused?(request)

@spec refused?(t()) :: boolean()

Whether the row is a call the guard refused before any HTTP (metadata.refused). Its status is "error"; the Usage tab marks it and filters on it as "refused".

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.