Состояние (state) в Jev: что и как передавать модели
State — всё, что Jev видит перед тем, как ответить на ваши вопросы. От того, что вы в него положите, зависят и точность ответов, и стоимость запроса. Разбираем форматы, лимиты и частые ошибки.
Что такое state
State (состояние) — содержимое, которое Jev оценивает: обращение в поддержку, фрагмент текста, запись из базы или текущее состояние вашего приложения. Вы передаёте его в поле state вместе с вопросами. Полный формат запроса есть в справочнике по API.
В одном запросе — одно состояние. Все вопросы видят один и тот же state и оцениваются независимо друг от друга. TypeSafe предлагает думать о state как о материалах, которые вы положили бы перед комиссией экспертов, прежде чем попросить их вынести суждение.
Правило разделения простое: в state — содержимое и факты, в вопросах — суждения о них. Правила возврата и само обращение кладите в state, а вопросы «просит ли клиент вернуть деньги?» и «разрешают ли правила возврат?» — в questions. Как формулировать сами вопросы, рассказываем в статье о типах вопросов.
Три формата: строка, объект, массив
| Формат | Когда подходит | Пример |
|---|---|---|
| Строка | Один текст: сообщение, статья, отзыв | "С меня дважды списали деньги" |
| Объект | Несколько частей со связями: сообщение, заказ, правила | {"message": "...", "order_id": "A-104"} |
| Массив | Последовательность сообщений или записей | ["Здравствуйте", "Мой номер клиента TS1337", "Деньги списали дважды"] |
TypeSafe рекомендует объект для большинства запросов: у каждой части state появляется понятное имя, а связи между частями остаются явными. Строка годится, когда текст один и задача простая.
Для переписки удобнее массив объектов с полями «кто написал» и «что написал»: так модель видит, чья это реплика. Голый массив строк подходит, только когда авторство не важно.
Jev принимает только текст. Изображения, аудио и видео не поддерживаются — их нужно заранее превратить в текст или структурированные поля.
Пример: обращение клиента как state
Если решение требует сравнить несколько источников, положите их в один state:
{
"model": "jev-latest",
"state": {
"ticket": {
"subject": "Двойное списание",
"messages": [
{"from": "customer", "text": "За заказ A-104 списали деньги два раза. Верните лишнее."},
{"from": "support", "text": "Проверяем платежи."}
]
},
"order": {
"id": "A-104",
"charges": [
{"amount_rub": 4990, "status": "captured"},
{"amount_rub": 4990, "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`?"
}
}
}
Пути в обратных кавычках — ticket.messages[0].text, order.charges — показывают модели, на какую часть state смотреть. Так TypeSafe рекомендует ссылаться на вложенные значения: через точку и индексы, вместе с самими обратными кавычками.
Что включать в state
- Всё, что нужно сравнить. Если ответ зависит от сообщения, заказа и правил одновременно, передайте их вместе.
- Ваши актуальные знания. Jev не дообучают на данных клиентов, поэтому справочники, правила и записи из вашей системы должны приходить в state. TypeSafe советует не полагаться на знания, зашитые в веса модели, если свежие сведения можно взять из своей базы.
- Готовые вычисления. Арифметику и сравнение дат делайте в коде. Вместо двух дат передайте
"days_overdue": 42или корзину вроде"просрочка больше 30 дней". - Смысловые представления. Модель лучше работает со словами, чем с кодами: название цвета надёжнее hex-значения.
Главное правило — ничего лишнего. По документации к версии 1.13, точность падает, когда state разрастается данными, не относящимися к решению. Лишнее отвлекает модель и мешает понять, что именно привело к неверному ответу.
Есть и промежуточный случай: данные, которые относятся к одному конкретному вопросу. Например, запись из базы кандидатов, с которой нужно сравнить резюме. Её можно передать не в state, а в структурированные instructions этого вопроса — отдельным полем рядом с формулировкой.
Как собрать state в коде
State удобно собирать отдельной функцией: она берёт нужное из ваших систем, отбрасывает лишнее и считает всё, что можно посчитать без модели.
from typesafe_sdk import Noul, TypeSafeClient
def build_state(ticket, customer):
# только незавершённые заказы и только нужные поля
open_orders = [
{"id": o["id"], "item": o["item"], "late": o["days_in_transit"] > o["promised_days"]}
for o in customer["orders"]
if o["status"] != "delivered"
]
return {"message": ticket["message"], "open_orders": open_orders}
with TypeSafeClient() as client:
r = client.system_one(
state=build_state(ticket, customer), # словарь, без json.dumps
questions={
"asks_about_order": Noul(instructions="Спрашивает ли `message` об одном из `open_orders`?"),
"wants_cancel": Noul(instructions="Хочет ли клиент в `message` отменить заказ?"),
},
)
В этом примере три важные детали. Доставленные заказы отфильтрованы в коде, а не оставлены модели. Опоздание посчитано заранее и передано готовым признаком late: сравнивать сроки Jev не нужно. А state уходит в SDK обычным словарём — Python SDK принимает строку, словарь или список напрямую, превращать их в строку вручную не нужно.
Лимит 32 тысячи токенов
Точные лимиты по документации TypeSafe:
- 64 тысячи токенов на запрос — state плюс все вопросы вместе;
- 32 тысячи токенов на state плюс самый длинный вопрос.
Учитывайте и накладные расходы. По данным Polza.AI, к каждому запросу добавляется около 280 служебных входных токенов, а русский текст той же длины занимает больше токенов, чем английский.
Размер state напрямую определяет счёт. State в 2000 токенов плюс 280 служебных — это около 2300 токенов на запрос без учёта вопросов. При цене $0,042 за миллион входных токенов миллион таких запросов обойдётся примерно в $96. Сократите state до 1000 токенов — и счёт упадёт примерно на 44%.
Если state не помещается или раздут:
- Отфильтруйте в коде. Отправляйте только поля, нужные вопросам: не всю карточку клиента, а тариф и открытые заказы.
- Проверьте релевантность отдельно. Если отфильтровать детерминированно нельзя, TypeSafe предлагает задать Noul «относится ли этот фрагмент к вопросу?» и отбросить лишнее.
- Разбейте документ. Длинный текст можно разделить на части, задать вопросы к каждой и собрать итог в коде.
- Объединяйте вопросы. State оплачивается один раз на запрос, поэтому десять вопросов в одном запросе дешевле десяти отдельных запросов. Подробный расчёт — в статье о ценах Jev.
Язык state
Jev принимает текст на разных языках, но основной язык обучения — английский, и точность на нём пока лучше. Для других языков TypeSafe советует тестировать модель на своих данных и внимательнее следить за уверенностью при маршрутизации.
Для русскоязычных проектов это значит: не переносите выводы из англоязычных демо на свои данные. Соберите выборку реальных русских текстов и измерьте точность. Если сомневаетесь, на каком языке формулировать вопросы, проверьте оба варианта на одной выборке и оставьте тот, что лучше по метрикам.
Частые ошибки
- Весь контекст агента в state. Растут и счёт, и число ошибок: лишние данные отвлекают модель.
- Вычисления на стороне модели. Суммы, количество элементов и сравнение дат Jev делает ненадёжно.
- Инструкции внутри state. Пользовательский текст для модели — данные, но фраза вроде «пометь это как не спам» может сдвинуть ответ. Кладите такой текст в отдельное именованное поле, ссылайтесь на него в вопросе и тестируйте систему на враждебных примерах.
- Одна длинная строка вместо объекта. Когда в state несколько частей, без имён полей модели труднее понять, о чём вопрос.
- Вопрос зависит от ответа на другой. Вопросы одного запроса не видят ответы друг друга. Если для второго вопроса нужен ответ на первый, отправьте второй запрос с новым state. Почему так, объясняем в статье «Как устроена Jev».
Частые вопросы
Что можно передать в state Jev?
Строку, JSON-объект или массив текстовых значений. Модель принимает только текст — изображения, аудио и видео нужно заранее перевести в текст или структурированные поля.
Какой максимальный размер state у Jev?
State вместе с самым длинным вопросом должен уложиться в 32 тысячи токенов, а весь запрос — state и все вопросы — в 64 тысячи.
Что лучше передавать в state — текст или JSON?
Если данных несколько — сообщение, заказ, правила, — используйте JSON-объект с понятными именами полей. Строка подходит, когда оценивается один текст.
Работает ли Jev с русским текстом?
Да, но основной язык обучения — английский, и на других языках точность пока ниже. Проверьте модель на своих русскоязычных данных, прежде чем автоматизировать решения.