AIFreeAPI Logo

Chat Completions или Responses API: что меняется в интеграции

A
3 min readРазработка ИИ

Для нового проекта разумный выбор по умолчанию — Responses API. Стабильную интеграцию Chat Completions можно переносить постепенно: сначала зафиксировать контракты состояния, инструментов и потока.

Сравнение контрактов Chat Completions и Responses API для ввода, вывода, состояния, инструментов, structured output и streaming

Если проект начинается сегодня, в большинстве случаев стоит брать Responses API. Если сервис на Chat Completions стабильно решает простую задачу генерации текста, срочной переписи нет. Текущее руководство OpenAI по миграции одновременно говорит две важные вещи: Responses рекомендован для новых проектов, а Chat Completions продолжает поддерживаться.

Это не два имени одного JSON-протокола. Chat Completions строится вокруг массива сообщений и массива вариантов ответа. Responses использует типизированные Items: сообщение, reasoning, вызов функции и результат функции — разные элементы. Поэтому смена URL затрагивает парсер, состояние диалога, инструменты, streaming и наблюдаемость.

Сначала найдите контракт, от которого зависит код

Минимальные вызовы выглядят похоже:

python
completion = client.chat.completions.create( model="gpt-5.6", messages=[{"role": "user", "content": "Классифицируй обращение"}], ) text = completion.choices[0].message.content response = client.responses.create( model="gpt-5.6", input="Классифицируй обращение", ) text = response.output_text

Но output_text — удобный помощник SDK только для итогового текста. Если нужны вызовы инструментов, статусы или другие типы результата, приложение должно разбирать response.output.

КонтрактChat CompletionsResponses API
Endpoint/v1/chat/completions/v1/responses
Входmessagesinput и при необходимости instructions
Выходchoices[].messageтипизированные output[] Items
Несколько кандидатовпараметр nодна генерация в response
Продолжение диалогаповторная отправка историиprevious_response_id, Conversations или ручной replay
Structured Outputsresponse_formattext.format
Потокchunks и choices[].deltaтипизированные события

Простой массив role/content можно передать в Responses как input. Это облегчает первый тест, но не делает протоколы взаимозаменяемыми.

Состояние диалога не отменяет ответственность приложения

В Chat Completions приложение обычно хранит нужную историю и снова отправляет её в messages. Responses позволяет связать следующий ход через previous_response_id:

python
first = client.responses.create( model="gpt-5.6", instructions="Отвечай как дежурный инженер.", input="Сгруппируй эти алерты по причине.", ) next_turn = client.responses.create( model="gpt-5.6", previous_response_id=first.id, instructions="Отвечай как дежурный инженер.", input="Оставь только критическую группу.", )

Повтор instructions здесь обязателен по смыслу. API reference Responses предупреждает: инструкции предыдущего response не переносятся автоматически только из-за previous_response_id.

Удобное продолжение и хранение данных — разные решения. В документе OpenAI о данных отдельно описаны store, Zero Data Retention, background mode, кэш, hosted tools и внешние сервисы. Сейчас для сохранённого Responses application state указан период не менее 30 дней, но организационные настройки и исключения меняют результат. Для требований к данным проверяйте реальную конфигурацию, а не один флаг.

Function calling меняет весь цикл

Цикл вызова инструмента в Chat Completions и Responses API с разными конвертами и конечными состояниями
Цикл вызова инструмента в Chat Completions и Responses API с разными конвертами и конечными состояниями

В Chat Completions вызовы функций находятся внутри assistant message. Результат возвращается сообщением role: "tool", связанным через tool_call_id. В Responses вызов — отдельный Item function_call, а результат — function_call_output, связанный через call_id.

python
outputs = [] for item in response.output: if item.type == "function_call": outputs.append({ "type": "function_call_output", "call_id": item.call_id, "output": run_tool(item.name, item.arguments), })

Нельзя обрабатывать только первый элемент: модель может вернуть параллельные вызовы. Приёмочные тесты должны покрывать ноль, один и несколько вызовов, неверные аргументы, timeout, ошибку инструмента и повторный вызов после результата. Актуальные конверты приведены в официальном руководстве по function calling.

Hosted tools — web search, file search, code interpreter и remote MCP — делают Responses особенно полезным для агентных сценариев. Но поддержка конкретного инструмента зависит от модели.

Streaming требует диспетчера событий

Chat Completions отдаёт chunks, и интерфейс часто просто добавляет choices[0].delta.content. Responses отдаёт семантические события разных типов: текстовые delta, аргументы функции, завершение Item и финальный статус всего response. В руководстве по streaming эти формы показаны отдельно.

Интерфейс должен различать completed, failed, incomplete, отмену пользователем и разрыв сети. HTTP 200 и первый текстовый fragment ещё не означают успешного завершения. Для диагностики полезно сохранять response ID, финальный статус, типы Items, usage и причину ошибки или незавершённости.

Structured Outputs тоже меняет форму запроса: response_format становится text.format. Проверяйте не только JSON Schema, но и поддержку модели, refusal и ветку ошибки. Официальное руководство отдельно объясняет, когда нужна структурированная реплика пользователю, а когда function calling для действия в системе.

Когда остаться, а когда перейти

Матрица выбора API по типу нагрузки и проверки совместимости перед миграцией
Матрица выбора API по типу нагрузки и проверки совместимости перед миграцией

Responses лучше подходит новому проекту с инструментами, reasoning context, мультимодальным входом, длинной задачей или будущим агентным циклом. Chat Completions можно оставить для зрелого однопроходного текста, если миграция пока не даёт измеримой пользы.

Для сторонних сервисов важна переносимость. Надпись «OpenAI-compatible» часто означает совместимость именно с Chat Completions. Она не доказывает поддержку Responses. По документации провайдера отдельно проверяйте endpoint, Items, события потока, tool envelopes, продолжение состояния и ошибки.

Практичная миграция идёт за адаптером: сначала уберите из бизнес-кода прямой доступ к choices[0], затем запустите shadow-трафик, выберите стратегию состояния, перенесите полный цикл инструментов, перепишите streaming и только после этого постепенно переключайте production. Готовность наступает не тогда, когда пример выдал текст, а когда диалог восстанавливается, все вызовы связаны, schema разбирается, поток корректно закрывается, а сбой можно объяснить.