Оценка вместо генерации (Jev)
Обычная модель пишет текст, и дальше вы его разбираете: ищете «да» в ответе, парсите JSON, надеетесь, что формат не поедет. Jev не пишет текста вообще. Вы даёте ей состояние и список типизированных вопросов — она возвращает вероятности, оценки и выбор.
Это быстро (доли секунды), очень дёшево и не ломается: ответ всегда нужной формы, потому что форму задаёте вы.
Для чего: классификация обращений, маршрутизация заявок, проверка по критериям, модерация, отбор — всё, где нужен не текст, а решение.
Несколько вопросов — один запрос
Модель отвечает на все вопросы за один вызов. Десять вопросов одним запросом стоят примерно как один — это и есть способ экономить.
Быстрый старт
curl https://nordrouter.com/v1/evaluate \
-H "Authorization: Bearer ВАШ-КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe-ai/jev",
"state": "Заказ №1841 не пришёл, клиент пишет третий раз, тон резкий",
"questions": {
"urgent": {
"type": "boolean",
"question": "Это срочно?",
"criteria": { "true": "повторное обращение или резкий тон", "false": "первое спокойное" }
},
"team": {
"type": "choice",
"question": "Кому передать",
"criteria": { "доставка": "про заказ и сроки", "биллинг": "про деньги", "поддержка": "всё прочее" }
}
}
}'Ответ:
{
"model": "typesafe-ai/jev",
"answers": {
"urgent": { "type": "boolean", "probability": 0.85 },
"team": {
"type": "choice",
"choice": "доставка",
"probabilities": { "доставка": 1, "биллинг": 0, "поддержка": 0 },
"confidence": 0.99
}
},
"usage": { "input_tokens": 434, "output_tokens": 82 }
}Ключи ответов — ваши же имена вопросов. Ничего парсить не нужно.
Три вида вопросов
У каждого вида своя форма criteria
Это главная и единственная ловушка формата. Перепутать легко, ошибка приходит сразу и понятная.
boolean — да или нет
criteria — объект с двумя ключами:
"angry": {
"type": "boolean",
"question": "Клиент раздражён?",
"criteria": { "true": "резкий тон, требования", "false": "спокойный тон" }
}Возвращает probability от 0 до 1. Порог выбираете вы: 0.5 — обычный, 0.8 — когда ошибка дорога.
score — оценка по шкале
criteria — массив, от низшего к высшему:
"severity": {
"type": "score",
"question": "Насколько серьёзно",
"criteria": ["мелочь", "обычное", "критично"]
}Возвращает score, распределение probabilities по делениям и confidence.
choice — выбор одного из вариантов
criteria — объект: вариант и его описание.
"route": {
"type": "choice",
"question": "Кому отдать",
"criteria": { "поддержка": "общие вопросы", "биллинг": "про деньги", "инженер": "поломка" }
}Возвращает choice, распределение по всем вариантам и confidence.
Вместо критериев — инструкция
Для любого вида можно передать instructions строкой:
"ok": { "type": "boolean", "question": "Всё в порядке?", "instructions": "да, если жалоб нет" }Одно из двух — criteria или instructions — обязательно. Без них модель откажет.
Python
import httpx
r = httpx.post(
"https://nordrouter.com/v1/evaluate",
headers={"Authorization": "Bearer ВАШ-КЛЮЧ"},
json={
"model": "typesafe-ai/jev",
"state": ticket_text,
"questions": {
"spam": {"type": "boolean", "question": "Это спам?",
"criteria": {"true": "реклама или бессмыслица", "false": "живое обращение"}},
"topic": {"type": "choice", "question": "О чём обращение",
"criteria": {"оплата": "про деньги", "доступ": "не может войти",
"ошибка": "что-то сломалось"}},
},
},
timeout=40,
)
a = r.json()["answers"]
if a["spam"]["probability"] > 0.8:
drop(ticket)
else:
route_to(a["topic"]["choice"])Цена
| за 1 млн токенов | |
|---|---|
| вход | $0,0504 |
| выход | бесплатно |
Считается только то, что вы прислали. Ответ не тарифицируется вовсе.
Обращение из примера выше — 434 токена, то есть $0,0000219. Около 46 тысяч таких вызовов на один доллар.
Сколько списано за конкретный вызов, приходит в заголовке X-Charged-USD.
Ограничение частоты
Канал держит 15 запросов в секунду. Всё, что сверх, получает 429сразу — мы не держим ваш запрос в ожидании и не решаем за вас, сколько ему висеть. Вместе с отказом приходит заголовок Retry-After с числом секунд.
Повторы — на вашей стороне, и это намеренно: вы лучше знаете, что делать с конкретным вызовом — подождать, отложить или отбросить.
import time, httpx
def evaluate(payload, tries=3):
for _ in range(tries):
r = httpx.post(URL, headers=HDRS, json=payload, timeout=40)
if r.status_code != 429:
return r
time.sleep(int(r.headers.get("Retry-After", 1)))
return rДержите темп ниже потолка
Отказы ничего не стоят, но и пользы не приносят. Пятнадцать запросов в секунду ровным темпом дадут больше сделанной работы, чем сотня разом, из которой восемьдесят вернутся с 429.
Пределы и особенности
- Контекст — 32 000 токенов на
stateвместе с вопросами. - Потока (
stream) нет: ответ приходит целиком, обычно за 0,3–0,6 секунды. - Модель только эта. Запрос с другим именем вернёт
400. - Обычный
/v1/chat/completionsс ней не работает: это оценочная модель, у неё свой адрес/v1/evaluate.
Ключ и баланс
Ваш обычный ключ sk-nr-… и ваш обычный баланс. Ничего заводить не нужно: если вы уже пользуетесь NordRouter, оценочная модель доступна сразу.
Списания видны в кабинете вместе с остальными — отдельной бухгалтерии нет.
Ошибки
| код | что значит | что делать |
|---|---|---|
401 | ключ не принят | обычный sk-nr-…, проверьте, что он включён |
402 | на счёте пусто | пополнить |
400 | не та модель или форма вопроса | сверьтесь с формой criteria выше |
429 | превышен потолок частоты | подождать Retry-After секунд и повторить |
502 | модель временно недоступна | повторить через несколько секунд |