# Choice

Select one option from a defined set. The answer has the chosen option, a probability for every option, and a confidence.

## Request

```json
{"state": "My running shoes arrived in the wrong size.",
 "model": "jepela-latest",
 "questions": {"department": {"type": "choice", "instructions": "Which team should handle this?",
                              "criteria": {"returns": "Exchanges, wrong or damaged items",
                                           "shipping": "Delivery status, delays, lost packages",
                                           "billing": "Charges, invoices, payment problems"}}}}
```

`criteria` is a map of 1 to 255 option names to descriptions. Descriptions may be strings or JSON objects.

Up to 20 options are read in one pass by the engine. **With more than 20, Jepela matches instead of reading** (`"method": "auto"`, the default): the state and each option are turned into vectors by a small embedding model, the options once and then cached, and the closest option wins. The answer has `"method": "match"`, `probabilities` from the similarities, and `similarity` (the best and second-best cosine). Measured on 2026-09-27 on BANKING77 (600 real bank messages, 77 intents that are close to each other), on a GPU test server: matching 65.2% right in a median of 12 ms, 23 tokens billed; the engine reading all 77 options 62.2% in 57 ms, 812 tokens. On public data matching also picked the right function among 672 far more often than the engine (60.0% against 37.3% on the same 150 questions, measured on public data on 2026-09-26).

- `"method": "engine"` makes the engine read every option; above 20 it asks in two rounds, the options in groups of up to 20, then the group winners against each other (8 of 8 right at 40, 80 and 255 options, measured 2026-09-23). The answer then has `"rounds": 2`.
- `"method": "match"` matches every choice question, whatever its size (not score or noul questions).
- Matching reads a string or an object from its start, with its memory lines placed first, at most 512 tokens (its search prefix and two special tokens included). An array it reads as the engine reads it: the elements the engine kept (its oldest left out so that the memory lines are read, see State), and where the matching model reads less than the engine, its newest elements that fit with the lines, the oldest left out whole, never a line or the newest element. What is still too long is cut from its start. The question's `reading` (with `method: "match"`, counted with the matching model's tokens) says what it read, and a state it did not read whole brings the `state_cut` warning; a matched choice is not read in windows. For short choices read in context (a handful of options, yes/no, scores), the engine stays the default: it judges the situation; matching finds the closest label.
- Write options as short descriptions of what they mean (`"card_arrival": "card has not arrived"`); an option without a description is matched by its name.

The engine is sensitive to the order of the options: answers to a large choice can change when its options are reordered. `"robust": true` asks each choice in up to three fixed orders built from the sorted option names and averages them, so the caller's order no longer matters; the answer has `orders` and `agreement` (the share of orders that picked the winner). A 2-option choice has only 2 orders; `{"orders": n}` sets 1 to 5. Each order reads the state again, and the tokens it reads are billed (`usage.input_tokens`). This applies to choices of up to 20 options: a larger choice is matched (the order does not matter there), or with `"method": "engine"` answered in two rounds, in groups that follow the order you wrote, and is not asked in several orders.

## Answer

```json
{
 "department": {
  "type": "choice",
  "choice": "returns",
  "confidence": 0.249,
  "probabilities": {
   "returns": 0.623,
   "shipping": 0.319,
   "billing": 0.058
  }
 }
}
```

`choice` is the option with the highest probability. `confidence` is reported when the engine computes it (Jepela does); it summarises how concentrated the probabilities are (one minus their normalised entropy). It is not the probability of the choice: that is `answer_confidence`, and a noul's `confidence` is on that scale instead; see Confidence.

## Guidance

- Include `other` or `none_of_these` when the options may not cover the state.
- Keep options mutually exclusive; overlapping descriptions split the probability.
- For deep hierarchies, chain Choice questions level by level, or put the children inside each parent's description so the engine sees the subtree.
- Gate actions on confidence; see Confidence.
- Do not name a forbidden option in a rule you put in memory; see Rules in memory.
