Документация

Модели решений

Модель решений получает данные и вопросы с вариантами ответа, а возвращает выбранный вариант и вероятность каждого. Вызывается она одним запросом на адрес /v1/decisions: ответ приходит на этот же запрос, задачу ставить и опрашивать не нужно. Поставщик — TypeSafe AI.

Модели

Идентификатор Модель Страница на сайте
jev/1-14 Jev 1.14 Открыть
jev/1-13 Jev 1.13 Открыть

Попробовать

Input

Войдите и получите 50 кредитов на тесты и любое использование сервиса. Без регистрации доступно 10 запусков в сутки.

Output

Нажмите «Запустить» — ответы модели появятся здесь

{ }

Вызов

POST https://api.gen202.com/v1/decisions

Адрес один, и ответ приходит на этот же запрос. Ключ передаётся заголовком Authorization: Bearer sk-… и выпускается в кабинете. На один ключ шлюз пропускает 600 запросов в минуту.

Счёт идёт по входным токенам из поля usage ответа: это данные и вопросы вместе. Ответ модели бесплатный. Кредиты списываются после ответа, по факту; за один запрос списывается не меньше 0,02 кредита. Сколько списано, приходит в ответе полем credits_consumed. Запрос, не дошедший до ответа, не тарифицируется.

Поля запроса

Формат тот же, что у разработчика модели: три поля. Данные и вопросы вместе — до 262 144 токенов. В одном запросе можно задать несколько вопросов об одних данных: модель отвечает на каждый отдельно.

ПолеТипОбяз.Что в нём
model текст обязательное jev/1-14
state текст, объект или список обязательное Данные, о которых модель выносит решение: письмо, отзыв, запись из базы; картинки — частью image_url, как в документации
questions объект обязательное Вопросы: имя вопроса и его описание. Имя вы выбираете сами, под ним придёт ответ
questions.*.type текст обязательное Вид вопроса: choice — один из вариантов, noul — да или нет, score — место на шкале, box — где на картинке предмет (вопрос box)
questions.*.instructions текст, объект или список обязательное Сам вопрос. Текстом — когда хватает одной фразы. Объектом или списком — когда к вопросу нужны пояснения или данные, на которые он ссылается
questions.*.criteria объект обязательное У choice — варианты ответа: имя варианта и его описание. Описание — текст, объект, список или null, когда пояснять нечего. До 255 вариантов
questions.*.criteria список обязательное У score — ступени шкалы от низшей к высшей. Ступень — текст, объект или список. До 10 ступеней
questions.*.criteria объект необязательное У noul — что считать ответом «да» и что ответом «нет»: поля true и false, оба сразу

Вопрос объектом — пример из справки разработчика: сам вопрос лежит в одном поле, данные — в соседнем, и вопрос ссылается на них по имени в обратных кавычках.

instructions.json
"instructions": {
  "potential_duplicate": {
    "name": "John Smith",
    "location": "Oakland, California",
    "last_employer": "Google"
  },
  "question": "Is the resume for the same person as `potential_duplicate`?"
}

Вызов

Запрос показан целиком, с именем этой модели и тремя вопросами разного вида: подставить остаётся только свой ключ.

decisions.sh
curl https://api.gen202.com/v1/decisions \
  -H "Authorization: Bearer sk-ваш-ключ" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jev/1-14",
    "state": "Help! My payouts have been failing for 3 days.",
    "questions": {
      "is_urgent": {
        "type": "noul",
        "instructions": "Does this convey urgency?",
        "criteria": {
          "true": "Explicitly time-sensitive",
          "false": "No urgency expressed"
        }
      },
      "department": {
        "type": "choice",
        "instructions": "Which team should handle this?",
        "criteria": {
          "billing": "Payments, invoicing, refunds",
          "technical": "Bugs, outages, integrations",
          "sales": "Pricing, upgrades, new accounts"
        }
      },
      "frustration": {
        "type": "score",
        "instructions": "How frustrated is the customer?",
        "criteria": ["Calm", "Frustrated", "Very angry"]
      }
    }
  }'
decisions.py
import requests

answer = requests.post(
    "https://api.gen202.com/v1/decisions",
    headers={"Authorization": "Bearer sk-ваш-ключ"},
    json={
        "model": "jev/1-14",
        "state": "Help! My payouts have been failing for 3 days.",
        "questions": {
            "is_urgent": {
                "type": "noul",
                "instructions": "Does this convey urgency?",
                "criteria": {
                    "true": "Explicitly time-sensitive",
                    "false": "No urgency expressed",
                },
            },
            "department": {
                "type": "choice",
                "instructions": "Which team should handle this?",
                "criteria": {
                    "billing": "Payments, invoicing, refunds",
                    "technical": "Bugs, outages, integrations",
                    "sales": "Pricing, upgrades, new accounts",
                },
            },
            "frustration": {
                "type": "score",
                "instructions": "How frustrated is the customer?",
                "criteria": ["Calm", "Frustrated", "Very angry"],
            },
        },
    },
).json()

print(answer["answers"]["department"]["choice"])  # billing
print(answer["usage"])  # по нему выставлен счёт

Ответ

Ответ на запрос выше, каким он пришёл от модели: под именем каждого вопроса — его ответ.

decisions-response.json
{
  "model": "jev/1-14",
  "answers": {
    "is_urgent": { "type": "noul", "noul": 0.95 },
    "department": {
      "type": "choice",
      "choice": "billing",
      "probabilities": { "billing": 0.86, "technical": 0.14, "sales": 0 },
      "confidence": 0.79
    },
    "frustration": {
      "type": "score",
      "score": 1.05,
      "legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" },
      "probabilities": { "0": 0, "1": 0.95, "2": 0.05 },
      "confidence": 0.93
    }
  },
  "usage": { "input_tokens": 426, "output_tokens": 73 },
  "credits_consumed": 0.02
}
ПолеТипЧто в нём
model текст Имя модели, как в запросе
answers объект Ответы: под именем каждого вопроса — его ответ
answers.*.type текст Вид вопроса: noul, choice, score или box
answers.*.noul число У noul — вероятность ответа «да», от 0 до 1
answers.*.choice текст У choice — вариант с наибольшей вероятностью
answers.*.score число У score — место на шкале, взвешенное по вероятностям ступеней; может лежать между ступенями
answers.*.legend объект У score — номер ступени и её описание из запроса
answers.*.probabilities объект У choice и score — вероятность каждого варианта или ступени, в сумме 1
answers.*.confidence число У choice и score — уверенность модели, от 0 до 1; считается из вероятностей. У box — уверенность в рамке, от 0 до 1
answers.*.box объект У box — края рамки top, bottom, left, right: доли высоты и ширины картинки от 0 до 1, считая от левого верхнего угла
usage.input_tokens целое Токены данных и вопросов. По ним выставлен счёт
usage.output_tokens целое Токены ответа. Не тарифицируются
credits_consumed число Сколько кредитов списано за запрос

Отказы

Тело отказа — объект error, как у OpenAI: {"error":{"message":…,"type":…,"code":…,"param":null}}. Ни один из этих отказов не тарифицируется: деньги списываются только после ответа модели.

КодcodeКогда
400 model_not_found Имени из поля model нет среди моделей решений. В сообщении перечислено, что принимается.
400 invalid_state Поле state не передано или пустое. Данные принимаются строкой, объектом или списком.
400 invalid_questions Поле questions не передано или пустое, либо вопрос задан не по схеме: не назван вид (choice, noul, score, box), пустое поле instructions, у choice нет объекта вариантов или их больше 255, у score нет списка ступеней или их больше 10, у noul в criteria нет одного из полей true и false. Тот же отказ приходит на вопрос box к модели, которая на него не отвечает: box отвечает только jev/1-14. В сообщении назван сам вопрос.
400 invalid_image Картинка передана не так: ссылкой http(s), в формате кроме PNG и JPEG, строкой base64 без приставки data:image/…;base64, частью input_image или полями assets и images. В сообщении названо место в запросе и показано, как передать картинку.
400 key_required Названный заголовком учёта ключ не принадлежит аккаунту или отключён. При вызове по ключу Bearer такого отказа не бывает.
400 invalid_request Модель отказала по самому запросу. В сообщении — её слова. Запрос не тарифицируется.
401 invalid_api_key Ключа нет в заголовке Authorization, либо он неверный или отключён.
402 insufficient_credits На балансе не осталось свободных кредитов. Перед вызовом шлюз проверяет только это — сумма списывается после ответа, по факту.
403 forbidden Аккаунт заблокирован: вызовы модели, пополнение и загрузка файлов ему закрыты. Ключи при этом не отключены — запрет лежит на аккаунте.
413 invalid_request Запрос слишком велик для модели. Запрос не тарифицируется.
422 invalid_request Модель не смогла обработать запрос в таком виде. В сообщении — её слова. Запрос не тарифицируется.
429 concurrent_request Другой запрос этого аккаунта ещё считается. Пока на балансе 50 кредитов или меньше, текстовые запросы выполняются по одному: списание приходит после ответа, и одновременные запросы увели бы счёт в минус. Дождитесь ответа или пополните баланс.
502 upstream_error Поставщик не ответил или ответил ошибкой. Запрос не тарифицируется: списывать нечего, ответа не было.
503 service_overloaded Поставщик перегружен или отбил запрос по своему лимиту. Запрос не тарифицируется, повторить можно через несколько секунд — срок назван в заголовке Retry-After.

Сверх 600 запросов в минуту с одного ключа шлюз отвечает 429 в своём виде: {"statusCode":429,"error":…,"message":…} — объекта error в таком ответе нет.

Картинки

Картинки принимают обе модели решений — jev/1-14 и jev/1-13. Картинку кодируют в base64 и кладут в state частью image_url рядом с текстом. Отвечают по картинке вопросы всех видов, а вопрос box находит на ней нужный предмет.

Запрос с картинкой

Фотография читается с диска, кодируется в base64 и подставляется в поле url. Вопросы ссылаются на картинку по имени поля в обратных кавычках.

decisions-image.sh
IMAGE=$(base64 < photo.jpg | tr -d '\n')

curl https://api.gen202.com/v1/decisions \
  -H "Authorization: Bearer sk-ваш-ключ" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "model": "jev/1-14",
  "state": {
    "listing": "Photo from a listing.",
    "photo": { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,$IMAGE" } }
  },
  "questions": {
    "animal": { "type": "noul", "instructions": "There is a cat in \`photo\`." },
    "face": { "type": "box", "instructions": "the cat's face in \`photo\`" }
  }
}
EOF

Ответ — под именем каждого вопроса. Поля usage и credits_consumed приходят те же, что в ответе выше, и здесь опущены.

decisions-image-response.json
{
  "model": "jev/1-14",
  "answers": {
    "animal": { "type": "noul", "noul": 0.95 },
    "face": {
      "type": "box",
      "box": { "top": 0.29, "bottom": 0.47, "left": 0.45, "right": 0.61 },
      "confidence": 0.86
    }
  }
}

Числа — из нашего запроса 17 октября 2026 года с фотографией 900 × 900 пикселей в JPEG. В том запросе стоял ещё вопрос choice, и весь запрос — фотография, подпись и три вопроса — занял 2 597 входных токенов.

Как передать картинку

  • Картинка — объект {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,…"}}.
  • В url стоит строка base64 с приставкой data:image/png;base64, или data:image/jpeg;base64,. Принимаются PNG и JPEG. Ссылки http(s) не скачиваются.
  • Картинка лежит в state на любой глубине: элементом списка или значением поля объекта. Её можно положить и в вопрос — в instructions или в описание варианта в criteria.
  • Картинка в instructions уходит модели с каждым вопросом, в котором стоит, и каждый раз считается в токены. Картинку, нужную нескольким вопросам, кладут в state один раз и называют по имени поля.
  • Текст рядом с картинкой — обычные строки, а не части {"type": "text"}.
  • Вопрос box отвечает только jev/1-14.

Картинкой не считаются:

  • поле images на верхнем уровне запроса;
  • поле assets;
  • часть input_image;
  • строка base64 без приставки data:image/…;base64, — прямо в state модель прочтёт её как текст;
  • картинка WebP, GIF или в другом формате, кроме PNG и JPEG.

На поля images и assets, на часть input_image и на часть image_url со ссылкой, другим форматом или строкой без приставки шлюз отвечает 400 invalid_image. В сообщении названо место в запросе.

Пределы картинок

ПределЗначение
ФорматPNG или JPEG, только неподвижные: анимированный PNG модель отклоняет
Ширина и высотаОт 280 до 1568 пикселей каждая
Пикселей всегоОт 78 400 до 2 458 624 — площадь квадрата от 280 × 280 до 1568 × 1568
Файл картинкиДо 16 МиБ после раскодирования base64
Тело запросаДо 20 МиБ вместе со строками base64
ОкноКартинки считаются входными токенами и вместе с данными и вопросами входят в 262 144 токенов
  • Картинку за этими пределами модель отклоняет, а не уменьшает, и тогда не проходит весь запрос: меньше нижней границы — 400 invalid_request, больше верхней — 413 invalid_request, оба со словами модели.
  • Поворот из EXIF модель не применяет: фотографию поворачивают до кодирования.
  • Картинка оплачивается входными токенами по ставке модели, отдельной платы за неё нет. Сколько токенов ушло, показывает usage.input_tokens.

Каждый запрос с картинкой модель обрабатывает в режиме длинного контекста, а этот режим, по словам разработчика, медленнее и менее точен.

Картинки и вопрос box разработчик помечает как раннюю возможность: формат запроса, ответы и пределы могут меняться от выпуска к выпуску.

Вопрос box

Вопрос box находит на картинке один предмет и отвечает рамкой вокруг него — четырьмя краями в долях ширины и высоты картинки — и уверенностью. Отвечает на него только jev/1-14: такой вопрос к jev/1-13 шлюз отклоняет сам, отказом 400 invalid_questions. В одном запросе box стоит рядом с вопросами других видов, и все они относятся к одним данным.

Поля вопроса

ПолеТипОбяз.Что в нём
questions.*.type текст обязательное box
questions.*.instructions текст, объект или список обязательное Что найти и на какой картинке. Пишется описанием предмета, а не командой: the cat's face in `photo`
questions.*.criteria — не задаётся Вариантов у box нет, и это поле модель не читает
box-request.json
{
  "model": "jev/1-14",
  "state": {
    "listing": "Photo from a listing.",
    "photo": { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,/9j/4AAQ..." } }
  },
  "questions": {
    "face": { "type": "box", "instructions": "the cat's face in `photo`" }
  }
}

Ответ

Края рамки лежат в поле box. Ответ — из того же нашего запроса.

box-answer.json
"face": {
  "type": "box",
  "box": { "top": 0.29, "bottom": 0.47, "left": 0.45, "right": 0.61 },
  "confidence": 0.86
}
ПолеТипЧто в нём
answers.*.type текст box
answers.*.box.top, bottom число Верхний и нижний края — доли высоты картинки от 0 до 1, считая сверху. top меньше bottom
answers.*.box.left, right число Левый и правый края — доли ширины картинки от 0 до 1, считая слева. left меньше right
answers.*.confidence число Уверенность модели в рамке, от 0 до 1

Как прочитать рамку

Чтобы обрезать картинку по рамке или нарисовать её, каждый край умножают на ширину или высоту картинки в пикселях. На фотографии 900 × 900 рамка из ответа выше — это прямоугольник от 405 до 549 пикселей по ширине и от 261 до 423 по высоте.

crop.py
from PIL import Image

image = Image.open("photo.jpg")
width, height = image.size
edges = answer["answers"]["face"]["box"]

box = (
    round(edges["left"] * width),
    round(edges["top"] * height),
    round(edges["right"] * width),
    round(edges["bottom"] * height),
)
image.crop(box).save("face.jpg")

Ответа «не найдено» у box нет: рамка приходит, даже когда предмета на картинке нет. В нашем запросе без картинки box вернул рамку с уверенностью 0,03. Поэтому в тот же запрос ставят вопрос noul — есть ли предмет на картинке — и рамку не берут, когда вероятность «да» низкая.

  • Один вопрос box — одна рамка. Несколько предметов ищут несколькими вопросами в одном запросе.
  • Если похожих предметов несколько, нужный описывают так, чтобы подходил только он: the mug nearest the sink in `photo`.
  • Мелкий предмет на большой картинке модель может пропустить. Сначала находят нужную часть картинки — например, вопросом choice, где варианты — части картинки, — и задают box уже по ней.
  • Порог уверенности разработчик советует подбирать на своих картинках. При низкой уверенности спрашивают снова по картинке крупнее или расширяют рамку перед обрезкой.

Сколько стоит Jev 1.14

Jev 1.14. Цена за миллион токенов — за входные токены: данные и вопросы. Ответ модели бесплатный.

Токены Наша цена
Вход 18.59 кр. $0.08459,29 ₽
Выход бесплатно

кр. — кредиты, покупаются за рубли.

Jev 1.13. Цена за миллион токенов — за входные токены: данные и вопросы. Ответ модели бесплатный.

Токены Наша цена
Вход 18.59 кр. $0.08459,29 ₽
Выход бесплатно

кр. — кредиты, покупаются за рубли.

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