Тема
Язык
·4 мин. чтения

Responses API и Chat Completions: в чём разница и что выбрать

Практические различия между /v1/responses и /v1/chat/completions в API, совместимом с OpenAI: формат запросов, история разговоров, инструменты, события потоковой передачи и рекомендации по выбору. Каждый пример был запущен в реальном времени через GetVibe API.

Responses API и Chat Completions: в чём разница и что выбрать

В OpenAI-совместимых API теперь есть два основных формата запросов: давно используемый /v1/chat/completions и более новый /v1/responses. GetVibe API поддерживает оба с одним ключом и одним базовым URL — https://getvibeapi.com/v1. Разберёмся, чем они отличаются на практике, какой выбрать и о какой ловушке нужно помнить при переходе между ними.

Кратко

Chat CompletionsResponses
ЭндпоинтPOST /v1/chat/completionsPOST /v1/responses
Входные данныемассив messagesinput: строка или массив элементов
Системный промптсообщение с ролью systemполе instructions
Ответchoices[0].messageмассив output: рассуждение, сообщение, вызовы функций
Лимит выводаmax_tokensmax_output_tokens
Кто используетбольшинство SDK, фреймворков и чат-приложенийCodex CLI и более новые SDK для агентов

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

Один и тот же запрос в обоих форматах

Chat Completions:

curl https://getvibeapi.com/v1/chat/completions \
  -H "Authorization: Bearer $GETVIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-luna",
    "messages": [
      {"role": "system", "content": "Ответьте одним предложением."},
      {"role": "user", "content": "Что означает HTTP 429?"}
    ],
    "max_tokens": 300
  }'

Responses:

curl https://getvibeapi.com/v1/responses \
  -H "Authorization: Bearer $GETVIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-luna",
    "instructions": "Ответьте одним предложением.",
    "input": "Что означает HTTP 429?",
    "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://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])

chat = client.chat.completions.create(
    model="gpt-6-luna",
    messages=[{"role": "system", "content": "Ответьте одним предложением."},
              {"role": "user", "content": "Что означает HTTP 429?"}],
)
print(chat.choices[0].message.content)

resp = client.responses.create(
    model="gpt-6-luna",
    instructions="Ответьте одним предложением.",
    input="Что означает HTTP 429?",
)
print(resp.output_text)

Responses не ограничен моделями OpenAI. Перед публикацией мы отправили один и тот же запрос Responses моделям gpt-6-luna, claude-sonnet-5.5 и deepseek-v4.1-flash, и все три ответили. DeepSeek вернула элемент reasoning перед элементом message — именно так, как описано выше.

История диалога: передавайте её самостоятельно

Это единственное, что нужно знать перед переходом. Собственный Responses API OpenAI может хранить диалог на сервере, поэтому в следующем запросе можно указать предыдущий запрос с помощью previous_response_id. GetVibe API не хранит ваши диалоги, поэтому previous_response_id не поддерживается, а store игнорируется. Когда мы попробовали это сделать, запрос был отклонён с ошибкой 400.

Рабочий подход такой же, как в Chat Completions: передавайте всю историю в input.

history = [{"role": "user", "content": "Меня зовут Ana. Запомни это."}]
first = client.responses.create(model="gpt-6-luna", input=history)

history.append({"role": "assistant", "content": first.output_text})
history.append({"role": "user", "content": "Как меня зовут? Одним словом."})
second = client.responses.create(model="gpt-6-luna", input=history)
print(second.output_text)  # Ana

Инструменты: другая структура

Вызов функций работает в обоих форматах, но определение инструмента выглядит по-разному. В Chat Completions поля функции вложены в объект function, а в Responses находятся непосредственно в инструменте. Вызов поступает как отдельный элемент 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-6-luna", input=items, tools=tools)

for item in resp.output:
    if item.type == "function_call":
        result = {"city": "Denver", "temp_f": 54, "sky": "overcast"}  # ваша функция
        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)})

final = client.responses.create(model="gpt-6-luna", input=items, tools=tools)
print(final.output_text)

В нашем запуске модель вызвала get_weather с параметром {"city":"Denver"}, а во втором запросе ответила, что в Денвере 54°F и пасмурно. Версия того же цикла для Chat Completions приведена в нашем руководстве по вызову функций.

Потоковая передача

Оба формата поддерживают "stream": true, но события отличаются. Chat Completions отправляет унифицированные строки data:, где каждый новый фрагмент текста находится в choices[0].delta.content. Responses отправляет именованные события: сначала response.created, затем response.output_text.delta с фрагментами текста и в конце response.completed. Если вы разбираете поток самостоятельно, а не через SDK, вам понадобится парсер для конкретного формата.

Что выбрать

  • Chat Completions, если у вас уже есть код на нём или вы используете фреймворк, чат-приложение либо платформу без кода. Его поддерживает почти каждый инструмент, и нет причин переписывать рабочий код только ради смены формата.
  • Responses, если этого требует инструмент. Главный пример — Codex CLI, который обращается к /v1/responses; инструкции по настройке приведены в документации Codex CLI и в нашем руководстве по Codex CLI.

В любом случае список моделей и цены одинаковы. Все поля описаны в справочнике API, а актуальные цены указаны на странице моделей.

Responses API и Chat CompletionsOpenAI Responses API/v1/responsesChat Completions APIprevious_response_idCodex CLI Responses API

Попробуйте GetVibe API бесплатно

GPT, Claude, Gemini и другие модели через единый API, совместимый с OpenAI. Оплата в USD картой или криптовалютой.

Похожие статьи

Responses API и Chat Completions: в чём разница и что выбрать | GetVibe API