Skip to content
Przewodnik i wgląd

Zbuduj warstwę zgodności interfejsu API odpowiedzi w bramie interfejsu API AI

Brama interfejsu API odpowiedzi to nie tylko serwer proxy zakończenia czatu z nową trasą. Zachowaj elementy odpowiedzi, stan, wywołania narzędzi, strumienie, ciągłość rozumowania, przypisanie użycia i zachowanie przy przejściu na starszą wersję dzięki pierwszorzędnej warstwie kompatybilności.

Nie implementuj /v1/responses, tłumacząc każde żądanie na /v1/chat/completions i mając nadzieję, że kształt będzie wystarczająco zbliżony. Ten adapter może zwracać tekst, ale może po cichu utracić elementy, na których zależy programistom: elementy odpowiedzi, stan po stronie serwera, wywołania narzędzi, ciągłość wnioskowania, zdarzenia cyklu życia strumienia, semantykę anulowania i przypisywanie użycia na poziomie elementu.

Praktycznym celem jest warstwa kompatybilności, która traktuje Odpowiedzi API jako bogatszy protokół. Zachowaj obsługę uzupełnień czatu dla istniejących klientów, ale zbuduj odpowiedzi jako własną powierzchnię bramy z własnym modelem stanu, normalizatorem strumienia, księgą wywołań narzędzi, macierzą możliwości i regułami awaryjnymi.

Co to jest fakt, co to polityka, a co przewidywanie?

Fakty: OpenAI opisuje Odpowiedzi API jako możliwości ujednolicania, które wcześniej były podzielone między Uzupełnienia czatu i Asystentów, w tym obsługę takich narzędzi, jak wyszukiwanie w Internecie, wyszukiwanie plików i korzystanie z komputera. API udostępnia pola takie jak previous_response_id, przesyłanie strumieniowe, wybór narzędzi i narzędzia wbudowane. Dokumentacja SDK pokazuje, że previous_response_id może zapewnić ciągłość rozmowy, podczas gdy poprzednie instrukcje nie są automatycznie przenoszone i muszą zostać przesłane ponownie, gdy powinny nadal obowiązywać. Odniesienie do przesyłania strumieniowego OpenAI obejmuje odrębny cykl życia odpowiedzi i zdarzenia wyjściowe, a nie tylko różnice tokenów.

Zalecenia: Brama powinna zachować tę semantykę, a nie domyślnie ją spłaszczać. Powinien odrzucać żądania lub jawnie obniżać wersję, jeśli docelowy dostawca nie może obsłużyć wymaganego zachowania.

Przewidywanie: Większe obciążenie agenta będzie zależeć od struktury elementu odpowiedzi, śladów wykonania narzędzia i kontekstu wnioskowania stanowego. Bramy modelujące te koncepcje będą teraz łatwiejsze do rozbudowy niż bramy traktujące Odpowiedzi jako kosmetyczny punkt końcowy.

Określ oddzielną umowę dotyczącą zgodności dla odpowiedzi

Pierwszy błąd w implementacji zakłada, że OpenAI-kompatybilny oznacza jeden uniwersalny schemat żądań i odpowiedzi. W praktyce /v1/chat/completions i /v1/responses powinny stanowić oddzielne umowy dotyczące zgodności.

Zachowaj wspólną warstwę uwierzytelniania, rozliczeń, przydziałów i routingu, ale oddziel warstwę protokołu:

  • Powierzchnia uzupełnień czatu: wiadomości, wybory, zmiany, wywołania narzędzi w formacie czatu, zachowanie starszego klienta.
  • Powierzchnia odpowiedzi: elementy wejściowe, elementy wyjściowe, identyfikatory odpowiedzi, odniesienia do poprzednich odpowiedzi, bogatsze zdarzenia narzędzi, zdarzenia strumienia cyklu życia, pola związane z rozumowaniem i końcowy stan odpowiedzi.

Ten podział ma znaczenie w przypadku testów zgodności. Adapter dostawcy, który przejdzie testy na czacie, może nadal nie przejść testów Odpowiedzi, ponieważ nie może zachować previous_response_id, kolejności elementów, struktury odmów, metadanych hostowanego narzędzia ani nazw zdarzeń przesyłania strumieniowego.

Umowa o minimalnej kompatybilności powinna odpowiadać:

  • Które pola żądania są akceptowane, odrzucane, przekształcane lub ignorowane?
  • Jakie typy elementów odpowiedzi są zachowywane?
  • Jakie typy narzędzi są obsługiwane w zależności od dostawcy i modelu?
  • Czy dostawca może utrzymać stan konwersacji, czy musi go utrzymywać brama?
  • Co się stanie, gdy zostanie zażądane store=false?
  • Jakie zdarzenia w transmisji są gwarantowane?
  • Jak rejestrowane jest anulowanie, przekroczenie limitu czasu i częściowe wykorzystanie?

Jeśli masz już bramkę AI API, traktuj obsługę odpowiedzi jako rozszerzenie protokołu, a nie alias trasy.

Użyj kanonicznego modelu pozycji odpowiedzi

Odpowiedzi API zwracają więcej niż jedną wiadomość asystenta. Może reprezentować różne elementy wyjściowe i zdarzenia. Twoja brama potrzebuje wewnętrznego modelu kanonicznego, zanim zostanie zmapowana na dowolnego dostawcę.

Praktyczny schemat elementów wewnętrznych może zaczynać się w ten sposób:

{
  "gateway_response_id": "gw_resp_...",
  "provider_response_id": "resp_...",
  "tenant_id": "ten_123",
  "key_id": "key_456",
  "model_alias": "agent-default",
  "provider": "openai",
  "items": [
    {
      "item_id": "item_1",
      "type": "text",
      "role": "assistant",
      "content": [{ "type": "output_text", "text": "..." }],
      "status": "completed"
    },
    {
      "item_id": "item_2",
      "type": "function_call",
      "call_id": "call_abc",
      "name": "lookup_order",
      "arguments_json": "{\"order_id\":\"123\"}",
      "status": "completed"
    }
  ],
  "usage": {
    "input_tokens": 0,
    "output_tokens": 0,
    "reasoning_tokens": null,
    "tool_units": []
  },
  "status": "completed"
}

Uwzględnij typy elementów, zanim każdy dostawca będzie mógł je wyprodukować. Przydatne kategorie obejmują:

  • Wyjście tekstowe
  • Odmowy
  • Wywołania funkcji
  • Wyniki funkcji przesłane przez aplikację
  • Podsumowania lub metadane związane z rozumowaniem, jeśli są dostępne
  • Odniesienia do plików
  • Wyszukiwanie w Internecie, wyszukiwanie plików, korzystanie z komputera lub inne zdarzenia udostępniane w ramach narzędzi
  • Ostateczne wykorzystanie i metadane rozliczeniowe

Chodzi o to, aby nie udostępniać użytkownikom zastrzeżonego schematu. Chodzi o to, aby brama nie wyrzuciła informacji, zanim będzie mogła je sprawdzić, rozliczyć, przesłać strumieniowo, odtworzyć lub przekształcić.

Utwórz księgę stanową należącą do bramy

previous_response_id to pole, które najlepiej ukazuje różnicę między bezstanowym proxy czatu a zgodnością z odpowiedziami. Jeśli klient odwołuje się do poprzedniej odpowiedzi, brama musi wiedzieć, co oznacza ten identyfikator, czy dzierżawca może z niego korzystać i czy dostawca może z niego kontynuować.

Utwórz księgę stanu z kluczem według najemcy i identyfikatora odpowiedzi:

{
  "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",
  "model": "gpt-...",
  "provider": "openai",
  "store_mode": "provider|gateway|none",
  "retention_policy": "standard|zero_retention|custom_30d",
  "instructions_hash": "sha256:...",
  "tool_policy_id": "tools_readonly_v3",
  "created_at": "...",
  "expires_at": "...",
  "deleted_at": null
}

Ważna zasada: nie emuluj automatycznie previous_response_id, odtwarzając pełną historię czatów, chyba że najemca wyraźnie zezwolił na takie zachowanie i koszty. Powtórka może zwiększyć koszt tokena, zmienić poziom prywatności i zmienić zachowanie modelu. Bezpieczniej jest zwrócić wyraźny błąd możliwości, niż dyskretnie wysłać zapisaną treść konwersacji, której aplikacja nie spodziewała się zachować lub ponownie wykorzystać.

Tryby obsługi stanu

  • Stan dostawcy: Dostawca nadrzędny przechowuje wystarczającą ilość kontekstu, a brama mapuje identyfikatory odpowiedzi bramy na identyfikatory odpowiedzi dostawcy.
  • Stan bramy: Brama przechowuje niezbędne elementy wcześniejsze i rekonstruuje kontekst, jeśli jest to dozwolone.
  • Brak stanu: W żądaniu zastosowano store=false lub zasady dzierżawy zabraniają przechowywania. previous_response_id należy odrzucić, chyba że dostawca może spełnić żądanie bez przechowywania bramy i zasady na to pozwalają.

Pamiętaj również, że może zaistnieć potrzeba ponownego przesłania przez klienta poprzednich instrukcji, gdy będą one nadal obowiązywać. Brama nie powinna wymyślać ukrytych instrukcji w celu rekompensaty, chyba że takie zachowanie jest częścią wyraźnych zasad najemcy.

Sprawdź narzędzia przed wysyłką

Responses sprawia, że korzystanie z narzędzi jest bardziej centralne. Warstwa zgodności powinna obsługiwać dwie szerokie kategorie:

  • Narzędzia aplikacji: Definicje funkcji dostarczone przez klienta, wykonywane poza dostawcą modelu, a wyniki przesyłane z powrotem do API.
  • Narzędzia dostawcy hostowanego: wyszukiwanie w Internecie, wyszukiwanie plików, korzystanie z komputera, wykonywanie kodu, uziemianie lub podobne narzędzia wykonywane przez dostawcę lub infrastrukturę kontrolowaną przez bramę.

Przy wejściu sprawdź schematy narzędzi przed routingiem:

  • Odrzuć wcześniej nieprawidłowy JSON schemat.
  • Wymuś maksymalny rozmiar schematu i głębokość zagnieżdżenia.
  • Sprawdź, czy nazwy narzędzi są zgodne z dostawcami.
  • Zastosuj zakresy dzierżawcy, klucza, użytkownika i środowiska.
  • Wymagaj bramek zatwierdzających w przypadku narzędzi, które zapisują dane, wydają pieniądze, uzyskują dostęp do wrażliwych systemów lub łączą się z zewnętrznymi łącznikami.

Do wywoływania funkcji aplikacji wymagany jest stabilny identyfikator wywołania. Model emituje wywołanie funkcji z call_id; aplikacja przesyła dane wyjściowe narzędzia odwołujące się do tego identyfikatora; brama rejestruje oba w tym samym śladzie. Bez tego klucza łączenia dzienniki kontroli i ponowne próby stają się niejednoznaczne.

W przypadku narzędzi hostowanych zarezerwuj budżet przed wysyłką i rozlicz koszty później. Hostowane narzędzia mogą dodawać opłaty poza zwykłym rozliczaniem tokenów, więc połącz księgę narzędzi z ujednoliconą sztuczną inteligencją API rozliczeniową, zamiast ukrywać te koszty w ogólnej sumie wywołań modelowych.

Normalizuj przesyłanie strumieniowe jako zdarzenia, a nie tekst tokena

Proxy czatu często może uniknąć różnic w tokenach przekazywania. Brama odpowiedzi nie może. Strumień ma znaczenie w cyklu życia: może rozpocząć się odpowiedź, elementy wyjściowe mogą się rozpocząć i zakończyć, tekst może pojawić się w postaci delt, wywołania narzędzi mogą być łączone przyrostowo, użycie może nastąpić na końcu lub w trakcie strumienia, a odpowiedź może zakończyć się niepowodzeniem lub zostać anulowana.

Zdefiniuj schemat zdarzenia bramy, a następnie zamapuj na niego strumień każdego dostawcy:

event: response_started
data: { "response_id": "gw_resp_123", "status": "in_progress" }

event: output_item_started
data: { "item_id": "item_1", "type": "text" }

event: text_delta
data: { "item_id": "item_1", "delta": "Hello" }

event: tool_call_delta
data: { "item_id": "item_2", "call_id": "call_abc", "arguments_delta": "{\"order" }

event: usage_delta
data: { "output_tokens": 12 }

event: completed
data: { "response_id": "gw_resp_123", "usage": { ... } }

Zalecane zdarzenia znormalizowane:

  • response_started
  • output_item_started
  • output_item_completed
  • text_delta
  • refusal_delta
  • tool_call_delta
  • tool_result_received
  • usage_delta
  • completed
  • cancelled
  • failed

Kiedy klient się rozłączy, propaguj anulowanie w górę łańcucha dostaw, jeśli dostawca to obsługuje. Zapisz stan częściowej odpowiedzi w dowolny sposób. Jeśli dostawca później zwróci ostateczne wykorzystanie w drodze opóźnionego wywołania zwrotnego lub ostatniej części, należy uzgodnić księgę. Zgodność przesyłania strumieniowego dotyczy zarówno rozliczania i cyklu życia, jak i opóźnień.

Utwórz matrycę możliwości dostawcy

Routing wielomodelowy jest użyteczny tylko wtedy, gdy brama rozumie, co może być bezpiecznie trasowane. Dodaj funkcje specyficzne dla Responses do swojego katalogu modeli:

{
  "model_alias": "agent-default",
  "routes": [
    {
      "provider": "openai",
      "model": "...",
      "supports_responses": true,
      "supports_previous_response_id": true,
      "supports_store_false": true,
      "supports_builtin_web_search": true,
      "supports_function_calling": true,
      "supports_stream_lifecycle_events": true,
      "supports_reasoning_context_continuity": true,
      "max_tool_schema_bytes": 65536
    },
    {
      "provider": "provider_b",
      "model": "...",
      "supports_responses": false,
      "chat_adapter_available": true,
      "loss_profile": ["no_previous_response_id", "no_hosted_tools", "flattened_stream"]
    }
  ]
}

Rezerwacja powinna uwzględniać straty. Jeśli żądanie wymaga wbudowanej wyszukiwarki internetowej, a dostawca zastępczy nie może go wykonać, nie odpowiadaj w trybie cichym bez wyszukiwania. Jeśli żądanie zależy od zachowanego kontekstu rozumowania i trasa rezerwowa nie może go zachować, zwróć błąd możliwości lub odpowiedź na obniżenie wersji, na którą klient wyraźnie wyraził zgodę.

Przydatna opcja żądania to:

{
  "model": "agent-default",
  "input": "...",
  "fallback_policy": {
    "allow_lossy": false,
    "allowed_losses": []
  }
}

W przypadku mniej wrażliwych przypadków użycia dzierżawcy mogą zezwolić na określone straty na niższą wersję:

{
  "fallback_policy": {
    "allow_lossy": true,
    "allowed_losses": ["flattened_stream", "no_reasoning_summary"]
  }
}

Brama powinna tak czy inaczej zarejestrować decyzję o powrocie. Dzięki temu możliwe jest późniejsze debugowanie, gdy agent zachowuje się inaczej po awarii dostawcy lub przekierowaniu modelu.

Wykorzystanie atrybutu na poziomie odpowiedzi i elementu

Rozmowy w odpowiedziach mogą kosztować więcej niż równoważne rozmowy na czacie, ponieważ mogą obejmować wykonanie narzędzia, dłuższy kontekst, tokeny rozumowania, wyszukiwanie plików, wyszukiwanie w Internecie lub powtarzane instrukcje. Pojedyncza zagregowana liczba tokenów nie wystarczy dla AI API pulpitu nawigacyjnego analizy użycia.

Rekord użycia na dwóch poziomach:

  • Poziom odpowiedzi: najemca, klucz, użytkownik, model, dostawca, opóźnienie, stan końcowy, tokeny wejściowe, tokeny wyjściowe, tokeny wnioskowania, jeśli zostały zgłoszone, całkowity koszt i trasa awaryjna.
  • Poziom elementu/narzędzia: nazwa narzędzia, identyfikator wywołania, hostowane jednostki narzędzi, identyfikatory plików, liczba zapytań, jeśli są dostępne, opóźnienie narzędzia, koszt narzędzia i wynik zasad zatwierdzania.

Dzięki temu programiści mogą odpowiadać na konkretne pytania:

  • Czy koszty wzrosły z powodu dłuższego stanu, wysiłku w zakresie rozumowania, wywołań narzędzi lub powrotu do stanu pierwotnego?
  • Który dzierżawca lub API klucz generuje opłaty za narzędzia hostowane?
  • Która odpowiedź nie powiodła się po wywołaniu narzędzia, ale przed końcowym tekstem?
  • Które anulowane transmisje nadal wiązały się z dodatkowym obciążeniem?

Zachowuj zera i usuwaj je jako zachowanie najwyższej klasy

Stan po stronie serwera jest pomocny, ale zmienia obowiązki przechowywania bramy. Wbuduj zasady w warstwę protokołu, zamiast traktować je jako ustawienie rejestrowania.

W przypadku każdego żądania Odpowiedzi rozwiąż:

  • Zasady przechowywania najemców
  • Poziom żądania store preferencja
  • Zgodność przechowywania dostawcy
  • Czy dozwolone jest odtwarzanie przez bramę
  • Czy można przechowywać dane wejściowe i wyjściowe narzędzia
  • Zachowanie związane z wygaśnięciem i usunięciem stanu odpowiedzi

Jeśli przechowywanie jest wyłączone, brama może nadal przechowywać minimalne metadane operacyjne: znaczniki czasu, identyfikatory, stan, liczbę tokenów, koszty i decyzje dotyczące zasad. Unikaj przechowywania nieprzetworzonych podpowiedzi, pełnych wyników narzędzi lub zrekonstruowanej historii, chyba że pozwalają na to zasady.

Urządzenia zapewniające zgodność, które należy dodać przed uruchomieniem

Nie polegaj na ręcznych testach Happy-path. Dodaj urządzenia weryfikujące zachowanie protokołu na trasach OpenAI bezpośrednich, trasach dostosowanych przez dostawcę i scenariuszach awaryjnych.

Minimalny zestaw testowy

  • Odpowiedź podstawowa: zwracany jest element tekstowy ze stabilnym identyfikatorem odpowiedzi i użyciem.
  • Stan wieloobrotowy: odniesienia do drugiego żądania previous_response_id; brama sprawdza własność dzierżawy i tryb stanu.
  • Powtarzane instrukcje: sprawdź, czy pominięte instrukcje nie zostały po cichu wymyślone przez bramę.
  • Wywołanie funkcji w obie strony: model emituje identyfikator wywołania; aplikacja przesyła dane wyjściowe; ostateczna odpowiedź łączy oba rekordy.
  • Zasady dotyczące narzędzi hostowanych: nieautoryzowane wbudowane narzędzie jest blokowane przed wysłaniem.
  • Kolejność przesyłania strumieniowego: początek odpowiedzi, początek elementu, różnice, zakończenie elementu, użycie i zakończenie są emitowane w prawidłowej kolejności.
  • Anulowanie strumienia: rozłączenie klienta powoduje anulowanie transmisji nadrzędnej, jeśli jest to możliwe, i rejestruje częściowe wykorzystanie.
  • Odrzucenie zastępcze: dostawca bez wymaganej semantyki odpowiedzi zwraca błąd możliwości.
  • Zgoda na rezerwę stratną: żądanie z dozwolonymi stratami otrzymuje wyraźny znacznik obniżenia wersji.
  • Tryb zerowego przechowywania: odtwarzanie stanu i zachowywanie monitów po stronie bramy są zablokowane.

Zalecana sekwencja wdrażania

  1. Udostępnij trasę wersji beta. Dodaj /v1/responses bez zmiany istniejącego zachowania czatu.
  2. Najpierw zaimplementuj przekazywanie dla dostawców z natywną obsługą odpowiedzi. Zachowaj identyfikatory, elementy, strumienie, użycie i błędy.
  3. Dodaj księgę stanu. Mapuj identyfikatory bram na identyfikatory dostawców i egzekwuj własność dzierżawcy.
  4. Dodaj elementy kanoniczne. Przechowuj metadane elementów potrzebne do kontroli, rozliczeń i rekonstrukcji strumienia.
  5. Dodaj zarządzanie narzędziami. Sprawdzaj poprawność schematów, egzekwuj zakresy i rejestruj połączenia wywołań narzędzi.
  6. Dodaj normalizację przesyłania strumieniowego. Konwertuj strumienie specyficzne dla dostawcy na zdarzenia cyklu życia bramy.
  7. Dodaj routing uwzględniający możliwości. Domyślnie zezwalaj tylko na bezpieczne połączenia awaryjne.
  8. Dodaj statystyki i rozliczenia. Oddzielnie token atrybutu, uzasadnienie i użycie narzędzia.
  9. Opublikuj uwagi dotyczące zgodności. Poinformuj programistów, które pola są natywne, emulowane, nieobsługiwane lub stratne.

Wniosek, który można zastosować

Warstwa zgodności API powinna zachować znaczenie protokołu, a nie tylko zwracać wiarygodny tekst. Zbuduj go wokół pięciu trwałych obiektów: kanonicznego modelu pozycji odpowiedzi, księgi stanów konwersacji, księgi wywołań narzędzi, normalizatora zdarzeń przesyłania strumieniowego i macierzy możliwości dostawcy.

Najbezpieczniejszym ustawieniem domyślnym jest ścisła zgodność: jeśli trasa nie może zachować wymaganego stanu, narzędzi, kontekstu rozumowania, zdarzeń strumieniowych lub zachowania związanego z przechowywaniem, zwróć wyraźny błąd możliwości. Dodaj opcjonalną stratną rezerwę rezerwową tylko wtedy, gdy programiści zrozumieją, co zostanie porzucone. Takie podejście może wydawać się mniej wygodne niż automatyczne spłaszczanie, ale zapobiega najgorszemu trybowi awarii: aplikacji, która wydaje się kompatybilna, a jednocześnie cicho traci semantykę, która sprawiła, że ​​w pierwszej kolejności korzystała z odpowiedzi API.

Powiązane lektury

FAQ

Często zadawane pytania

Czy brama może wdrożyć interfejs Responses API, tłumacząc wszystko na Chat Completions?
Tylko dla wąskiego, stratnego podzbioru. Podstawowe generowanie tekstu może działać, ale stan, elementy odpowiedzi, hostowane narzędzia, kontekst związany z rozumowaniem, struktura odmów, zdarzenia cyklu życia strumienia i użycie na poziomie elementu mogą zostać utracone. Brama produkcyjna powinna udostępniać odpowiedzi jako oddzielną powierzchnię zgodności.
Czy brama powinna odtwarzać zapisaną historię czatów, aby emulować previous_response_id?
Nie domyślnie. Powtórka zmienia sposób przechowywania, koszt, a czasami model zachowania. Dzierżawca powinien jawnie zezwolić na przechowywanie i odtwarzanie stanu po stronie bramy, zanim brama użyje tej strategii.
Co powinno się stać, gdy dostawcy rezerwowi nie mogą obsługiwać semantyki odpowiedzi?
Najbezpieczniejszym ustawieniem domyślnym jest błąd możliwości. Jeśli dzierżawca zdecyduje się na stratną rezerwę, brama powinna zwrócić wyraźny znacznik obniżenia wersji i zapisać, która semantyka została porzucona.
Po co rejestrować użycie na poziomie elementu odpowiedzi?
Wywołania odpowiedzi mogą obejmować wywołania narzędzi, opłaty za narzędzia hostowane, tokeny wnioskowania, strumienie częściowe i zachowanie awaryjne. Użycie na poziomie elementu ułatwia wyjaśnienie rozliczeń, debugowania i analiz dzierżawy.