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

A typed-classification request — Layer A serializable data.

    iex> q = ALLM.ClassificationQuestion.choice("Which team?", ["billing", "technical"])
    iex> req = ALLM.ClassificationRequest.new(state: "My payouts failed.", questions: %{"department" => q})
    iex> ALLM.Validate.classification_request(req)
    :ok

## One state, many questions

A request carries one `:state` — the thing being classified — and a map of
named `:questions`. Every question is answered independently against the
same state, and the response keys its answers by the same ids, so asking
several questions in one request costs one call rather than several.

`:state` is a string, a JSON object (map), or a JSON array (list). It is
text only: images and audio are not part of the state union.

## Question ids are strings

The keys of `:questions` must be non-empty binaries. Atom keys would not
survive a JSON round trip, so `ALLM.Validate.classification_request/1`
rejects them rather than letting a persisted request change shape.

## State encoding caveat

A map `:state` with atom keys is sent with string keys and comes back
from a JSON round trip with string keys — the same property every
`metadata: map()` field has. Use string keys when the request will be
persisted.

## Construction

`new/1` is a bare `struct!/2` pass-through: unknown keys raise `KeyError`,
and nothing is enforced. `state: nil` and `questions: %{}` are
deliberately constructible so that the validator, not the constructor,
rejects them.

## Other fields

`:model` is `nil` by default and late-resolved. `:options` is the home for
provider-specific opaque opts; an adapter that has no use for it ignores
it and says so. `:metadata` is caller-owned.

# `state`

```elixir
@type state() :: String.t() | map() | list()
```

The input being classified: text, a JSON object, or a JSON array.

# `t`

```elixir
@type t() :: %ALLM.ClassificationRequest{
  metadata: map(),
  model: String.t() | nil,
  options: map(),
  questions: %{required(String.t()) =&gt; ALLM.ClassificationQuestion.t()},
  state: state() | nil
}
```

# `new`

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

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

Unknown keys raise `KeyError` via `struct!/2`. No validation — call
`ALLM.Validate.classification_request/1` to check the field rules.

## Examples

    iex> req = ALLM.ClassificationRequest.new()
    iex> {req.state, req.questions, req.model}
    {nil, %{}, nil}

    iex> req = ALLM.ClassificationRequest.new(state: %{"ticket" => "Refund please"}, model: "jev-1.13.0")
    iex> req.model
    "jev-1.13.0"

---

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