# `ALLM.ClassificationResponse`
[🔗](https://github.com/cykod/ALLM/blob/v0.6.1/lib/allm/classification_response.ex#L1)

A typed-classification response — Layer A serializable data.

    iex> a = ALLM.ClassificationAnswer.new(type: :choice, choice: "billing", confidence: 0.88)
    iex> resp = ALLM.ClassificationResponse.new(answers: %{"department" => a})
    iex> ALLM.ClassificationResponse.answer(resp, :department).choice
    "billing"

## Answers

`:answers` is keyed by the same question ids the request used, one
`ALLM.ClassificationAnswer` per question. Use `answer/2` to read one.

## Usage

`:usage` is an `ALLM.Usage`, never `nil`. An adapter populates
`:input_tokens` and `:output_tokens` from the provider and sets
`:total_tokens` to their sum. The cost fields stay `nil`: no model
catalog carries classification pricing, but pricing is per input token,
so a caller who knows the rate can compute the cost.

## Identifiers

`:id` is the provider's own identifier for the call — the value to quote
to the provider's support team — or `nil` when the provider sends none.
`:request_id` is ALLM's own correlation id. The two are never mixed: the
provider's id is not copied into `:request_id`, and it is not put in
`:metadata`, which is caller-owned.

## Other fields

`:model` is the model the provider reports as having answered. For a
provider with moving aliases this is the pinned version, not the alias
that was sent. `:provider` is the provider atom. `:raw` carries the same
caller-responsibility contract as `ALLM.Response.raw`: a
non-JSON-encodable `:raw` raises at encode time.

# `t`

```elixir
@type t() :: %ALLM.ClassificationResponse{
  answers: %{required(String.t()) =&gt; ALLM.ClassificationAnswer.t()},
  id: String.t() | nil,
  metadata: map(),
  model: String.t() | nil,
  provider: atom() | nil,
  raw: term(),
  request_id: String.t() | nil,
  usage: ALLM.Usage.t()
}
```

# `answer`

```elixir
@spec answer(t(), String.t() | atom()) :: ALLM.ClassificationAnswer.t() | nil
```

The answer for `id`, or nil. Atom ids are stringified.

## Examples

    iex> a = ALLM.ClassificationAnswer.new(type: :yes_no, yes_probability: 0.93)
    iex> resp = ALLM.ClassificationResponse.new(answers: %{"refund" => a})
    iex> ALLM.ClassificationResponse.answer(resp, "refund").yes_probability
    0.93
    iex> ALLM.ClassificationResponse.answer(resp, "missing")
    nil

# `new`

```elixir
@spec new(keyword()) :: t()
```

Build a `%ClassificationResponse{}` from keyword opts.

Unknown keys raise `KeyError` via `struct!/2`.

## Examples

    iex> resp = ALLM.ClassificationResponse.new(model: "jev-1.13.0")
    iex> {resp.answers, resp.usage}
    {%{}, %ALLM.Usage{}}

---

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