Ghid și perspectivă

Construiți un strat de compatibilitate API Responses într-un Gateway API AI

Un gateway API Responses nu este doar un proxy Chat Completions cu o rută nouă. Păstrați elementele de răspuns, starea, apelurile de instrumente, fluxurile, continuitatea raționamentului, atribuirea utilizării și comportamentul de downgrade cu un nivel de compatibilitate de primă clasă.

Nu implementați /v1/responses traducând fiecare solicitare în /v1/chat/completions și sperând că forma este suficient de apropiată. Acest adaptor poate returna text, dar poate pierde în tăcere părțile care le interesează dezvoltatorilor: elemente de răspuns, stare la nivel de server, apeluri de instrumente, continuitate raționamentului, evenimente ciclului de viață al fluxului, semantică de anulare și atribuire de utilizare la nivel de articol.

Obiectivul practic este un strat de compatibilitate care tratează API-ul Responses ca pe un protocol mai bogat. Păstrați suportul pentru Finalizările de chat pentru clienții existenți, dar construiți răspunsurile ca propria suprafață de poartă cu propriul model de stare, normalizator de flux, registru de apeluri de instrumente, matrice de capabilități și reguli de rezervă.

Ce este fapt, ce este politica și ce este predicție?

Fapte: OpenAI descrie API-ul Responses ca fiind capabilități unificatoare care au fost împărțite anterior între Terminări de chat și Asistente, inclusiv suport pentru instrumente precum căutarea pe web, căutarea de fișiere și utilizarea computerului. API-ul expune câmpuri precum previous_response_id, streaming, selecția instrumentelor și instrumentele încorporate. Documentația SDK arată că previous_response_id poate oferi continuitate conversației, în timp ce instrucțiunile anterioare nu sunt reportate automat și trebuie retrimise atunci când ar trebui să se aplice în continuare. Referința de streaming OpenAI include ciclul de viață al răspunsului distinct și evenimente de ieșire, mai degrabă decât doar delte de simboluri.

Recomandări: un gateway ar trebui să păstreze această semantică în loc să le aplatizeze în mod implicit. Ar trebui să respingă sau să reducă în mod explicit cererile atunci când un furnizor țintă nu poate suporta comportamentul necesar.

Predicție: mai multe încărcături de lucru ale agenților vor depinde de structura elementului de răspuns, de urmele de execuție a instrumentului și de contextul raționamentului precis. Gateway-urile care modelează aceste concepte acum vor fi mai ușor de extins decât gateway-urile care tratează răspunsurile ca un punct final cosmetic.

Definiți un contract de compatibilitate separat pentru răspunsuri

Prima greșeală de implementare este să presupunem că compatibil OpenAI înseamnă o singură schemă universală de solicitare și răspuns. În practică, /v1/chat/completions și /v1/responses ar trebui să fie contracte de compatibilitate separate.

Păstrați un nivel comun de autentificare, facturare, cotă și rutare, dar separați nivelul de protocol:

  • Apar Terminările de chat: mesaje, opțiuni, delte, apeluri de instrumente în format chat, comportamentul clientului vechi.
  • Apar răspunsurile: elemente de intrare, elemente de ieșire, ID-uri de răspuns, referințe de răspuns anterioare, evenimente de instrumente mai bogate, evenimente din fluxul de viață, câmpuri legate de raționament și starea finală a răspunsului.

Această diviziune contează pentru testele de conformitate. Un adaptor de furnizor care trece testele de chat poate eșua în continuare testele de răspunsuri, deoarece nu poate păstra previous_response_id, comanda articolelor, structura de refuz, metadatele instrumentelor găzduite sau numele evenimentelor în flux.

Un contract de compatibilitate minimă ar trebui să răspundă:

  • Ce câmpuri de solicitare sunt acceptate, respinse, transformate sau ignorate?
  • Ce tipuri de elemente de răspuns sunt păstrate?
  • Ce tipuri de instrumente sunt acceptate pentru fiecare furnizor și model?
  • Poate furnizorul să mențină starea conversației sau trebuie să o mențină gateway-ul?
  • Ce se întâmplă când se solicită store=false?
  • Ce evenimente în flux sunt garantate?
  • Cum sunt înregistrate anularea, expirarea timpului și utilizarea parțială?

Dacă aveți deja un gateway API AI, tratați suportul pentru răspunsuri ca o extindere a protocolului, nu un alias de rută.

Utilizați un model de răspuns canonic

API-ul Responses returnează mai mult de un mesaj de asistent. Poate reprezenta diferite elemente de ieșire și evenimente. Gateway-ul dvs. are nevoie de un model canonic intern înainte de a fi mapat la orice furnizor.

O schemă practică de articol intern poate începe astfel:

{
  "gateway_response_id": "gw_resp_...",
  "provider_response_id": "resp_...",
  "tenant_id": "ten_123",
  "key_id": "key_456",
  "model_alias": "agent-implicit",
  "furnizor": "openai",
  „articole”: [
    {
      "item_id": "item_1",
      "type": "text",
      "rol": "asistent",
      "conținut": [{ "type": "output_text", "text": "..." }],
      "status": "finalizat"
    },
    {
      "item_id": "item_2",
      "type": "function_call",
      "call_id": "call_abc",
      "nume": "comanda_căutare",
      "arguments_json": "{\"order_id\":\"123\"}",
      "status": "finalizat"
    }
  ],
  „utilizare”: {
    „input_tokens”: 0,
    „output_tokens”: 0,
    „resoning_tokens”: nul,
    „tool_units”: []
  },
  "status": "finalizat"
}

Includeți tipurile de articole chiar înainte ca fiecare furnizor să le poată produce. Categoriile utile includ:

  • Ieșire text
  • Refuzuri
  • Apeluri de funcții
  • Ieșiri ale funcției trimise de aplicație
  • Rezumate de raționament sau metadate legate de raționament, acolo unde sunt disponibile
  • Referințe la fișiere
  • Căutare pe web, căutare de fișiere, utilizarea computerului sau alte evenimente de instrumente găzduite
  • Utilizarea finală și metadatele de facturare

Ideea este să nu expuneți utilizatorilor o schemă proprietară. Ideea este să împiedicați gateway-ul să arunce informații înainte de a le putea audita, factura, transmite în flux, reda sau transforma.

Creați un registru de stat deținut de gateway

previous_response_id este câmpul care expune cel mai mult diferența dintre proxy-ul de chat fără stat și compatibilitatea cu răspunsurile. Dacă un client face referire la un răspuns anterior, gateway-ul trebuie să știe ce înseamnă acel ID, dacă chiriașului i se permite să-l folosească și dacă furnizorul poate continua de la acesta.

Creați un registru de stat codat de locatar și ID de răspuns:

{
  "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-...",
  "furnizor": "openai",
  "store_mode": "furnizor|gateway|niciun",
  "retention_policy": "standard|zero_retention|custom_30d",
  "instructions_hash": "sha256:...",
  "tool_policy_id": "tools_readonly_v3",
  "created_at": "...",
  "expires_at": "...",
  „deleted_at”: nul
}

Regulă importantă: nu emulați automat previous_response_id reluând istoricul complet al chat-ului decât dacă locatarul a permis în mod explicit acel comportament de reținere și cost. Reluarea poate crește costul tokenului, poate schimba postura de confidențialitate și poate modifica comportamentul modelului. Este mai sigur să returnați o eroare clară de capacitate decât să trimiteți în tăcere conținutul de conversație stocat pe care aplicația nu se aștepta să îl păstrați sau să îl reutilizați.

Moduri de gestionare a stării

  • Starea furnizorului: furnizorul din amonte stochează suficient context, iar gateway-ul mapează ID-urile de răspuns ale gateway-ului la ID-urile de răspuns ale furnizorului.
  • Starea gateway-ului: gateway-ul stochează elementele anterioare necesare și reconstruiește contextul atunci când este permis.
  • Fără stare: solicitarea folosește store=false sau politica chiriașilor interzice păstrarea. previous_response_id ar trebui respins, cu excepția cazului în care furnizorul poate onora cererea fără reținerea gateway-ului și politica permite acest lucru.

De asemenea, rețineți că instrucțiunile anterioare ar putea trebui să fie retrimise de către client atunci când ar trebui să continue să se aplice. Gateway-ul nu ar trebui să inventeze instrucțiuni ascunse pentru a compensa, decât dacă acel comportament face parte dintr-o politică explicită a chiriașilor.

Validați instrumentele înainte de expediere

Răspunsurile fac ca utilizarea instrumentului să fie mai centrală. Un strat de compatibilitate ar trebui să gestioneze două categorii largi:

  • Instrumente de aplicație: definiții de funcții furnizate de client, executate în afara furnizorului de model, cu rezultate trimise înapoi către API.
  • Instrumente pentru furnizorul găzduit: căutarea pe web, căutarea de fișiere, utilizarea computerului, execuția codului, punerea la pământ sau instrumente similare executate de furnizor sau de infrastructura controlată de gateway.

La intrare, validați schemele instrumentelor înainte de rutare:

  • Respingeți mai devreme schema JSON nevalidă.
  • Implementați dimensiunea maximă a schemei și adâncimea de imbricare.
  • Verificați numele instrumentelor pentru compatibilitatea furnizorilor.
  • Aplicați domeniile locatar, cheie, utilizator și mediu.
  • Solicită porți de aprobare pentru instrumentele care scriu date, cheltuiesc bani, accesează sisteme sensibile sau apelează conectori externi.

Pentru apelarea funcției de aplicație, aveți nevoie de un ID de apel stabil. Modelul emite un apel de funcție cu call_id; aplicația trimite rezultatul instrumentului care face referire la acel ID; gateway-ul le înregistrează pe ambele în aceeași urmă. Fără acea cheie de conectare, jurnalele de audit și reîncercările devin ambigue.

Pentru instrumentele găzduite, rezervați bugetul înainte de expediere și stabiliți costurile după aceea. Instrumentele găzduite pot adăuga taxe în afara contabilității obișnuite cu simboluri, așa că conectați registrul de instrumente la facturarea API unificată AI, în loc să ascundeți aceste costuri într-un total de apeluri de model generic.

Normalizează fluxul ca evenimente, nu text simbol

Un proxy de chat poate scăpa deseori cu delte de simboluri de redirecționare. Un gateway Responses nu poate. Fluxul are sensul ciclului de viață: un răspuns poate începe, elementele de ieșire pot începe și finaliza, textul poate ajunge în delte, apelurile de instrumente pot fi asamblate progresiv, utilizarea poate ajunge la sfârșit sau în timpul fluxului, iar răspunsul poate eșua sau poate fi anulat.

Definiți o schemă de eveniment gateway, apoi mapați fiecare flux de furnizor în ea:

eveniment: response_started
date: { "response_id": "gw_resp_123", "status": "în_progres" }

eveniment: output_item_starteddate: { "item_id": "item_1", "type": "text" }

eveniment: text_delta
date: { "item_id": "item_1", "delta": "Bună ziua" }

eveniment: tool_call_delta
date: { "item_id": "item_2", "call_id": "call_abc", "arguments_delta": "{\"order" }

eveniment: usage_delta
date: { "output_tokens": 12 }

eveniment: finalizat
date: { "response_id": "gw_resp_123", "usage": { ... } }

Evenimente normalizate recomandate:

  • response_started
  • output_item_started
  • output_item_completed
  • text_delta
  • refusal_delta
  • tool_call_delta
  • tool_result_received
  • utilisation_delta
  • finalizat
  • anulat
  • eșuat

Când clientul se deconectează, propagați anularea în amonte dacă furnizorul o acceptă. Înregistrați starea răspunsului parțial în orice mod. Dacă furnizorul returnează ulterior utilizarea finală printr-un apel invers întârziat sau o bucată finală, reconciliați registrul. Compatibilitatea în flux se referă atât la contabilitate și ciclul de viață, cât și la latență.

Creați o matrice a capacităților furnizorului

Rutarea cu mai multe modele este utilă numai atunci când gateway-ul înțelege ce poate fi rutat în siguranță. Adăugați capabilități specifice răspunsurilor la catalogul dvs. de modele:

{
  "model_alias": "agent-implicit",
  "rute": [
    {
      "furnizor": "openai",
      "model": "...",
      „supports_responses”: adevărat,
      „supports_previous_response_id”: adevărat,
      „supports_store_false”: adevărat,
      „supports_builtin_web_search”: adevărat,
      „supports_function_calling”: adevărat,
      „supports_stream_lifecycle_events”: adevărat,
      „supports_reasoning_context_continuity”: adevărat,
      „max_tool_schema_bytes”: 65536
    },
    {
      "provider": "provider_b",
      "model": "...",
      „supports_responses”: fals,
      „chat_adapter_available”: adevărat,
      "loss_profile": ["no_previous_response_id", "no_hosted_tools", "flattened_stream"]
    }
  ]
}

Fallback ar trebui să fie conștient de pierderi. Dacă solicitarea necesită căutare încorporată pe web și furnizorul de rezervă nu o poate efectua, nu răspundeți în tăcere fără căutare. Dacă solicitarea depinde de contextul de raționament păstrat și ruta de rezervă nu o poate păstra, returnați o eroare de capacitate sau un răspuns de downgrade pentru care clientul a optat în mod explicit.

O opțiune de solicitare utilă este:

{
  "model": "agent-implicit",
  "input": "...",
  „politica de rezervă”: {
    „allow_lossy”: fals,
    „pierderi_permise”: []
  }
}

Pentru cazuri de utilizare mai puțin sensibile, chiriașii pot permite anumite downgrade cu pierderi:

{
  „politica de rezervă”: {
    „allow_losssy”: adevărat,
    "allowed_loses": ["flattened_stream", "no_reasoning_summary"]
  }
}

Poarta de acces ar trebui să înregistreze decizia de rezervă în orice mod. Acest lucru face posibilă depanarea ulterioară atunci când un agent se comportă diferit după o întrerupere a furnizorului sau o redirecționare a modelului.

Utilizarea atributelor la nivel de răspuns și articol

Apelurile cu răspunsuri pot costa mai mult decât finalizarea chatului echivalent, deoarece pot include execuția instrumentului, context mai lung, indicative de raționament, căutare de fișiere, căutare pe web sau instrucțiuni repetate. Un singur număr agregat de simboluri nu este suficient pentru un tabloul de bord de analiză a utilizării API AI.

Înregistrați utilizarea la două niveluri:

  • Nivel de răspuns: chiriaș, cheie, utilizator, model, furnizor, latență, stare finală, indicative de intrare, indicative de ieșire, indicative de raționament unde au fost raportate, costul total și ruta de rezervă.
  • Nivel articol/instrument: numele instrumentului, ID de apel, unități de instrumente găzduite, ID-uri de fișiere, numărul de interogări de căutare, dacă este disponibil, latența instrumentului, costul instrumentului și rezultatul politicii de aprobare.

Acest lucru le permite dezvoltatorilor să răspundă la întrebări concrete:

  • Au crescut costurile din cauza stării mai lungi, a efortului de raționament, a apelurilor la instrumente sau a retragerii?
  • Ce chiriaș sau cheie API generează taxe pentru instrumentul găzduit?
  • Ce răspuns a eșuat după un apel de instrument, dar înainte de textul final?
  • Care streamuri anulate au fost încă utilizate în amonte?

Tratați reținerea și ștergerea zero ca un comportament de primă clasă

Starea de pe server este utilă, dar modifică obligațiile de păstrare ale gateway-ului. Creați o politică în stratul de protocol în loc să o tratați ca pe o setare de înregistrare.

Pentru fiecare solicitare de răspunsuri, rezolvați:

  • Politica de păstrare a chiriașilor
  • Preferința magazin la nivel de solicitare
  • Compatibilitate cu păstrarea furnizorilor
  • Dacă este permisă reluarea gateway-ului
  • Dacă intrările și ieșirile instrumentului pot fi stocate
  • Comportamentul de expirare și ștergere pentru starea răspunsului

Dacă reținerea este dezactivată, gateway-ul poate păstra în continuare metadate operaționale minime: marcaje de timp, ID-uri, stare, număr de simboluri, cost și decizii de politică. Evitați stocarea solicitărilor brute, a rezultatelor complete ale instrumentului sau a istoricului reconstruit, cu excepția cazului în care politica o permite.

Dispozitive de conformitate de adăugat înainte de lansare

Nu vă bazați pe testele manuale ale drumului fericit. Adăugați dispozitive care verifică comportamentul protocolului pe rute OpenAI directe, rute adaptate de furnizor și scenarii de rezervă.

Setul minim de testare

  • Răspunsul de bază: textul este returnat cu un ID de răspuns stabil și cu utilizarea.
  • Starea cu mai multe viraj: a doua cerere se referă la previous_response_id; gateway-ul validează proprietatea chiriașului și modul de stare.
  • Instrucțiuni repetate: verificați dacă instrucțiunile omise nu sunt inventate în tăcere de către gateway.
  • Apel de funcție dus-întors: modelul emite ID de apel; cererea trimite rezultate; răspunsul final unește ambele înregistrări.
  • Politica instrumentului găzduit: instrumentul încorporat neautorizat este blocat înainte de expediere.
  • Ordinea de difuzare în flux: începerea răspunsului, începutul articolului, deltele, finalizarea articolului, utilizarea și finalizarea sunt emise în ordine validă.
  • Anularea fluxului: deconectarea clientului declanșează anularea în amonte acolo unde este acceptată și înregistrează utilizarea parțială.
  • Respingere alternativă: furnizorul fără semantica răspunsurilor necesară returnează o eroare de capacitate.
  • Înscriere cu pierderi de rezervă: solicitarea cu pierderi permise primește un marcator explicit de downgrade.
  • Modul de reținere zero: reluarea stării și reținerea promptului la gateway sunt blocate.

Secvență de lansare recomandată

  1. Expuneți o rută beta. Adăugați /v1/responses fără a modifica comportamentul de chat existent.
  2. Implementați mai întâi transferul pentru furnizorii cu suport nativ pentru răspunsuri. Păstrați ID-urile, articolele, fluxurile, utilizarea și erorile.
  3. Adăugați registrul de stat. Hartați ID-urile gateway-ului la ID-urile furnizorilor și impuneți calitatea de proprietar al chiriașilor.
  4. Adăugați articole canonice. Stocați metadatele articolului necesare pentru auditare, facturare și reconstrucția fluxului.
  5. Adăugați guvernanța instrumentului. Validați schemele, aplicați domeniile și înregistrați îmbinările instrument-apel.
  6. Adăugați normalizarea fluxului. Convertiți fluxurile specifice furnizorului în evenimente ciclului de viață al gateway-ului.
  7. Adăugați o rutare care să țină cont de capabilități. Permiteți numai alternative sigure în mod prestabilit.
  8. Adăugați analize și decontare a facturării. Atribuiți separat simbolul, raționamentul și utilizarea instrumentului.
  9. Publicați note de compatibilitate. Spuneți dezvoltatorilor care câmpuri sunt native, emulate, neacceptate sau cu pierderi.

Concluzie acționabilă

Un strat de compatibilitate cu API-ul Responses ar trebui să păstreze semnificația protocolului, nu doar să returneze text plauzibil. Construiți-l în jurul a cinci obiecte durabile: un model de articol de răspuns canonic, un registru de stare a conversației, un registru de apeluri de instrumente, un normalizator de evenimente de streaming și o matrice de capabilități ale furnizorului.

Cea mai sigură variantă implicită este compatibilitatea strictă: dacă o rută nu poate păstra starea necesară, instrumentele, contextul de raționament, evenimentele de flux sau comportamentul de reținere, returnați o eroare clară de capacitate. Adăugați opt-in cu pierdere de rezervă numai atunci când dezvoltatorii înțeleg ce va fi renunțat. Această abordare poate fi mai puțin convenabilă decât aplatizarea automată, dar previne cel mai grav mod de eșec: o aplicație care pare compatibilă în timp ce pierde în tăcere semantica care a făcut-o să folosească API-ul Responses în primul rând.

Lectură similară

  • annulation-token/streaming manipulare
FAQ

Întrebări frecvente

Poate un gateway să implementeze API-ul Responses traducând totul în Chat Completions?
Doar pentru un subset îngust, cu pierderi. Generarea de bază a textului poate funcționa, dar starea, elementele de răspuns, instrumentele găzduite, contextul legat de raționament, structura de refuz, evenimentele ciclului de viață al fluxului și utilizarea la nivel de articol se pot pierde. Un gateway de producție ar trebui să expună răspunsurile ca o suprafață de compatibilitate separată.
Ar trebui gateway-ul să redă istoricul de chat stocat pentru a emula previous_response_id?
Nu implicit. Reluarea modifică comportamentul de reținere, costul și, uneori, comportamentul modelului. Chiriașul ar trebui să permită în mod explicit păstrarea și reluarea stării la nivelul gateway-ului înainte ca gateway-ul să folosească acea strategie.
Ce ar trebui să se întâmple atunci când furnizorii de rezervă nu pot accepta semantica răspunsurilor?
Cel mai sigur implicit este o eroare de capacitate. Dacă chiriașul optează pentru fallback cu pierderi, gateway-ul ar trebui să returneze un marcator explicit de downgrade și să înregistreze ce semantică a fost abandonată.
De ce să înregistrați utilizarea la nivel de răspuns?
Apelurile de răspuns pot include apeluri pentru instrumente, taxe pentru instrumente găzduite, indicative de raționament, fluxuri parțiale și comportament de rezervă. Utilizarea la nivel de articol face ca facturarea, depanarea și analiza chiriașilor să fie explicabile.