Руководство и понимание

Создайте уровень совместимости API ответов в шлюзе AI API

Шлюз API ответов — это не просто прокси-сервер Chat Completions с новым маршрутом. Сохраняйте элементы ответа, состояние, вызовы инструментов, потоки, непрерывность рассуждений, атрибуцию использования и поведение при переходе на более раннюю версию с помощью первоклассного уровня совместимости.

Не реализуйте /v1/responses, переводя каждый запрос в /v1/chat/completions и надеясь, что форма будет достаточно близкой. Этот адаптер может возвращать текст, но он может незаметно потерять те части, которые важны для разработчиков: элементы ответа, состояние на стороне сервера, вызовы инструментов, непрерывность рассуждений, события жизненного цикла потока, семантику отмены и атрибуцию использования на уровне элементов.

Практическая цель — уровень совместимости, который рассматривает API ответов как более функциональный протокол. Сохраните поддержку завершения чата для существующих клиентов, но создайте ответы как отдельную поверхность шлюза со своей собственной моделью состояния, нормализатором потока, реестром вызовов инструментов, матрицей возможностей и резервными правилами.

Что такое факт, что такое политика и что такое прогноз?

Факты. OpenAI описывает API ответов как объединяющий возможности, которые ранее были разделены на функции завершения чата и помощников, включая поддержку таких инструментов, как веб-поиск, поиск файлов и использование компьютера. API предоставляет такие поля, как previous_response_id, потоковую передачу, выбор инструментов и встроенные инструменты. Документация SDK показывает, что previous_response_id может обеспечить непрерывность диалога, в то время как предыдущие инструкции не переносятся автоматически и должны быть отправлены повторно, когда они все еще должны применяться. Справочник по потоковой передаче OpenAI включает в себя отдельные жизненный цикл ответа и выходные события, а не только дельты токенов.

Рекомендации. Шлюз должен сохранять эту семантику, а не сглаживать ее по умолчанию. Он должен отклонять или явно понижать запросы, если целевой поставщик не может поддерживать требуемое поведение.

Прогноз. Дополнительные рабочие нагрузки агента будут зависеть от структуры элементов ответа, трассировок выполнения инструментов и контекста рассуждений с отслеживанием состояния. Шлюзы, которые моделируют эти концепции, теперь будет легче расширять, чем шлюзы, которые рассматривают ответы как косметическую конечную точку.

Определить отдельный контракт совместимости для ответов

Первая ошибка реализации заключается в предположении, что совместимость с OpenAI означает одну универсальную схему запроса и ответа. На практике /v1/chat/completions и /v1/responses должны быть отдельными контрактами совместимости.

Сохраните общий уровень аутентификации, выставления счетов, квот и маршрутизации, но отделите уровень протокола:

<ул>
  • Дополнения в чате: сообщения, варианты выбора, отклонения, вызовы инструментов в формате чата, поведение устаревшего клиента.
  • Область ответов: элементы ввода, элементы вывода, идентификаторы ответов, ссылки на предыдущие ответы, события расширенного инструмента, события жизненного цикла, поля, связанные с рассуждениями, и окончательное состояние ответа.
  • Это разделение имеет значение для тестов на соответствие. Адаптер поставщика, который проходит тесты чата, по-прежнему может не пройти тесты ответов, поскольку он не может сохранить previous_response_id, порядок элементов, структуру отказа, метаданные размещенного инструмента или названия событий потоковой передачи.

    Минимальный контракт совместимости должен отвечать:

    <ул>
  • Какие поля запроса принимаются, отклоняются, преобразуются или игнорируются?
  • Какие типы элементов ответа сохраняются?
  • Какие типы инструментов поддерживаются каждым поставщиком и моделью?
  • Может ли провайдер поддерживать состояние диалога или его должен поддерживать шлюз?
  • Что происходит, когда запрашивается store=false?
  • Какие события трансляции гарантированы?
  • Как регистрируются отмена, тайм-аут и частичное использование?
  • Если у вас уже есть шлюз AI API, рассматривайте поддержку ответов как расширение протокола, а не псевдоним маршрута.

    Используйте каноническую модель ответа

    API Responses возвращает более одного сообщения помощника. Он может представлять различные выходные элементы и события. Вашему шлюзу необходима внутренняя каноническая модель, прежде чем он будет сопоставлен с каким-либо поставщиком.

    Практическая схема внутреннего элемента может начинаться так:

    {
      "gateway_response_id": "gw_resp_...",
      "provider_response_id": "resp_...",
      "tenant_id": "ten_123",
      "key_id": "key_456",
      "model_alias": "агент-по умолчанию",
      "провайдер": "openai",
      "предметы": [
        {
          "item_id": "item_1",
          "тип": "текст",
          "роль": "помощник",
          "content": [{ "type": "output_text", "text": "..." }],
          "статус": "завершено"
        },
        {
          "item_id": "item_2",
          "type": "function_call",
          "call_id": "call_abc",
          "name": "lookup_order",
          "arguments_json": "{\"order_id\":\"123\"}",
          "статус": "завершено"
        }
      ],
      "использование": {
        «входные_токены»: 0,
        «выходные_токены»: 0,
        "reasoning_tokens": ноль,
        "tool_units": []
      },
      "статус": "завершено"
    

    Включайте типы товаров еще до того, как каждый поставщик сможет их произвести. Полезные категории включают в себя:

    <ул>
  • Вывод текста
  • Отказы
  • Вызовы функций
  • Выходные данные функции, отправленные приложением
  • Резюме рассуждений или метаданные, связанные с рассуждениями, если таковые имеются.
  • Ссылки на файлы
  • Поиск в Интернете, поиск файлов, использование компьютера или другие события, связанные с размещенными инструментами.
  • Окончательные метаданные об использовании и выставлении счетов
  • Смысл в том, чтобы не предоставлять пользователям закрытую схему. Цель состоит в том, чтобы шлюз не выбрасывал информацию до того, как он сможет ее проверить, выставить счет, транслировать, воспроизвести или преобразовать.

    Создайте государственную книгу, принадлежащую шлюзу

    previous_response_id — это поле, которое наиболее наглядно демонстрирует разницу между проксированием чата без сохранения состояния и совместимостью ответов. Если клиент ссылается на предыдущий ответ, шлюз должен знать, что означает этот идентификатор, разрешено ли арендатору использовать его и может ли поставщик продолжить работу с ним.

    Создайте реестр штата с указанием арендатора и идентификатора ответа:

    {
      "gateway_response_id": "gw_resp_789",
      "provider_response_id": "resp_provider_789",
      "previous_gateway_response_id": "gw_resp_456",
      "tenant_id": "ten_123",
      "user_id": "user_999",
      "key_id": "key_456",
      "модель": "gpt-...",
      "провайдер": "openai",
      "store_mode": "провайдер|шлюз|нет",
      "retention_policy": "standard|zero_retention|custom_30d",
      "instructions_hash": "sha256:...",
      "tool_policy_id": "tools_readonly_v3",
      "create_at": "...",
      "expires_at": "...",
      «deleted_at»: ноль
    

    Важное правило: не эмулируйте автоматически previous_response_id путем воспроизведения полной истории чата, если клиент явно не разрешил такое поведение по удержанию и затратам. Воспроизведение может увеличить стоимость токена, изменить положение конфиденциальности и изменить поведение модели. Безопаснее вернуть явную ошибку возможности, чем молча отправлять сохраненный контент разговора, который приложение не ожидало сохранить или повторно использовать.

    Режимы обработки состояний

    <ул>
  • Состояние поставщика. Вышестоящий поставщик хранит достаточный контекст, а шлюз сопоставляет идентификаторы ответов шлюза с идентификаторами ответов поставщика.
  • Состояние шлюза. Шлюз сохраняет необходимые предыдущие элементы и восстанавливает контекст, когда это разрешено.
  • Нет состояния. В запросе используется store=false или политика клиента запрещает сохранение. previous_response_id следует отклонять, если поставщик не может обработать запрос без сохранения шлюза и это разрешено политикой.
  • Также помните, что клиенту может потребоваться повторно отправить предыдущие инструкции, когда они продолжат действовать. Шлюзу не следует изобретать скрытые инструкции для компенсации, если такое поведение не является частью явной политики клиента.

    Проверка инструментов перед отправкой

    Отклики делают использование инструмента более централизованным. Уровень совместимости должен обрабатывать две широкие категории:

    <ул>
  • Инструменты приложения. Определения функций, предоставленные клиентом, выполняются вне поставщика модели, а выходные данные передаются обратно в API.
  • Инструменты размещенного провайдера: поиск в Интернете, поиск файлов, использование компьютера, выполнение кода, заземление или аналогичные инструменты, выполняемые провайдером или инфраструктурой, контролируемой шлюзом.
  • При входе проверьте схемы инструментов перед маршрутизацией:

    <ул>
  • Досрочное отклонение недействительной схемы JSON.
  • Обеспечить максимальный размер схемы и глубину вложенности.
  • Проверьте названия инструментов на совместимость с поставщиками.
  • Применить области арендатора, ключа, пользователя и среды.
  • Требуйте уровни одобрения для инструментов, которые записывают данные, тратят деньги, получают доступ к конфиденциальным системам или вызывают внешние соединители.
  • Для вызова функций приложения требуется стабильный идентификатор вызова. Модель генерирует вызов функции с call_id; приложение отправляет выходные данные инструмента со ссылкой на этот идентификатор; шлюз записывает оба в одну и ту же трассировку. Без этого ключа объединения журналы аудита и повторные попытки становятся неоднозначными.

    Для размещенных инструментов зарезервируйте бюджет перед отправкой и оплатите стоимость позднее. Размещенные инструменты могут добавлять расходы, выходящие за рамки обычного учета токенов, поэтому подключите реестр инструментов к унифицированному выставлению счетов AI API, а не скрывайте эти затраты внутри общей суммы вызовов модели.

    Нормализация потоковой передачи как событий, а не текста токена

    Прокси-серверу чата часто удается избежать пересылки дельт токенов. Шлюз ответов не может. Поток имеет смысл жизненного цикла: ответ может начинаться, элементы вывода могут начинаться и завершаться, текст может поступать в дельтах, вызовы инструментов могут собираться постепенно, использование может поступать в конце или во время потока, а ответ может завершиться с ошибкой или быть отменен.

    Определите схему событий шлюза, а затем сопоставьте с ней каждый поток поставщика:

    событие: response_started
    данные: { "response_id": "gw_resp_123", "status": "in_progress" }
    
    событие: выход_item_startedданные: { "item_id": "item_1", "type": "text" }
    
    событие: text_delta
    данные: { "item_id": "item_1", "delta": "Привет" }
    
    событие:tool_call_delta
    data: { "item_id": "item_2", "call_id": "call_abc", "arguments_delta": "{\"order" }
    
    событие: use_delta
    данные: { "output_tokens": 12 }
    
    событие: завершено
    данные: { "response_id": "gw_resp_123", "usage": { ... } 

    Рекомендуемые нормализованные события:

    <ул>
  • response_started
  • output_item_started
  • output_item_completed
  • text_delta
  • refusal_delta
  • tool_call_delta
  • tool_result_received
  • usage_delta
  • завершено
  • отменено
  • не удалось
  • Когда клиент отключается, распространите отмену вверх по течению, если провайдер поддерживает это. Запишите состояние частичного ответа в любом случае. Если позже поставщик возвращает окончательное использование через отложенный обратный вызов или финальный фрагмент, согласуйте реестр. Совместимость потоковой передачи зависит не только от задержки, но и от учета и жизненного цикла.

    Создайте матрицу возможностей поставщика

    Мультимодельная маршрутизация полезна только тогда, когда шлюз понимает, что можно безопасно маршрутизировать. Добавьте возможности, специфичные для ответов, в каталог моделей:

    {
      "model_alias": "агент-по умолчанию",
      "маршруты": [
        {
          "провайдер": "openai",
          "модель": "...",
          «supports_responses»: правда,
          «supports_previous_response_id»: правда,
          «supports_store_false»: правда,
          «supports_builtin_web_search»: правда,
          «supports_function_calling»: правда,
          «supports_stream_lifecycle_events»: правда,
          «supports_reasoning_context_continuity»: правда,
          "max_tool_schema_bytes": 65536
        },
        {
          "провайдер": "provider_b",
          "модель": "...",
          "supports_responses": ложь,
          «chat_adapter_available»: правда,
          "loss_profile": ["no_previous_response_id", "no_hosted_tools", " Flattened_stream"]
        }
      ]
    

    Резервный вариант должен учитывать потери. Если для запроса требуется встроенный веб-поиск, а резервный поставщик не может его выполнить, не отвечайте молча без поиска. Если запрос зависит от сохраненного контекста обоснования и резервный маршрут не может его сохранить, верните ошибку возможности или ответ на понижение версии, на который клиент явно согласился.

    Полезный вариант запроса:

    {
      "модель": "агент-по умолчанию",
      "вход": "...",
      "fallback_policy": {
        «allow_lossy»: ложь,
        "allow_losses": []
      }
    

    Для менее деликатных случаев использования арендаторы могут разрешить понижение версии с потерями:

    {
      "fallback_policy": {
        «allow_lossy»: правда,
        "allowed_losses": [" Flattened_stream", "no_reasoning_summary"]
      }
    

    Шлюз в любом случае должен регистрировать резервное решение. Это делает возможной последующую отладку, когда агент ведет себя по-другому после сбоя провайдера или перенаправления модели.

    Использование атрибутов на уровне ответа и элемента

    Вызовы ответов могут стоить дороже, чем эквивалентное завершение чата, поскольку они могут включать в себя выполнение инструмента, более длинный контекст, токены рассуждения, поиск файлов, поиск в Интернете или повторяющиеся инструкции. Одного совокупного количества токенов недостаточно для панели анализа использования AI API.

    Запись использования на двух уровнях:

    <ул>
  • Уровень ответа: клиент, ключ, пользователь, модель, поставщик, задержка, окончательный статус, входные токены, выходные токены, токены обоснования, где сообщается, общая стоимость и резервный маршрут.
  • Уровень элемента/инструмента: название инструмента, идентификатор вызова, размещенные модули инструмента, идентификаторы файлов, количество поисковых запросов, если доступно, задержка инструмента, стоимость инструмента и результат политики утверждения.
  • Это позволит разработчикам ответить на конкретные вопросы:

    <ул>
  • Увеличились ли затраты из-за более длительного состояния, усилий по рассуждению, вызовов инструментов или отката?
  • Какой клиент или ключ API взимает плату за размещенный инструмент?
  • Какой ответ не удался после вызова инструмента, но до окончательного текста?
  • Какие отмененные потоки по-прежнему использовались в восходящем направлении?
  • Относиться к нулевому хранению и удалению как к первоклассному поведению

    Состояние на стороне сервера полезно, но оно меняет обязательства шлюза по хранению. Встройте политику на уровне протокола, а не рассматривайте ее как настройку журнала.

    Для каждого запроса ответов выполните следующее:

    <ул>
  • Политика удержания арендаторов
  • Предпочтение магазина на уровне запроса
  • Совместимость удержания поставщиков
  • Разрешено ли воспроизведение шлюза
  • Можно ли сохранять входные и выходные данные инструмента
  • Истечение срока действия и удаление состояния ответа
  • Если хранение отключено, шлюз по-прежнему может хранить минимальные рабочие метаданные: метки времени, идентификаторы, статус, количество токенов, стоимость и решения политики. Не храните необработанные запросы, полные выходные данные инструмента или восстановленную историю, если это не разрешено политикой.

    Добавление соответствия перед запуском

    Не полагайтесь на ручные тесты «счастливого пути». Добавьте приспособления, которые проверяют поведение протокола на прямых маршрутах OpenAI, маршрутах, адаптированных поставщиком, и резервных сценариях.

    Минимальный набор тестов

    <ул>
  • Базовый ответ: текстовый элемент возвращается со стабильным идентификатором ответа и сведениями об использовании.
  • Многоходовое состояние: второй запрос ссылается на previous_response_id; шлюз проверяет право собственности арендатора и режим состояния.
  • Повторяющиеся инструкции: убедитесь, что пропущенные инструкции не были изобретены шлюзом молча.
  • Обратный вызов функции: модель выдает идентификатор вызова; приложение отправляет выходные данные; окончательный ответ объединяет обе записи.
  • Политика размещенных инструментов: неавторизованный встроенный инструмент блокируется перед отправкой.
  • Порядок потоковой передачи: начало ответа, начало элемента, отклонения, завершение элемента, использование и завершение отправляются в допустимом порядке.
  • Отмена потока: отключение клиента вызывает отмену восходящего потока, если это поддерживается, и регистрирует частичное использование.
  • Отказ от резервного варианта: поставщик без обязательной семантики ответов возвращает ошибку возможности.
  • Включение резервного варианта с потерями: запрос с разрешенными потерями получает явный маркер понижения версии.
  • Режим нулевого хранения: воспроизведение состояния и сохранение подсказок на стороне шлюза блокируются.
  • Рекомендуемая последовательность развертывания

    <ол>
  • Открыть бета-версию. Добавьте /v1/responses, не меняя существующее поведение чата.
  • Сначала внедрите сквозную передачу для поставщиков со встроенной поддержкой ответов. Сохраняйте идентификаторы, элементы, потоки, использование и ошибки.
  • Добавьте реестр штата. Сопоставьте идентификаторы шлюзов с идентификаторами поставщиков и установите право владения арендаторами.
  • Добавьте канонические элементы. Сохраните метаданные элемента, необходимые для аудита, выставления счетов и реконструкции потока.
  • Добавьте управление инструментом. Проверяйте схемы, применяйте области действия и записывайте соединения вызовов инструментов.
  • Добавьте нормализацию потоковой передачи. Преобразуйте потоки, специфичные для поставщика, в события жизненного цикла шлюза.
  • Добавить маршрутизацию с учетом возможностей. По умолчанию разрешать только безопасные резервные варианты.
  • Добавьте аналитику и расчет счетов. Разделите токен атрибута, обоснование и использование инструмента.
  • Опубликовать примечания по совместимости. Сообщите разработчикам, какие поля являются собственными, эмулируемыми, неподдерживаемыми или с потерей данных.
  • Практическое заключение

    Уровень совместимости API ответов должен сохранять значение протокола, а не просто возвращать правдоподобный текст. Создайте его на основе пяти надежных объектов: канонической модели элементов ответа, реестра состояний диалога, журнала вызовов инструментов, нормализатора потоковой передачи событий и матрицы возможностей поставщика.

    Самым безопасным значением по умолчанию является строгая совместимость: если маршрут не может сохранить требуемое состояние, инструменты, контекст обоснования, потоковые события или поведение хранения, возвращайте явную ошибку возможности. Добавляйте резервный вариант с возможностью потери данных только тогда, когда разработчики поймут, что будет удалено. Этот подход может показаться менее удобным, чем автоматическое выравнивание, но он предотвращает худший вариант отказа: приложение, которое выглядит совместимым, молча теряя семантику, которая заставила его в первую очередь использовать API Responses.

    Связанное чтение

    FAQ

    Часто задаваемые вопросы

    Может ли шлюз реализовать API ответов, переводя все в завершение чата?
    Только для узкого подмножества с потерями. Базовая генерация текста может работать, но состояние, элементы ответа, размещенные инструменты, контекст, связанный с рассуждениями, структура отказа, события жизненного цикла потока и использование на уровне элементов могут быть потеряны. Рабочий шлюз должен предоставлять ответы как отдельную поверхность совместимости.
    Должен ли шлюз воспроизвести сохраненную историю чата для эмуляции previous_response_id?
    Не по умолчанию. Воспроизведение меняет поведение хранения, стоимость, а иногда и поведение модели. Арендатор должен явно разрешить сохранение и воспроизведение состояния на стороне шлюза, прежде чем шлюз применит эту стратегию.
    Что должно произойти, если резервные поставщики не могут поддерживать семантику ответов?
    Самым безопасным значением по умолчанию является ошибка возможности. Если арендатор выбирает резервный вариант с потерями, шлюз должен вернуть явный маркер перехода на более раннюю версию и записать, какая семантика была удалена.
    Зачем фиксировать использование на уровне элементов ответа?
    Вызовы ответов могут включать в себя вызовы инструментов, расходы на размещенные инструменты, токены рассуждений, частичные потоки и резервное поведение. Использование на уровне элементов делает понятными выставление счетов, отладку и аналитику арендаторов.