У OpenAI-совместимых API сейчас два основных формата запросов: давний /v1/chat/completions и более новый /v1/responses. PlusVibe принимает оба с одним ключом и одним базовым адресом https://plusvibeapi.ru/v1. Ниже — чем они отличаются на практике, какой выбрать и где подвох, если вы переходите с одного на другой.
Коротко: чем отличаются форматы
Chat Completions Responses АдресPOST /v1/chat/completions
POST /v1/responses
Вход
массив messages
input — строка или массив элементов
Системная инструкция
сообщение с ролью system
поле instructions
Ответ
choices[0].message
массив output: рассуждение, сообщение, вызовы функций
Лимит ответа
max_tokens
max_output_tokens
Кто использует
большинство SDK, фреймворков и чат-интерфейсов
Codex CLI, новые агентные SDK
Модель, цена и токены от выбора формата не зависят: один и тот же запрос к gpt-5.6-luna через оба адреса тарифицируется одинаково — по входным и выходным токенам модели.
Один и тот же запрос в двух форматах
Нужен ключ PlusVibe вида sk-pv-… — его можно создать после регистрации. Chat Completions:
curl https://plusvibeapi.ru/v1/chat/completions \
-H "Authorization: Bearer $PLUSVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-luna",
"messages": [
{"role": "system", "content": "Отвечай одним предложением."},
{"role": "user", "content": "Чем полезен кэш промптов?"}
],
"max_tokens": 300
}'
Responses:
curl https://plusvibeapi.ru/v1/responses \
-H "Authorization: Bearer $PLUSVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-luna",
"instructions": "Отвечай одним предложением.",
"input": "Чем полезен кэш промптов?",
"max_output_tokens": 300
}'
В ответе Chat Completions текст лежит в choices[0].message.content. В ответе Responses — внутри output: у рассуждающих моделей первым элементом идёт reasoning, текст ответа — в элементе с типом message. Разбирать массив руками не обязательно: в Python SDK есть готовое свойство output_text.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://plusvibeapi.ru/v1",
api_key=os.environ["PLUSVIBE_API_KEY"],
)
# Chat Completions
chat = client.chat.completions.create(
model="gpt-5.6-luna",
messages=[
{"role": "system", "content": "Отвечай одним предложением."},
{"role": "user", "content": "Что такое HTTP 429?"},
],
)
print(chat.choices[0].message.content)
# Responses
resp = client.responses.create(
model="gpt-5.6-luna",
instructions="Отвечай одним предложением.",
input="Что такое HTTP 429?",
)
print(resp.output_text)
Перед публикацией мы запустили оба варианта. Кроме gpt-5.6-luna, через /v1/responses ответили claude-sonnet-5 и deepseek-v4.1-flash: Responses работает не только с моделями OpenAI.
История диалога: передавайте её сами
Это главное, что нужно знать при переходе. У OpenAI Responses умеет хранить диалог на стороне сервера: следующий запрос ссылается на предыдущий через previous_response_id. PlusVibe переписку не хранит, поэтому previous_response_id не продолжает прошлый запрос, а поле store игнорируется (это описано в документации). Ошибки при этом не будет: модель просто не увидит прошлых реплик. Мы проверили: на вопрос «Как меня зовут?» с одним только previous_response_id модель ответила «Неизвестно».
Рабочий вариант — передавать всю историю в input, как в Chat Completions передают messages:
history = [{"role": "user", "content": "Меня зовут Аня. Запомни."}]
first = client.responses.create(model="gpt-5.6-luna", input=history)
history.append({"role": "assistant", "content": first.output_text})
history.append({"role": "user", "content": "Как меня зовут? Ответь одним словом."})
second = client.responses.create(model="gpt-5.6-luna", input=history)
print(second.output_text) # Аня
Инструменты: другая форма описания
Function calling работает в обоих форматах, но описание функции выглядит по-разному. В Chat Completions поля функции вложены в объект function, в Responses — лежат прямо в элементе tools. Вызов функции приходит отдельным элементом function_call, а результат вы возвращаете элементом function_call_output с тем же call_id:
import json
tools = [{
"type": "function",
"name": "get_weather",
"description": "Текущая погода в городе",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
}]
items = [{"role": "user", "content": "Какая погода в Казани?"}]
resp = client.responses.create(model="gpt-5.6-luna", input=items, tools=tools)
for item in resp.output:
if item.type == "function_call":
args = json.loads(item.arguments)
result = {"city": args["city"], "temp_c": 12, "sky": "пасмурно"} # ваша функция
items.append({"type": "function_call", "call_id": item.call_id,
"name": item.name, "arguments": item.arguments})
items.append({"type": "function_call_output", "call_id": item.call_id,
"output": json.dumps(result, ensure_ascii=False)})
final = client.responses.create(model="gpt-5.6-luna", input=items, tools=tools)
print(final.output_text)
В нашем прогоне модель вызвала get_weather с аргументом {"city": "Казань"}, а вторым запросом ответила, что в Казани 12 °C и пасмурно. Как то же самое выглядит в Chat Completions, мы разобрали в статье про function calling.
Потоковый режим
Оба формата поддерживают "stream": true, но события разные. Chat Completions присылает однотипные строки data:, где новый кусок текста лежит в choices[0].delta.content. Responses присылает именованные события: response.created, response.output_text.delta с кусками текста, response.completed в конце. Если вы разбираете поток сами, а не через SDK, парсер придётся писать под конкретный формат.
Какой формат выбрать
- Chat Completions — если у вас уже есть код на нём или вы используете фреймворк, чат-интерфейс или no-code-платформу. Его понимает почти любой инструмент, и переписывать работающее ради смены формата незачем.
- Responses — если его требует инструмент. Главный пример — Codex CLI: он ходит в
/v1/responses, настройка описана в документации и в статье про Codex CLI в России. Ещё один повод — вы пишете новый агентный код на свежем SDK, где Responses используется по умолчанию. - Messages — третий формат, от Anthropic. Он нужен Claude Code и Anthropic SDK и живёт по адресу
/v1/messagesс заголовкомx-api-key. Подробности — в разделе Messages и Responses.
Частые ошибки при переходе
Модель «забывает» диалог. Вы полагаетесь на previous_response_id. Передавайте историю в input целиком.
Пустой текст в ответе. Код читает output[0], а там элемент reasoning. Ищите элемент с типом message или берите output_text из SDK.
Ответ обрывается. Параметр называется max_output_tokens, а не max_tokens. У рассуждающих моделей в этот лимит входят и токены рассуждения, поэтому слишком маленькое значение может оставить ответ пустым.
Инструменты не вызываются. Описание функции скопировано из Chat Completions вместе с обёрткой function. В Responses поля name, description и parameters идут на верхнем уровне.
Итог
Chat Completions и Responses — два способа обратиться к одним и тем же моделям. В PlusVibe они работают с одним ключом, одинаковыми ценами и одинаковым каталогом. Если код уже написан, оставайтесь на Chat Completions. Responses нужен для Codex CLI и новых агентных SDK, только историю диалога передавайте в каждом запросе. Список моделей и цены — в каталоге, если нужен ответ строго по схеме, пригодится статья про Structured Outputs.
Chat Completions, Responses и Messages
Три формата, один ключ и один базовый адрес. Оплата в рублях.
Получить ключ →


