Загрузка...

System One API (Decisions API): что это и как работает

System One API (Decisions API) — это эндпоинт, который отправляет модели не запрос на генерацию текста, а состояние и набор типизированных вопросов, и получает обратно готовые ответы с вероятностями: да или нет, один из вариантов, оценку по шкале.

Обычная языковая модель пишет ответ токенами, а приложение потом пытается вытащить из этого текста решение. Модели класса decisions устроены иначе: они читают входные данные за один проход и возвращают вероятность для каждого допустимого ответа, не генерируя ни одного токена.

Откуда взялось название

Деление на две системы мышления — из психологии: быстрые интуитивные суждения и медленное рассуждение. В ИИ так стали называть два класса моделей. System Two — привычные генеративные модели, которые рассуждают и пишут связный текст. System One — модели, которые быстро выдают структурированное решение и на этом заканчивают.

Термин закрепила TypeSafe: в её документации System One описан как класс моделей, а Jev — первая модель этого класса. Liquid AI свои модели того же назначения называет просто decision models. В RouterAI оба названия обозначают одно и то же — эндпоинт, на который можно отправить decisions-модель.

Как это работает

Запрос состоит из двух частей. В state лежит то, что нужно оценить: строка, объект или массив, а модели с поддержкой изображений принимают ещё и картинки. В questions — именованные вопросы с типом и инструкцией. Имя вопроса придумывает разработчик: модель его не видит, ответ придёт под этим же ключом.

{
  "model": "liquid/d1.1",
  "state": "Клиент пишет, что деньги списались дважды.",
  "questions": {
    "refund_requested": {
      "type": "noul",
      "instructions": "Клиент прямо просит вернуть деньги?"
    }
  }
}

Типы вопросов:

Тип Что спрашиваем Что приходит в ответе
noul Да или нет? вероятность «да» от 0 до 1
choice Какой вариант из списка? победивший вариант, probabilities по всем вариантам, confidence
score Где на шкале? положение на шкале, probabilities по уровням, confidence
box Где объект на изображении? координаты рамки и confidence

У choice варианты задаются объектом «ключ — описание», у score — массивом уровней от 2 до 10. Все вопросы к одному state уходят одним запросом и обрабатываются параллельно, поэтому добавление вопросов почти не увеличивает время ответа.

Ответ приходит в поле answers, по ключу на каждый вопрос:

{
  "answers": {
    "is_urgent": { "type": "noul", "noul": 0.997 },
    "department": {
      "type": "choice",
      "choice": "billing",
      "confidence": 0.55,
      "probabilities": { "billing": 0.697, "technical": 0.298, "sales": 0.005 }
    },
    "frustration": {
      "type": "score",
      "score": 0.59,
      "confidence": 0.36,
      "probabilities": { "0": 0.418, "1": 0.575, "2": 0.007 },
      "legend": { "0": "Спокоен, просто описывает ситуацию", "1": "Раздражён, но вежлив", "2": "Очень зол, резкие выражения" }
    }
  },
  "usage": { "input_tokens": 224, "output_tokens": 0 }
}

Два поля стоит читать вместе со значением. confidence показывает, насколько модель уверена в победителе — низкое значение означает, что варианты близки. probabilities показывает, как распределились голоса: в примере выше биллинг выиграл, но техническая команда получила почти 30%, и такое обращение разумно отправить обоим адресатам.

Чем отличается от Chat Completions

  Chat Completions System One (Decisions)
Вход массив сообщений state и questions
Выход текст, который надо разобрать типизированные значения и вероятности
Откуда вероятность из вероятностей токенов, нередко после повторного вызова из модели напрямую, калибрована под варианты
Токены на выходе оплачиваются не генерируются, output_tokens равен нулю
Ответ вне списка вариантов возможен невозможен: выбор только из ваших вариантов
Форма ответа свободная одна из заранее заданных

Главное практическое отличие — предсказуемость. Текстовый ответ может не совпасть со схемой, а decisions-модель физически не может ответить тем, чего нет в списке. Ответ сразу ложится в if, порог или сортировку, и разбирать его регуляркой не нужно.

Вторая разница — цена и скорость. Тарифицируются только входные токены, выход бесплатен. Liquid AI на своей странице d1 приводит 200–300 мс на текстовое решение.

Есть и ограничение: decisions-модель нельзя вызвать через Chat Completions — запрос вернёт ошибку.

Ошибка 400 при вызове liquid/d1.1 через /api/v1/chat/completions
Попытка обратиться к decisions-модели как к чат-модели: RouterAI отвечает 400 и подсказывает нужный эндпоинт.

Модели в RouterAI

В каталоге RouterAI 29 карточек моделей с выходом decisions (считая алиас ~typesafe/jev-latest). Цены — в рублях за 1 млн входных токенов, по данным каталога.

Модель id Контекст Цена за 1 млн входных токенов Для чего
Joey 1 baseten/joey-1 16K 1,06 ₽ самый дешёвый вариант для массовых проверок
Clef Flash cloudflare/clef-flash 24K 1,91 ₽ быстрая классификация текста и изображений
d1.1 liquid/d1.1 64K 2,12 ₽ универсальный вариант: текст и картинки, понятная документация
Reflex morph/reflex 64K 4,46 ₽ повторные вопросы по одному состоянию благодаря кэшу
Jev 1.14 typesafe/jev-1.14 256K 4,46 ₽ длинные документы, все типы вопросов включая box

Разброс по цене внутри класса доходит до четырёх раз, поэтому модель выборки стоит подбирать под задачу, а не брать первую из списка. Чем крупнее модель и длиннее контекст, тем выше цена за токен.

Пример запроса

Эндпоинт: POST https://routerai.ru/api/v1/decisions. Синоним — /api/v1/systemone, он работает так же и возвращает тот же ответ. Модель, state и questions обязательны: без любого из них RouterAI ответит 400, не обращаясь к провайдеру.

import requests

resp = requests.post(
    "https://routerai.ru/api/v1/decisions",
    headers={"Authorization": "Bearer sk-xxxxxxxxxxxxxxxx"},
    json={
        "model": "liquid/d1.1",
        "state": "Здравствуйте! Третий день не могу подключить оплату на сайте — платежи клиентов не проходят, мы теряем заказы. Помогите, пожалуйста, срочно.",
        "questions": {
            "is_urgent": {
                "type": "noul",
                "instructions": "Клиент сообщает о срочной проблеме?",
            },
            "department": {
                "type": "choice",
                "instructions": "Какая команда должна заняться обращением?",
                "criteria": {
                    "billing": "Платежи, счета, возвраты, подписки",
                    "technical": "Ошибки, сбои, интеграции, настройка",
                    "sales": "Тарифы, покупка, вопросы до оплаты",
                },
            },
            "frustration": {
                "type": "score",
                "instructions": "Насколько раздражён клиент?",
                "criteria": [
                    "Спокоен, просто описывает ситуацию",
                    "Раздражён, но вежлив",
                    "Очень зол, резкие выражения",
                ],
            },
        },
    },
)

answers = resp.json()["answers"]
if answers["is_urgent"]["noul"] > 0.8:
    ticket.priority = "high"
route(answers["department"]["choice"])

Тот же запрос через curl:

curl -X POST "https://routerai.ru/api/v1/decisions" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json

На живом запросе с liquid/d1.1 та же фраза дала is_urgent 0,997, department — billing с вероятностью около 0,70 и frustration 0,59. Вероятности от прогона к прогону немного меняются, поэтому пороги подбирайте на своих данных.

Ответ /api/v1/decisions для liquid/d1.1: вероятности по вопросам noul, choice и score
Ответ на тот же запрос: срочность, отдел и раздражённость клиента в одном вызове. output_tokens=0 — текст модель не генерирует.

Где применяется

  • Маршрутизация запросов. Вопросы «какая это область?», «насколько сложная задача?» — и простые запросы уходят дешёвой модели, сложные — сильной. Логика выбора описана в статье про маршрутизацию ИИ-запросов.
  • Классификация. Тема обращения, отдел, язык, тип документа — задача choice с закрытым списком.
  • Guardrails. Проверка входящих и исходящих сообщений на инъекцию промпта, персональные данные, вредный запрос. Проверка стоит доли копейки рядом с вызовом модели, поэтому её можно ставить на каждое сообщение — см. Guardrails в ИИ.
  • Выбор действия в агенте. Когда агенту нужно решить, какой инструмент вызвать дальше, он получает список инструментов и возвращает один вариант — без текстовых рассуждений. Обвязку, в которой такой вызов живёт, разбирает статья про Agent Harness.

Связь с RouterAI

RouterAI отдаёт decisions-модели через тот же ключ и тот же баланс, что и Chat Completions: работа из России без VPN, оплата в рублях, отдельный аккаунт провайдера не нужен. Эндпоинт один, а модели — из общего каталога, где у каждой карточки указаны контекст и цена.

Полезное свойство каталога: если модель поддерживает только текст, а не изображения, это видно по характеристикам карточки ещё до запроса. Алиас ~typesafe/jev-latest всегда указывает на актуальную версию Jev, а в ответе поле model содержит датированный снимок, который обслужил запрос, — его стоит логировать, если вы подбирали пороги под конкретную версию.

Ограничения

  • Модель отвечает только вариантами из вашего списка: если ни один не подходит, она всё равно выберет ближайший. Для choice добавляйте вариант «ничего из перечисленного».
  • noul — не шкала: значение около 0,5 означает «модель не может решить», а не «средний уровень». Для уровня используйте score.
  • Ограничения запроса: 32 000 токенов на state и самый длинный вопрос, 64 000 токенов на state вместе со всеми вопросами, до 255 вариантов в одном choice.
  • Некоторые модели на входе принимают state любой длины, но фактически читают только начало — например, серии Clef на Workers AI обрезают текст примерно до первых 2K токенов.
  • Модель не объясняет решение. Если нужна причина отказа, спросите её отдельным вопросом choice с вариантами причин.

Что почитать