# `PhoenixAI.Usage`
[🔗](https://github.com/franciscpd/phoenix-ai/blob/main/lib/phoenix_ai/usage.ex#L1)

Normalized token usage from any AI provider.

All provider-specific usage data is mapped to a consistent shape
via `from_provider/2`. The original raw data is preserved in
`provider_specific` for backward compatibility.

## Examples

    iex> PhoenixAI.Usage.from_provider(:openai, %{"prompt_tokens" => 10, "completion_tokens" => 20, "total_tokens" => 30})
    %PhoenixAI.Usage{input_tokens: 10, output_tokens: 20, total_tokens: 30, provider_specific: %{"prompt_tokens" => 10, "completion_tokens" => 20, "total_tokens" => 30}}

# `t`

```elixir
@type t() :: %PhoenixAI.Usage{
  cache_creation_tokens: non_neg_integer() | nil,
  cache_read_tokens: non_neg_integer() | nil,
  input_tokens: non_neg_integer(),
  output_tokens: non_neg_integer(),
  provider_specific: map(),
  total_tokens: non_neg_integer()
}
```

# `from_provider`

```elixir
@spec from_provider(atom(), map() | nil) :: t()
```

Maps raw provider usage data to a normalized `%Usage{}` struct.

Accepts a provider atom and the raw usage map from the provider's
JSON response. Returns a `%Usage{}` with consistent field names.

## Supported providers

  * `:openai` — maps `prompt_tokens`, `completion_tokens`, `total_tokens`
  * `:anthropic` — maps `input_tokens`, `output_tokens`, cache fields; auto-calculates `total_tokens`
  * `:openrouter` — delegates to `:openai` (same wire format)
  * Any other atom — generic fallback that tries both naming conventions

When `raw` is `nil` or an empty map, returns a zero-valued `%Usage{}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
