Справочник API

Два эндпоинта, три формы вопроса

Сервис поднимается у вас и считает решения на месте. Ниже полное описание запроса и ответа: все поля, все типы вопросов, пороги и коды ошибок. Описано по коду сервиса, а не по намерениям.

Запуск

Сервис это одно приложение FastAPI. Веса подхватываются из каталога модели, путь задаётся переменной окружения. По умолчанию берётся собранная модель рядом с кодом.

pip install -r serve/requirements.txt
export RU_JEV_MODEL=/path/to/ru-jev
uvicorn serve.app:app --host 0.0.0.0 --port 8080

Устройство выбирается само: видеокарта, если она есть, иначе процессор. Температура и длина контекста читаются из calibration.json в каталоге модели, задавать их в запросе не нужно.

Запрос

POST /v1/systemone
ПолеОписание
stateобязательноеТекст, по которому принимается решение. Строка берётся как есть. Список склеивается через перевод строки, у элементов-объектов берётся поле text, иначе value. Любая другая структура сериализуется в JSON.
questionsобязательноеОбъект, где ключ это ваш идентификатор вопроса, а значение описывает вопрос. Идентификаторы возвращаются в ответе без изменений, так что по ним удобно раскладывать результат.
modelнеобязательноеИмя модели. По умолчанию ru-jev-latest. Сервис возвращает его обратно и ничего по нему не переключает: веса заданы при запуске.
thresholdнеобязательноеПорог уверенности на весь запрос, от 0 до 1. Ответы ниже порога помечаются как отклонённые. Если поле не задано, не отклоняется ничего.

Поля вопроса

ПолеОписание
typeобязательноеОдно из boolean, choice, score. Другое значение даёт ошибку 400.
criteriaВарианты ответа. Формат зависит от типа и описан ниже. Для choice и score поле обязательно и не может быть пустым.
instructionsнеобязательноеСтрока, которая подставляется перед текстом через перевод строки. Так задаётся, что именно оценивать, если один и тот же текст разбирается с нескольких сторон.
thresholdнеобязательноеПорог для этого вопроса. Перекрывает порог запроса.

Вопрос boolean

Да или нет. criteria необязательно: если передать объект с ключами true и false, этими словами и будут названы варианты. Без него берутся «да» и «нет».

Формулировка варианта влияет на результат, потому что модель читает её текст. Называйте варианты обычными словами по смыслу категории.

"questions": {
  "tox": {
    "type": "boolean",
    "criteria": { "true": "токсичный", "false": "нормальный" }
  }
}

В ответе приходит probability, вероятность первого варианта. Уверенность считается как расстояние от половины, то есть большее из p и 1 - p.

Вопрос choice

criteria это объект: ключ возвращается как выбранный вариант, значение это текст, который читает модель. Ключи удобно делать машинными, а значения человеческими.

"questions": {
  "route": {
    "type": "choice",
    "criteria": {
      "billing": "оплата, счета и возвраты",
      "tech":    "техническая проблема",
      "sales":   "вопрос о покупке"
    }
  }
}

Возвращается choice с лучшим ключом и probabilities по всем ключам. Сумма вероятностей равна единице: модель выбирает из того, что вы дали, и не может сказать, что не подходит ничего. Если такой исход возможен, добавьте отдельный вариант для него.

Вопрос score

criteria это список уровней по порядку, от нижнего к верхнему. Возвращается score, среднее по распределению, то есть дробное значение между индексами, и probabilities по номерам уровней.

"questions": {
  "ton": {
    "type": "score",
    "criteria": ["негативный", "нейтральный", "позитивный"]
  }
}

Значение 1.97 при трёх уровнях означает почти уверенный верхний уровень. Уверенность для порога берётся как вероятность самого вероятного уровня, а не как близость к краю шкалы.

Ответ

{
  "model": "ru-jev-latest",
  "answers": {
    "ton": {
      "type": "score",
      "score": 1.97,
      "probabilities": { "0": 0.008, "1": 0.009, "2": 0.982 }
    }
  },
  "usage": { "input_tokens": 14, "output_tokens": 0 },
  "providerMetadata": {
    "ru_jev": { "confidence": { "ton": 0.982 }, "review": [] }
  }
}
ПолеОписание
answersОтвет на каждый вопрос под тем же идентификатором, что и в запросе.
usageЧисло токенов во входном тексте. Выходных токенов нет: модель не порождает текст, поэтому там всегда ноль.
providerMetadata.ru_jev.confidenceУверенность по каждому вопросу, от 0 до 1. Это та величина, с которой сравнивается порог.
providerMetadata.ru_jev.reviewСписок идентификаторов, по которым ответ отклонён порогом и нужен человек. Пустой, если порог не задан.

Порог и отказ

Порог задаётся на весь запрос полем threshold либо отдельно у вопроса, и вопрос перекрывает запрос. Когда порог задан, у каждого ответа появляется поле abstain, а идентификаторы отклонённых собираются в review.

{
  "state": "Списали дважды за один заказ.",
  "threshold": 0.8,
  "questions": { "route": { "type": "choice", "criteria": { ... } } }
}

Чем выше порог, тем меньше решений уходит без человека и тем точнее то, что ушло. Эта зависимость замерена и показана на главной странице.

Проверка живости

GET /health

Загружает модель, если она ещё не загружена, и возвращает её параметры. Удобно вызывать после старта, чтобы первый рабочий запрос не ждал загрузку весов.

{
  "status": "ok",
  "model": "/opt/ru-jev",
  "device": "cpu",
  "max_len": 256,
  "temperature": 1.864
}

Ошибки

КодКогда
400Тип вопроса не поддерживается.
400У вопроса choice поле criteria отсутствует или пусто.
400У вопроса score поле criteria не список или пусто.
422Тело запроса не разбирается: нет state или questions, либо неверные типы.

Текст причины приходит в поле detail и называет идентификатор вопроса.