Pereiti prie pagrindinio turinio
OpenAI

2026 m. balandžio 22 d.

Inžinerija

Agentinių darbo eigų spartinimas „Responses API“ sąsajoje naudojant „WebSockets“

Autoriai: Brian Yu ir Ashwin Nathan, techninio personalo nariai

Įkeliama...

Kai paprašote „Codex“ ištaisyti klaidą, jis nuskaito jūsų kodo bazę ieškodamas susijusių failų, perskaito juos kontekstui sukurti, atlieka pakeitimus ir paleidžia testus, kad patikrintų, ar pataisymas suveikė. Techniškai tai reiškia dešimtis „Responses API“ užklausų: nustatyti kitą modelio veiksmą, kompiuteryje paleisti priemonę, gautą išvestį grąžinti į API ir viską pakartoti.

Dėl šių užklausų naudotojams gali tekti laukti ištisas minutes, kol „Codex“ atliks sudėtingas užduotis. Kalbant apie vėlavimą, ilgiausiai trunka trys pagrindiniai „Codex“ agento ciklo etapai: API paslaugų apdorojimas (užklausoms patvirtinti ir apdoroti), modelio vykdymas ir kliento pusės procesai (priemonėms paleisti ir modelio kontekstui kurti). Modelio vykdymas – tai etapas, kai modelis grafikos procesoriuose (angl. „Graphics Processing Unit“, GPU) generuoja naujus žetonus. Anksčiau didelių kalbos modelių (angl. „Large Language Model“, LLM) vykdymas GPU buvo lėčiausia agento ciklo dalis, todėl API paslaugų pridėtinė apkrova buvo beveik nepastebima. Spartėjant modelio vykdymui, bendra agento ciklo API apkrova tampa kur kas labiau pastebima.

Šiame įraše paaiškinsime, kaip API sąsajoje 40 % paspartinome agentų ciklus (nuo pradžios iki pabaigos) ir leidome naudotojams pajusti modelio vykdymo greičio šuolį nuo 65 iki beveik 1 000 žetonų per sekundę. Tai pasiekėme pasitelkę spartinančiąją atmintį, pašalinę nereikalingus tinklo šuolius, patobulinę saugos sistemą, kad problemas būtų galima pažymėti greičiau, ir, svarbiausia, sukūrę būdą užmegzti nuolatinį ryšį su „Responses API“, užuot vykdę daugybę sinchroninių API iškvietimų.

Diagrama pavadinimu „‚Codex‘ agento ciklas praktikoje“, kurioje rodomas iteracinis procesas tarp „Codex“ ir „Responses API“, kai keičiamasi priemonės iškvietimais („rg“, „sed“, „apply_patch“, „pytest“) ir rezultatais iki pat galutinio pranešimo: „Klaida buvo ištaisyta.“

Kai API tapo kliuviu

„Responses API“ sąsajoje ankstesni pavyzdiniai modeliai, pavyzdžiui, GPT‑5 ir GPT‑5.2, veikė maždaug 65 žetonų per sekundę (angl. „Tokens Per Second“, TPS) greičiu. Pristatydami GPT‑5.3‑Codex‑Spark – greitą programavimo modelį – užsibrėžėme tikslą keleriopai padidinti greitį: pasiekti daugiau nei 1 000 TPS. Tai padaryti leido speciali „Cerebras“ aparatinė įranga, optimizuota LLM vykdymui. Kad naudotojai galėtų pajusti tikrąjį šio naujojo modelio greitį, turėjome sumažinti API pridėtinę apkrovą.

Maždaug 2025 m. lapkritį pradėjome „Responses API“ našumo didinimo etapą ir įdiegėme daugybę optimizacijų, susijusių su vienos užklausos kritinio kelio vėlavimu:

  • atvaizduotų žetonų ir modelio konfigūracijos saugojimas atmintyje, siekiant išvengti sudėtingo skaidymo į žetonus ir tinklo užklausų daugiapakopiams atsakymams;
  • tinklo šuolių vėlavimo mažinimas pašalinant kreipimąsi į tarpines paslaugas (pavyzdžiui, vaizdo raiškos apdorojimo paslaugą) ir tiesiogiai kreipiantis į pačią modelio vykdymo paslaugą;
  • saugos sistemos tobulinimas, leidžiantis paleisti tam tikrus klasifikatorius, kad pokalbiai būtų pažymimi greičiau.

Dėl šių patobulinimų pirmojo žetono gavimo laikas (angl. „Time To First Token“, TTFT), parodantis, kaip greitai reaguoja API, sutrumpėjo beveik 45 %, tačiau GPT‑5.3‑Codex‑Spark modeliui to vis dar nepakako. Net ir po šių patobulinimų „Responses API“ pridėtinė apkrova buvo per didelė, palyginti su modelio greičiu – vadinasi, naudotojams teko laukti, kol centriniai procesoriai (angl. „Central Processing Unit“, CPU) apdoros API užklausas, ir tik tuomet jie galėjo naudotis modelį aptarnaujančiais grafikos procesoriais (GPU).

Gilesnė problema buvo struktūrinė: kiekvieną „Codex“ užklausą laikėme nepriklausoma ir su kiekviena tolesne užklausa iš naujo apdorodavome pokalbio būseną bei kitą pakartotinai naudojamą kontekstą. Net kai didžioji pokalbio dalis nesikeisdavo, vis tiek gaišome laiką apdorodami visą jo istoriją. Ilgėjant pokalbiams, šis pakartotinis apdorojimas reikalavo vis daugiau resursų.

Nuolatinio ryšio užmezgimas

Norėdami optimizuoti architektūrą, iš naujo apgalvojome perdavimo protokolą: ar galėtume palaikyti nuolatinį ryšį ir išsaugoti būseną atmintyje, užuot kaskart iš naujo užmezgę ryšį per HTTP ir su kiekviena tolesne užklausa siuntę visą pokalbio istoriją? Siekėme siųsti tik naują informaciją, kurią reikia patvirtinti ir apdoroti, o pakartotinai naudojamą būseną saugoti atmintyje tol, kol veikia ryšys. Tai sumažintų dėl perteklinio darbo atsirandančią apkrovą.

Svarstėme kelis skirtingus metodus, įskaitant „WebSockets“ ir „gRPC“ dvikryptį srautinį perdavimą. Pasirinkome „WebSockets“, nes tai paprastas pranešimų perdavimo protokolas, tad naudotojams nereikėtų keisti „Responses API“ įvesties ir išvesties formatų. Šis sprendimas buvo patogus kūrėjams ir be didesnių trikdžių įsiliejo į esamą architektūrą.

Pirmasis „WebSocket“ prototipas pakeitė mūsų požiūrį į tai, ką galima pasiekti mažinant „Responses API“ vėlavimą. Puikiai išmanydamas API infrastruktūrą, vienas „Codex“ komandos inžinierius vos per naktį sukūrė prototipą naudodamas „Codex“ agentą.

Šiame prototipe agentų ciklai buvo sumodeliuoti kaip vienas ilgai veikiantis atsakymas (angl. „Response“). Naudojant asyncio funkcijas, suformavus priemonės iškvietimą, „Responses API“ asinchroniškai sustabdydavo atrinkimo ciklą ir išsiųsdavo klientui atgalinį įvykį response.done. Įvykdę priemonės iškvietimą, klientai grąžindavo įvykį response.append su priemonės rezultatu – tai atblokuodavo atrinkimo ciklą ir leisdavo modeliui tęsti darbą.

Šis procesas prilygsta vietinės priemonės iškvietimo vertinimui kaip nuotolinės (priglobtosios). Kai modelis iškviečia paiešką saityne, modelio vykdymo ciklas sustoja, iškviečia saityno paieškos paslaugą ir įtraukia paslaugos atsakymą į modelio kontekstą. Mūsų architektūroje darėme tą patį, tačiau užuot iškvietę nuotolinę paslaugą, modelio priemonės iškvietimą grąžindavome klientui per „WebSocket“. Kai klientas atsakydavo, įtraukdavome jo priemonės iškvietimo atsakymą į kontekstą ir tęsdavome atrinkimą.

Ši struktūra buvo itin veiksminga, nes leido išvengti pasikartojančio API darbo per visą agento ciklą. Galėjome vieną kartą atlikti prieš modelio vykdymą būtinus veiksmus, sustabdyti procesą, kol bus panaudota priemonė, ir pačioje pabaigoje vieną kartą atlikti veiksmus po modelio vykdymo.

Deja, dėl to API formatas tapo neįprastas ir sudėtingesnis. Norėjome, kad kūrėjai galėtų lengvai įdiegti „WebSocket“ palaikymą ir jiems nereikėtų iš naujo kurti API integracijos pagal naują sąveikos modelį.

Įprastos API sąsajos išlaikymas ir laipsniškas infrastruktūros tobulinimas

Galutinėje versijoje grąžinome įprastą formatą: leista toliau naudoti response.create su tuo pačiu turiniu, o norint tęsti pokalbio kontekstą iš ankstesnio atsakymo būsenos – naudoti previous_response_id.

Užmezgus „WebSocket“ ryšį, serveris išsaugo ankstesnio atsakymo būseną ryšio lygmens atmintyje. Kai į tolesnę užklausą response.create įtraukiamas previous_response_id, užuot kūrę visą pokalbį iš naujo, gauname šią būseną iš atminties.

Ši atmintyje išsaugota būsena apima:

  • ankstesnį response objektą;
  • ankstesnius įvesties ir išvesties elementus;
  • priemonių apibrėžimus ir vardų sritis;
  • pakartotinai naudojamus atrinkimo artefaktus, pvz., anksčiau atvaizduotus žetonus.
Diagrama pavadinimu „Nuo nuoseklių užklausų iki persidengiančio vykdymo“, kurioje lyginamas nuoseklus užklausų procesas ir „WebSocket“ pagrįstas metodas, kai kelios užklausos persidengia patvirtinimo, veiksmų prieš modelio vykdymą, atrinkimo ir veiksmų po modelio vykdymo etapuose.

Pakartotinai naudodami atmintyje išsaugotą ankstesnio atsakymo būseną, galėjome įdiegti kelias svarbias optimizacijas:

  • dalis mūsų saugos klasifikatorių ir užklausų tvirtinimo priemonių apdoroja tik naują įvestį, o ne kaskart visą istoriją;
  • papildomi atvaizduoti žetonai saugomi atmintyje, todėl galime praleisti nereikalingą skaidymą į žetonus;
  • skirtingose užklausose pakartotinai naudojama išsaugota modelio parinkimo ir nukreipimo logika;
  • po modelio vykdymo einančių ir neblokuojančių užduočių, tokių kaip atsiskaitymas, vykdymas lygiagrečiai su vėlesnėmis užklausomis.

Tikslas buvo kiek įmanoma priartėti prie mažiausią pridėtinę apkrovą turinčio prototipo, tačiau išlaikyti tokį API formatą, kurį kūrėjai jau suprato ir kuriuo remdamiesi dirbo.

Naujo greičio standarto nustatymas

Po dviejų mėnesių intensyvaus „WebSocket“ režimo kūrimo, išleidome alfa versiją pagrindiniams programavimo agentų startuoliams, kad jie galėtų integruoti jį į savo infrastruktūrą ir saugiai padidinti srautą. Alfa versijos naudotojai buvo sužavėti ir pranešė apie iki 40 % išaugusį našumą(atsidaro naujame lange) savo agentų darbo eigose. Sulaukę teigiamų atsiliepimų apie alfa versiją, buvome pasirengę oficialiam pristatymui.

Išleidimo rezultatai buvo matomi iškart. „Codex“ greitai perkėlė didžiąją dalį savo „Responses API“ srauto į „WebSocket“ režimą ir pastebėjo reikšmingą vėlavimo sutrumpėjimą. Naudojant modelį GPT‑5.3‑Codex‑Spark, pasiekėme savo 1 000 TPS tikslą ir matėme šuolius iki 4 000 TPS. Tai įrodė, kad „Responses API“ gali neatsilikti nuo kur kas greitesnio modelio vykdymo realiomis srauto sąlygomis. Šis poveikis greitai išryškėjo ir kūrėjų bendruomenėje:

„WebSocket“ režimas – viena reikšmingiausių naujų „Responses API“ funkcijų nuo jos pristatymo 2025 m. kovo mėnesį. Glaudžiai bendradarbiaujant „OpenAI“ API ir „Codex“ komandoms, nuo idėjos iki jos įgyvendinimo realiomis sąlygomis praėjo vos kelios savaitės. Tai ne tik smarkiai sutrumpina vėlavimą agento cikle, bet ir patenkina augantį kūrėjų poreikį: greitėjant modelio vykdymui, su juo susijusios paslaugos bei sistemos taip pat turi veikti sparčiau, kad šią pažangą pajustų ir naudotojai.

Autoriai

Brian Yu ir Ashwin Nathan

Padėkos

Ypatinga padėka „Responses API“ ir „Codex“ komandoms, dirbusioms prie „WebSocket“ režimo kūrimo.