> ## Documentation Index
> Fetch the complete documentation index at: https://polza.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Как задавать вопросы Jev

> Три типа вопросов — noul, choice, score, — структура state и приёмы, от которых зависит качество ответов

Запрос к Jev состоит из двух частей: **`state`** — что оцениваем, и **`questions`** — что хотим узнать. Качество ответов почти целиком определяется тем, как сформулированы вопросы. Если вы ещё не отправляли запросов — начните с [первого запроса](/docs/gaidy/jev#первый-запрос).

## Один вопрос — одно суждение

Задавайте вопросы, на которые знающий человек ответит за секунду, взглянув на текст.

| Плохо                                              | Хорошо                                                                                          |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| «Проанализируй обращение и реши, что с ним делать» | «Клиент просит вернуть деньги?»                                                                 |
| «Оцени резюме кандидата»                           | Отдельно: глубина опыта в Python, опыт руководства, опыт проектирования систем                  |
| «Это спам?»                                        | Отдельно: есть ли ссылка на сторонний сайт, обещают ли лёгкий заработок, обращаются ли по имени |

Если решение зависит от нескольких факторов — спросите про каждый отдельно и сложите ответы в коде со своими весами. Изменились приоритеты — меняете коэффициент, а не переписываете промпт. Лишних запросов это не добавляет: все вопросы к одному `state` уходят одним запросом и обрабатываются параллельно.

## Из чего состоит вопрос

```json theme={null}
"refund_requested": {
  "type": "noul",
  "instructions": "Клиент просит вернуть деньги?"
}
```

* **Имя вопроса** (`refund_requested`) — для вашего кода: под ним придёт ответ. Модель его не видит, поэтому весь смысл должен быть в `instructions`.
* **`type`** — `noul`, `choice` или `score`.
* **`instructions`** — сам вопрос. Пишите точно и буквально: Jev отвечает на то, что написано, а не на то, что вы имели в виду.
* **`criteria`** — варианты ответа: у `choice` обязательны, у `score` обязательны, у `noul` — по желанию.

## Noul — да или нет

Возвращает вероятность «да» от 0 до 1. Около 1 — уверенное «да», около 0 — уверенное «нет», около 0,5 — модель не знает.

```json theme={null}
"has_pii": {
  "type": "noul",
  "instructions": "В сообщении есть персональные данные: телефон, адрес, паспорт, номер карты?"
}
```

Формулируйте так, чтобы высокая вероятность означала «да». Если граница между «да» и «нет» тонкая — уточните её в `criteria`:

```json theme={null}
"is_urgent": {
  "type": "noul",
  "instructions": "Клиент сообщает о срочной проблеме?",
  "criteria": {
    "true": "Прямо сказано о срочности, сроках или идущих убытках",
    "false": "Срочность не упомянута, даже если проблема серьёзная"
  }
}
```

<Warning>
  `noul` — не шкала. Значение 0,5 на вопрос «Кандидат силён в Python?» означает «модель не может решить», а не «средний уровень». Чтобы измерить уровень, используйте `score`.
</Warning>

## Choice — выбор из вариантов

Подходит, когда ответ — одна из известных категорий без порядка между ними: отдел, тема, тип документа, язык.

```json theme={null}
"department": {
  "type": "choice",
  "instructions": "Какая команда должна заняться обращением?",
  "criteria": {
    "returns": "Обмен, возврат, не тот или повреждённый товар",
    "shipping": "Статус доставки, задержки, потерянные посылки",
    "billing": "Списания, счета, проблемы с оплатой",
    "other": "Ничего из перечисленного"
  }
}
```

* Ключ — имя варианта, значение — его описание. Модель видит и то и другое, поэтому описания должны **отличать варианты друг от друга**. Если имя говорит само за себя, вместо описания можно передать `null`.
* Давайте полный список, а не выжимку: вариантов может быть до 255, каждый стоит несколько токенов.
* Добавляйте `other` или «ничего из перечисленного», если список может не покрывать все случаи. Иначе модель будет вынуждена выбрать неподходящий вариант.

В ответе `choice` — победитель, `probabilities` — вероятности всех вариантов (в сумме 1), `confidence` — насколько победитель оторвался от остальных.

## Score — оценка по шкале

Подходит, когда ответ лежит на спектре и вы можете описать каждую его точку: критичность, раздражение, релевантность, качество.

```json theme={null}
"bug_severity": {
  "type": "score",
  "instructions": "Насколько серьёзна описанная проблема?",
  "criteria": [
    "Косметический дефект, на работу не влияет",
    "Функция сломана, но есть обходной путь",
    "Работа заблокирована, обходного пути нет"
  ]
}
```

Уровни нумеруются с нуля по порядку в массиве — здесь это 0, 1 и 2. `score` в ответе — положение на этой шкале, и оно может оказаться **между** уровнями: 1,3 означает «в основном уровень 1, отчасти уровень 2».

Как писать уровни:

* **Описывайте ситуации, а не степени.** «Функция сломана, но есть обходной путь» модель может сопоставить с текстом. «Умеренно серьёзно» — не с чем сопоставлять.
* **Каждый уровень оценивается отдельно**, соседей модель не видит. Фразы вроде «хуже предыдущего» и цифры в описаниях не работают.
* **Одна шкала — одно измерение.** «Пунктуальный, умный и опытный» — это три шкалы. Разделите и сложите в коде.
* От 2 до 10 уровней. Берите столько, сколько можете описать различимо; трёх обычно достаточно.
* Если на краю шкалы есть редкий случай, на который нужна особая реакция, дайте ему свой уровень: после «очень зол» добавьте «угрожает или оскорбляет».

<Note>
  Один и тот же `score` могут дать разные распределения: 1,0 — это и «точно уровень 1», и «поровну 0 и 2». Смотрите на `confidence` и `probabilities` вместе со `score`. Низкая уверенность обычно значит одно из трёх: уровни перекрываются, вопрос измеряет сразу несколько вещей или в тексте недостаточно данных.
</Note>

## Какой тип выбрать

Берите тот, чей ответ код использует напрямую: `noul` ложится в `if`, `choice` — в ветвление по категориям, `score` — в порог или сортировку.

| Нужно узнать                                                               | Тип                               |
| -------------------------------------------------------------------------- | --------------------------------- |
| Есть ли признак: жалоба, срочность, просьба о возврате                     | `noul`                            |
| К какой категории относится                                                | `choice`                          |
| Насколько сильно выражено свойство                                         | `score`                           |
| Какое значение из закрытого списка названо в тексте (месяц, валюта, товар) | `choice` с вариантом «не указано» |

## Что класть в state

`state` — это материал для оценки: строка, объект или массив. Только текст: изображения, аудио и видео не поддерживаются.

| Формат | Когда удобен                             | Пример                                          |
| ------ | ---------------------------------------- | ----------------------------------------------- |
| Строка | Одно сообщение или абзац                 | `"С меня дважды списали деньги."`               |
| Объект | Несколько связанных частей с именами     | `{"message": "...", "policy": "..."}`           |
| Массив | Последовательность сообщений или записей | `["Здравствуйте", "Номер заказа A-104", "..."]` |

В большинстве случаев лучше объект: у каждой части есть имя, и в вопросе на неё можно сослаться.

**Кладите только то, что нужно для решения.** Лишний текст отвлекает модель и снижает точность — отфильтруйте данные в коде до запроса. Актуальные факты (правила возврата, остатки, статус заказа) передавайте в `state`, а не рассчитывайте на знания модели.

### Ссылки на части state

Если `state` — объект, укажите в вопросе путь к нужной части **в обратных кавычках**:

```json theme={null}
{
  "model": "typesafe/jev",
  "state": {
    "ticket": {
      "subject": "Двойное списание",
      "messages": [
        { "from": "customer", "text": "С меня дважды списали за заказ A-104. Верните, пожалуйста, лишний платёж." },
        { "from": "support", "text": "Проверяем списания." }
      ]
    },
    "order": {
      "id": "A-104",
      "charges": [
        { "amount_rub": 4900, "status": "captured" },
        { "amount_rub": 4900, "status": "captured" }
      ]
    },
    "refund_policy": "Двойные списания возвращаются в полном объёме."
  },
  "questions": {
    "refund_requested": {
      "type": "noul",
      "instructions": "В `ticket.messages[0].text` клиент просит вернуть деньги?"
    },
    "policy_supports_refund": {
      "type": "noul",
      "instructions": "Поддерживает ли `refund_policy` возврат, о котором просят в `ticket.messages[0].text`, с учётом `order.charges`?"
    }
  }
}
```

Ответ: `refund_requested` — 0,98, `policy_supports_refund` — 0,97.

## Много вопросов одним запросом

Все вопросы к одному `state` отправляйте вместе. Они обрабатываются параллельно и независимо: время ответа почти не растёт, а ответ на один вопрос не влияет на другой.

Спрашивайте и то, что **может не понадобиться**. Если обращение окажется не про баг — просто не читайте ответ про критичность бага. Лишний вопрос стоит несколько токенов, а отдельный запрос — ещё раз весь `state` и служебные токены.

Второй запрос оправдан только тогда, когда без первого ответа его нельзя составить: нужно сходить за данными, зависящими от ответа, или варианты следующего вопроса определяются предыдущим (обход дерева категорий уровень за уровнем).

Предел — общий бюджет запроса, см. [ограничения](/docs/gaidy/jev-recipes#ограничения-модели).

## Когда варианты путаются: структурные описания

Начинайте с коротких строк. Если модель стабильно путает два близких варианта, опишите каждый объектом: что входит, что **не** входит, примеры. Имена полей вы придумываете сами — модель видит их вместе со значениями, так что называйте понятно и одинаково у всех вариантов.

```json theme={null}
"topic": {
  "type": "choice",
  "instructions": "О чём спрашивает клиент?",
  "criteria": {
    "return_policy": {
      "what": "Вопросы о правилах: можно ли вернуть, в какой срок, на каких условиях",
      "not_for": "Статус уже оформленного возврата",
      "examples": ["Можно ли вернуть обувь после примерки?", "Сколько дней на возврат?"]
    },
    "return_status": {
      "what": "Статус уже отправленного возврата и сроки получения денег",
      "not_for": "Общие правила возврата",
      "examples": ["Где мой возврат?", "Посылка дошла, когда вернёте деньги?"]
    },
    "other": null
  }
}
```

На обращение «Отправил товар обратно неделю назад, трек показывает, что посылка у вас. Когда вернутся деньги?» ответ — `return_status` с уверенностью 1,0.

Так же можно структурировать `instructions`, уровни `score` и `criteria` у `noul`. Примеры помогают, только когда похожи на ваши реальные данные.

<Warning>
  Рост `confidence` после правки формулировок ещё не значит, что ответы стали правильнее. Проверяйте изменения на примерах с известным правильным ответом.
</Warning>

## Памятка

<AccordionGroup>
  <Accordion title="Формулировки">
    * Один вопрос — одно суждение.
    * Пишите буквально: точное условие, граничные случаи — в `criteria`.
    * Избегайте двойных отрицаний и вопросов «про свойство свойства».
    * Следите, чтобы `instructions` и `criteria` не противоречили друг другу.
  </Accordion>

  <Accordion title="State">
    * Объект с именованными полями вместо одной длинной строки.
    * Только то, что нужно для решения.
    * В вопросах — пути к полям в обратных кавычках.
  </Accordion>

  <Accordion title="Запросы">
    * Все вопросы к одному `state` — одним запросом.
    * Спрашивайте с запасом, лишнее игнорируйте в коде.
    * Пороги уверенности подбирайте на своих данных.
  </Accordion>
</AccordionGroup>
