OpenAI SDK для DeepSeek, Qwen и Doubao: меняем base_url
5 мин чтенияАвтор genmux API Team
Если в вашем коде уже есть openai.chat.completions.create(...), переход на DeepSeek, Qwen3 или Doubao через genmux — это изменение в две строки: укажите base_url на https://api.genmux.tech/v1 и замените ключ. Всё остальное — форма запроса, форма ответа, стриминг — остаётся прежним. Этот пост — справочник по полям: что здесь реально означает «совместимо с OpenAI». (GLM и Kimi временно исключены из линейки, пока вендор не починит апстрим — а список моделей тем временем продолжает расти.)
Миграция в две строки
from openai import OpenAI
client = OpenAI(
base_url="https://api.genmux.tech/v1", # было https://api.openai.com/v1
api_key="nb_live_...", # ваш ключ genmux
)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.genmux.tech/v1",
apiKey: process.env.GENMUX_API_KEY,
});Каждый вызов после этого выглядит точно так же, как против собственного API OpenAI — те же названия методов, те же объекты ответа, только model указывает на один из id genmux. С версии 0.4.0 сюда входят вызов функций и JSON-режим — то, что делает эндпоинт полноценным бэкендом для агентов для программирования.
Что поддерживается
POST /v1/chat/completions принимает стандартные поля:
| Поле | Поддержка | Комментарий |
|---|---|---|
model | да | Любой id из таблицы цен, например deepseek-v4-pro, qwen3-max, doubao-seed-2-pro, и другие по мере запуска |
messages | да | role: system | user | assistant, content |
max_tokens | да | Ограничивает резерв; значение выше max_output_tokens модели обрезается, а не отклоняется |
temperature, top_p, stop | да | Стандартные параметры сэмплирования |
stream | да | Server-sent events; в последнем чанке приходит usage; вызовы инструментов приходят как delta.tool_calls |
tools, tool_choice | да, 7 моделей | Вызов функций, эмулируется genmux; tool_calls ассистента и сообщения role: tool ходят по кругу как у OpenAI. Остальные модели: 400 tools_unsupported |
response_format | да | json_object и json_schema ({name, schema}); непотоковые ответы валидируются, один автоматический повтор, затем 502 json_invalid. Не сочетается с tools |
reasoning_effort | да | none/minimal выключают thinking, low…xhigh включают — на моделях с поддержкой рассуждений |
enable_thinking | расширение genmux | Только на thinking-моделях (см. ниже) |
web_search | расширение genmux | Только Doubao Seed 2.0 Pro |
Вызов функций и JSON-режим
tools работает на семи моделях с флагом params_schema.tools: true в GET /v1/models: deepseek-v4-pro, deepseek-v4-flash, deepseek-v3, qwen3-7-max, qwen3-max, doubao-seed-2-pro и doubao-seed-2-code. Шлюз вендора отбрасывает поле tools, поэтому genmux вписывает определения в системный промпт и разбирает ответ обратно в стандартные tool_calls — определения считаются токенами промпта (около 40 на инструмент плюс схема), а tool_choice: required — инструкция, которую модель может проигнорировать. Отправка tools моделям qwen3-6-flash, doubao-seed-2-lite или doubao-seed-2-mini возвращает 400 tools_unsupported. Инженерная часть и измеренные результаты — в посте про эмуляцию вызова функций.
response_format принимает {"type":"json_object"} и {"type":"json_schema","json_schema":{"name":…,"schema":{…}}}. Непотоковые ответы валидируются (JSON Schema 2020-12); при ошибке следует один автоматический повтор с ошибкой валидатора в промпте, а вторая неудача завершается 502 json_invalid с оплатой обеих попыток. Стримы проходят без валидации, а JSON-режим нельзя сочетать с tools в одном запросе.
Что не поддерживается
Три вещи возвращают 400 unsupported_parameter, а не молча игнорируются:
n > 1— только одно завершение на запрос.- Устаревшие
functions— используйтеtools; параfunctions/function_callотклоняется. logprobs— ни один апстрим их не возвращает.
Принимаются и игнорируются, чтобы старый клиентский код продолжал работать: stream_options, parallel_tool_calls, seed, user, metadata, store, logit_bias и name в сообщениях.
Чтение usage и стоимости
Ответ — стандартный chat.completion (или поток chat.completion.chunk), расширенный биллинговыми полями в usage:
{
"id": "gnx_9f2c...",
"object": "chat.completion",
"model": "qwen3-max",
"choices": [{ "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" }],
"usage": {
"prompt_tokens": 128,
"completion_tokens": 342,
"total_tokens": 470,
"cost": 0.276,
"cost_source": "vendor"
}
}id — это id задания genmux; OpenAI SDK спокойно проигнорирует его, если он не нужен, но по нему можно найти вызов позже через GET /v1/generations/{id} или получить список всех текстовых вызовов аккаунта через GET /v1/generations?capability=text.chat. cost указан в юнитах; cost_source равен vendor, если апстрим сообщил точный usage, и estimated, если genmux вычислил его по числу токенов (всегда так для стриминговых вызовов).
Ошибки, которые стоит обрабатывать явно
Ошибки на чат-маршруте приходят в конверте OpenAI — {"error":{"message","type","code","param","request_id"}}, где type — один из invalid_request_error, authentication_error, permission_error, insufficient_quota, rate_limit_error, not_found_error, server_error, — так что классы исключений OpenAI SDK ложатся на них без изменений. (Остальные маршруты genmux по-прежнему отвечают в RFC 7807 problem+json.)
| Статус | Код | Значение |
|---|---|---|
| 400 | unsupported_parameter | Отправлено одно из отклоняемых полей выше (n>1, functions, logprobs) |
| 400 | tools_unsupported | tools отправлены одной из трёх моделей без флага |
| 400 | context_length_exceeded | Промпт + max_tokens превышают контекстное окно модели |
| 402 | insufficient_credits | Баланса не хватает на резерв; ничего не сгенерировано и не списано |
| 502 | json_invalid | Ответ в JSON-режиме дважды не прошёл валидацию по схеме; обе попытки оплачены |
Thinking, если модель его поддерживает
enable_thinking работает на DeepSeek V4 (Pro и Flash), Qwen3.7-Max, Qwen3-Max и Doubao Seed 2.0 Pro/Code/Lite, список будет расти по мере запуска новых моделей — если отправить его модели без поддержки рассуждений, параметр просто игнорируется. Токены рассуждений тарифицируются как выходные; см. как тарифицируется thinking-режим, прежде чем включать его на высоконагруженном эндпоинте.
Стриминг остаётся той же формы
stream: true возвращает тот же формат SSE, который уже разбирает ваша интеграция с OpenAI — строки data: {...}\n\n, data: [DONE] в конце. Единственное дополнение: последний чанк перед [DONE] содержит пустой массив choices и заполненный объект usage — именно оттуда стоит читать стоимость. Полный код разбора для Python и Node — в гайде по стримингу.
С чего начать
Смените base_url, подставьте ключ genmux — и остальная интеграция с OpenAI продолжит работать, включая tools и JSON-режим, если только она не опирается на n>1, устаревшие functions или logprobs. Настройка агентов (OpenCode, aider, Cline, Roo Code, Continue) — на странице про агентов для программирования. Полное описание endpoint'а и текущий каталог моделей — в документации; цены на все модели — на странице цен.