spicyapiДокументация
Текст и чат
Основное содержимое

Переход с OpenAI или OpenRouter

Как подключить существующий код с библиотеками OpenAI к SpicyAPI: базовый URL, ключ, ID модели, отличия полей запроса и настройки, которые нужно убрать после OpenRouter.

Если ваш код уже вызывает чат-модель через официальные библиотеки OpenAI или инструмент с настройкой «совместимость с OpenAI», для перехода на SpicyAPI нужно изменить три значения: базовый URL, API-ключ и ID модели. На этой странице перечислены эти изменения и отличия в поведении, чтобы после миграции вы не столкнулись с неожиданным 400. Полные примеры программ — в разделе Примеры для чата.

Три изменения

НастройкаЗначение для SpicyAPI
Базовый URLhttps://api.spicyapi.ai/v1
API-ключКлюч SpicyAPI (начинается с sk-spicy-), передаваемый как Authorization: Bearer
МодельТочный ID текстовой модели из актуального каталога, например в SPICY_MODEL (см. ID моделей)
import os
from openai import OpenAI

# Before: client = OpenAI()   (reads OPENAI_API_KEY, calls api.openai.com)
client = OpenAI(api_key=os.environ["SPICY_API_KEY"], base_url="https://api.spicyapi.ai/v1")

reply = client.chat.completions.create(
    model=os.environ["SPICY_MODEL"],
    messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(reply.choices[0].message.content)

Библиотеки OpenAI также читают OPENAI_BASE_URL и OPENAI_API_KEY из окружения. Если задать эти переменные, существующий код заработает без изменений, но это перенаправит и все остальные вызовы OpenAI в том же процессе. Поэтому лучше передавать значения явно, как в примерах выше.

ID моделей

ID текстовых моделей имеют вид publisher/model/chat. Копируйте их из актуального каталога, а не преобразуйте знакомое название с другого сервиса:

  • GET /api/v1/models?modality=text перечисляет только текстовые модели с ценами и добавляет для каждой модели inputSchema при includeSchema=1. См. Каталог моделей и схемы.
  • GET /v1/models — список в формате OpenAI, который читают инструменты. Без фильтра он включает модели изображений, видео и аудио, которые нельзя вызывать на /v1/chat/completions; добавьте ?modality=text, чтобы получить только текстовые. Помимо четырёх полей OpenAI, каждый элемент содержит modality и task, а чат-модели — также context_length, max_output_tokens и supported_parameters (поля запроса, принимаемые моделью). Библиотеки OpenAI игнорируют дополнительные поля.

Несуществующий ID модели возвращает 404 с code: "model_not_found" и param: "model". Сообщение показывает формат ID и, если такой вариант есть, ближайшую доступную чат-модель. Вызов модели изображений или видео на чат-эндпоинте возвращает 400 с указанием, что это не чат-модель. ID других сервисов часто выглядят похоже, но не взаимозаменяемы: названия разработчиков могут писаться иначе, суффиксов вроде :free здесь нет, а текстовые модели заканчиваются на /chat.

Поля запроса

Каждая модель публикует принимаемые поля в своей inputSchema (а их названия — в supported_parameters на /v1/models).

  • Параметры сэмплирования, которых нет в списке модели, игнорируются. temperature, top_p, top_k, min_p, top_a, frequency_penalty, presence_penalty и repetition_penalty меняют только случайность или повторяемость ответа. Многие клиенты передают их по умолчанию, поэтому модель, которая их не принимает, просто генерирует без них. То же относится к n: 1, пустому stop, полю stop у модели без стоп-последовательностей и reasoning_effort у модели без уровней рассуждения. Ответ перечисляет проигнорированные поля в заголовке X-Spicy-Ignored-Params, например frequency_penalty, presence_penalty.
  • Значения вне допустимого диапазона заменяются ближайшим допустимым значением. Параметр сэмплирования за пределами диапазона модели ограничивается его границей; слишком длинный список stop сохраняет первые элементы; отсутствующий у модели уровень reasoning_effort заменяется ближайшим доступным (при равном расстоянии — меньшим). Ответ перечисляет изменения как name=value в заголовке X-Spicy-Adjusted-Params, например reasoning_effort=low, temperature=1.
  • Любое другое поле, которого нет в списке модели, отклоняется с 400, code: "unsupported_parameter", полем param, указывающим на него, и сообщением с его названием, например logprobs: is not a supported field. Эти поля меняют состав результата, поэтому вы не оплачиваете ответ, созданный без настройки, которую считали переданной.
ПолеПоведение в SpicyAPI
messagesТот же формат. Роли system, developer, user, assistant и tool. Текст работает везде; части image_url — только у моделей, схема которых их предусматривает
max_tokens, max_completion_tokensПринимаются оба с одинаковым значением. Токены рассуждения входят в этот лимит. У каждой модели свои значение по умолчанию и верхняя граница
stream, stream_optionsПоддерживаются с правилами использования токенов OpenAI: поток содержит данные об использовании только при include_usage, равном true (см. Ответы и потоки)
tools, tool_choiceПоддерживаются всеми текстовыми моделями. Некоторые модели принимают только auto и none для tool_choice; принудительный выбор конкретного инструмента у них возвращает 400
parallel_tool_callsТолько у моделей, в списке которых есть это поле
reasoning_effortУ большинства моделей, но допустимые значения зависят от модели: некоторые добавляют none, minimal, xhigh или max, а у некоторых нет medium. Недоступное значение заменяется ближайшим доступным, поэтому при важности точного уровня прочитайте enum модели
temperature, top_p, top_k, frequency_penalty, presence_penaltyИспользуются у моделей, в списке которых есть эти поля, с ограничением значений диапазоном модели; у остальных игнорируются (перечисляются в X-Spicy-Ignored-Params). Некоторые модели не принимают ни одного параметра сэмплирования
seedТолько у моделей, в списке которых есть это поле
stopИспользуется у моделей, в списке которых есть это поле; обрезается до максимального числа элементов модели. Игнорируется у моделей без стоп-последовательностей и при пустом значении
response_formatjson_object у моделей, в списке которых есть это поле; у остальных недоступно
user, metadata, storeПринимаются и игнорируются
n1 игнорируется; любое другое значение возвращает 400 у моделей, в списке которых нет этого поля
logprobs, top_logprobs, logit_bias и любое другое поле, которого нет в списке моделиОтклоняются с 400

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

Ответы и потоки

Ответ без потоковой передачи — обычный объект chat.completion, поэтому reply.choices[0].message.content и reply.usage работают как прежде. Отличий немного:

  • reasoning_content. Модели, которые рассуждают перед ответом, возвращают этот текст в message.reasoning_content (или delta.reasoning_content при потоковой передаче), рядом с content. Он уже учтён в usage.completion_tokens.
  • ID — это ID запроса. id имеет вид chatcmpl-req_..., а заголовок ответа x-request-id содержит то же значение req_.... Укажите его при обращении в поддержку. Второй заголовок, X-Spicy-Task-Id, указывает задачу, в которой учтена оплата (см. Стоимость и использование).
  • Нет system_fingerprint и logprobs.

Потоки используют те же события chat.completion.chunk, завершаются строкой data: [DONE] и следуют правилам OpenAI для данных об использовании:

  • Данные об использовании только по запросу. Без stream_options.include_usage ни один фрагмент не содержит usage, и у каждого непустой список choices. При "include_usage": true дополнительный фрагмент с пустым choices и итоговым usage приходит непосредственно перед [DONE]; у всех остальных фрагментов — usage: null. Код на основе примеров потоковой передачи OpenAI работает без изменений; проверка choices перед чтением choices[0] защищает от ошибки на последнем фрагменте.
  • Один finish_reason на каждый вариант ответа. Каждый вариант завершается ровно одним фрагментом с его finish_reason, независимо от модели.
  • Строки поддержания соединения. Пока модель рассуждает, поток передаёт строки-комментарии : keep-alive, чтобы соединение оставалось открытым. Библиотеки OpenAI их пропускают; собственный парсер должен делать то же.

Для длинных ответов или высокого reasoning_effort используйте потоковую передачу. Если запрос без потока выполняется дольше примерно 30 секунд, соединение поддерживается пробельными символами перед JSON-телом и заголовком X-Spicy-Keepalive: 1, поэтому библиотеки OpenAI по-прежнему разбирают ответ. Но при последующей ошибке её объект приходит в теле ответа 200, который библиотеки не считают ошибкой. См. Тайм-ауты и потоковая передача.

Ошибки

Ошибки используют формат OpenAI, {"error": {"message", "type", "param", "code"}}, и обычные HTTP-статусы, поэтому библиотеки OpenAI вызывают стандартные исключения. Поле param указывает на проблемное поле в виде пути через точки, например temperature или messages.1.content.0; code различает ошибки с одинаковым статусом: unsupported_parameter (поле или часть сообщения, которую модель не принимает), invalid_request (отсутствующее поле или недопустимое значение), content_rejected (отказ по правилам контента, также 400) и model_not_found (404). Одно отличие от OpenAI: 402 используется, когда баланс или лимит расходов не покрывает запрос. Полная таблица с действиями для каждого кода — в разделе Примеры для чата: если что-то пошло не так.

Библиотеки OpenAI самостоятельно повторяют запросы после ответов 429 и 5xx. Здесь это безопасно: неудавшийся запрос не оплачивается. Если передаёте Idempotency-Key, задавайте его для каждого вызова отдельно и сначала прочитайте Ключи идемпотентности на текстовых эндпоинтах.

Стоимость и использование

Ответы показывают число токенов в usage, а не цену. Цены за миллион входных, кешированных входных и выходных токенов указаны на странице каждой модели и в каталоге. Чтобы узнать фактическую стоимость вызова, прочитайте заголовок ответа X-Spicy-Task-Id (job_…), присутствующий в каждом принятом запросе — потоковом или обычном, — и найдите задачу через GET /api/v1/jobs/recordInfo?taskId=<job_…>. Поле cost становится итоговым, когда settled равно true. Элементы GET /api/v1/jobs также содержат requestId создавшего их вызова (заголовок X-Request-Id), а раздел Консоль → Логи показывает те же задачи. Как прочитать заголовок через библиотеки OpenAI — в разделе Примеры для чата: узнать стоимость вызова; см. также Расчёт цены и оплата.

Перед выполнением запроса из баланса резервируется сумма, покрывающая сообщения и весь объём выходных токенов max_tokens (значение по умолчанию модели, если поле не задано). Вы платите только за фактически использованные токены, но сначала должна помещаться вся резервируемая сумма. Поэтому небольшой баланс вместе с большим max_tokens приводит к 402. Задайте реалистичный max_tokens или настройте лимиты расходов ключа; см. Оплата.

Эндпоинты, которых здесь нет

Генерация текста доступна в форматах OpenAI Chat Completions, OpenAI Responses, Anthropic Messages и Google Gemini; подробности — в разделе Текст и потоковые ответы. Следующие эндпоинты OpenAI отсутствуют и возвращают 404: /v1/embeddings, устаревший /v1/completions, /v1/images/*, /v1/audio/*, /v1/moderations, /v1/files, /v1/batches, /v1/assistants, а также дообучение. Модели изображений, видео и аудио вызываются через API задач, а видео — также через /v1/videos.

Переход с OpenRouter

OpenRouter также использует формат OpenAI, поэтому действуют те же три изменения: замените базовый URL https://openrouter.ai/api/v1 на https://api.spicyapi.ai/v1, а также ключ и ID моделей. Затем уберите поля, существующие только в OpenRouter: здесь они возвращают 400:

Поле OpenRouterЧто делать
models (список резервных моделей) и routeУдалить. Передавайте один ID модели; SpicyAPI выбирает способ его обслуживания
providerУдалить. Выбирать провайдера для отдельного запроса нельзя
reasoning (объект вроде {"effort": "high"})Преобразуется в верхнеуровневое reasoning_effort (enabled: false становится none, если модель его поддерживает); остальные ключи внутри игнорируются. Явная передача reasoning_effort понятнее
usage ({"include": true})Удалить. Обычные ответы всегда содержат usage; для потоков передавайте stream_options: {"include_usage": true}
transforms, pluginsУдалить

Заголовки HTTP-Referer и X-Title безвредны и игнорируются.

Контрольный список

  1. Базовый URL — https://api.spicyapi.ai/v1, ключ — SpicyAPI.
  2. ID модели скопирован из актуального каталога и заканчивается на /chat.
  3. Поля запроса сверены с inputSchema модели; неподдерживаемые поля, не относящиеся к сэмплированию, удалены. Заголовки ответа X-Spicy-Ignored-Params и X-Spicy-Adjusted-Params проверены хотя бы один раз, чтобы увидеть изменения.
  4. При передаче stream_options.include_usage цикл обработки потока пропускает последний фрагмент с пустым списком choices.
  5. Для max_tokens задано реалистичное значение либо оставлено значение по умолчанию модели; на ключе настроены лимиты расходов.
  6. Длинные запросы или запросы с высоким уровнем рассуждения используют stream: true.

Дополнительные материалы

Примеры для чата · Текст и потоковые ответы · Каталог моделей и схемы · Аутентификация · Оплата

На этой странице