Preskočite na glavno vsebino
OpenAI

4. maj 2026

Tehnologija

Kako OpenAI v velikem obsegu zagotavlja glasovno UI z nizko latenco

Yi Zhang in William McDonald, člana tehničnega osebja

Glasovna UI deluje naravno le, če pogovor poteka s hitrostjo govora. Ko omrežje to ovira, ljudje to takoj slišijo kot nerodne premore, odrezane prekinitve ali zakasnjen vdor v govor. To je pomembno za glasovni ChatGPT, za razvijalce, ki gradijo z Realtime API, za agente, ki delujejo v interaktivnih delovnih tokovih, in za modele, ki morajo obdelovati zvok, medtem ko uporabnik še govori.

V obsegu, v kakršnem deluje OpenAI, to pomeni tri konkretne zahteve:

  • Globalni doseg za več kot 900 milijonov tedensko aktivnih uporabnikov
  • Hitra vzpostavitev povezave, da lahko uporabnik začne govoriti takoj ob začetku seje
  • Nizek in stabilen krožni čas prenosa medijev ter malo trepetanja in izgube paketov, da izmenjava govorjenja deluje tekoče

Ekipa pri OpenAI, odgovorna za interakcije z UI v realnem času, je pred kratkim prenovila naš sklad WebRTC, da bi odpravila tri omejitve, ki so se pri velikem obsegu začele prekrivati: zaključevanje medijev z enimi vrati na sejo se ne ujema dobro z infrastrukturo OpenAI, seje ICE (Interactive Connectivity Establishment) in DTLS (Datagram Transport Layer Security), ki hranijo stanje, potrebujejo stabilno lastništvo, globalno usmerjanje pa mora ohranjati nizko latenco prvega skoka. V tej objavi predstavljamo razdeljeno arhitekturo rele + sprejemno-oddajna enota (relay + transceiver), ki smo jo zgradili, da za odjemalce ohranimo standardno vedenje WebRTC, hkrati pa spremenimo način usmerjanja paketov znotraj infrastrukture OpenAI.

WebRTC nam omogoča izdelavo izdelkov z UI v realnem času

WebRTC je odprt standard za pošiljanje zvoka, videa in podatkov z nizko latenco med brskalniki, mobilnimi aplikacijami in strežniki. Pogosto ga povezujemo s klicanjem med enakovrednimi napravami, vendar je tudi praktična osnova za sisteme v realnem času med odjemalcem in strežnikom, saj standardizira zahtevne dele interaktivnih medijev: ICE za vzpostavljanje povezljivosti in prečkanje NAT (Network Address Translation), DTLS in SRTP (Secure Real-time Transport Protocol) za šifriran prenos, pogajanje o kodekih za stiskanje in dekodiranje zvoka, RTCP (Real-time Transport Control Protocol) za nadzor kakovosti ter funkcije na strani odjemalca, kot sta odpravljanje odmeva in medpomnjenje trepetanja.

Ta standardizacija je pomembna za izdelke z AI. Brez WebRTC bi vsak odjemalec potreboval drugačen odgovor na vprašanje, kako vzpostaviti povezljivost prek NAT-ov, šifrirati medije, se dogovoriti o kodekih (kodirnikih-dekodirnikih, izbranih za prenos in dekompresijo) in se prilagajati spreminjajočim se omrežnim razmeram. Z WebRTC lahko gradimo na protokolnem skladu, ki je že implementiran v brskalnikih in mobilnih platformah, svoje delo pa usmerimo v infrastrukturo, ki medije v realnem času povezuje z modeli.

Gradimo tudi na samem ekosistemu WebRTC, vključno z zrelimi odprtokodnimi implementacijami in standardizacijskim delom, ki skrbi, da so brskalniki, mobilne aplikacije in strežniki medsebojno združljivi. Temeljno delo Justina Ubertija (enega izmed prvotnih arhitektov WebRTC) in Seana DuBoisa (ustvarjalca in vzdrževalca Pion) je ekipam, kot je naša, omogočilo gradnjo na preizkušeni medijski infrastrukturi, namesto da bi na novo izumljali nizkonivojsko prenašanje, šifriranje in nadzor prezasedenosti. Veseli nas, da sta Justin in Sean zdaj naša sodelavca pri OpenAI in pomagata usmerjati, kako WebRTC in UI v realnem času še bolj povezujemo.

Za UI je najpomembnejša lastnost ta, da zvok prispe kot neprekinjen tok. Govoreči agent lahko začne prepisovati, sklepati, klicati orodja ali ustvarjati govor, medtem ko uporabnik še govori, namesto da čaka na celoten prenos. To je razlika med sistemom, ki deluje pogovorno, in takim, ki deluje kot pritisni-za-govor.

Izbira medijske arhitekture

Ko smo izbrali WebRTC, je bilo naslednje vprašanje, kje ga zaključiti (kje sprejmemo in prevzamemo povezavo WebRTC – na primer na robu) in kako te seje povezati z zalednim sistemom za sklepanje. To je pomembno, ker določa, kako obravnavamo stanje sej v realnem času, prenos medijev, usmerjanje, latenco in izolacijo napak.

Možnost 1: Pristop SFU vključuje UI kot udeleženca WebRTC

SFU oziroma enota za selektivno posredovanje je medijski strežnik, ki prejme en tok WebRTC od vsakega udeleženca in izbrane tokove posreduje drugim. V tem modelu SFU zaključi ločeno povezavo WebRTC za vsakega udeleženca, UI pa se seji pridruži kot še en udeleženec. To je lahko dobra izbira za izdelke, ki so po naravi večstranski, kot so skupinski klici, učilnice ali sodelovalni sestanki. Na enem mestu ohranja zvočne kodeke, sporočila RTCP, podatkovne kanale, snemanje in pravilnike za posamezne tokove.1

Tudi pri izdelkih od odjemalca do UI je SFU pogosto privzeto izhodišče, ker ekipam omogoča ponovno uporabo enega preverjenega sistema za signalizacijo, usmerjanje medijev, snemanje, opazljivost in prihodnje razširitve, kot sta predaja človeku ali dodajanje več udeležencev.

Možnost 2: Pristop s sprejemno-oddajno enoto zaključi WebRTC na robu in ga pretvori v zaledni protokol

Naša obremenitev je drugačna. Večina sej je 1 : 1 – en uporabnik govori z enim modelom ali ena aplikacija z enim agentom v realnem času –, pri čemer je pri vsakem koraku pomembna občutljivost na latenco. Za takšno obliko prometa smo izbrali model sprejemno-oddajne enote (transceiver): robna storitev WebRTC zaključi povezavo odjemalca, nato pa medije in dogodke pretvori v enostavnejše notranje protokole za modelsko sklepanje, prepisovanje, ustvarjanje govora, uporabo orodij in orkestracijo.

V tej zasnovi je sprejemno-oddajna enota edina storitev, ki ima v lasti stanje seje WebRTC, vključno s preverjanji povezljivosti ICE, rokovanjem DTLS, ključi za šifriranje SRTP in življenjskim ciklom seje. »Zaključevanje« tukaj pomeni, da je sprejemno-oddajna enota končna točka, ki dokonča ta rokovanja ter medije šifrira ali dešifrira. To, da je to stanje na enem mestu, je olajšalo razumevanje lastništva seje, hkrati pa je zalednim storitvam omogočilo skaliranje kot običajnim storitvam, namesto da bi same delovale kot enakovredni partnerji WebRTC.

Osrednji problem uvajanja: WebRTC sreča Kubernetes

Po izbiri modela sprejemno-oddajne enote je bila naša prva implementacija ena sama storitev v Go, zgrajena na Pion, ki je obravnavala tako signalizacijo kot zaključevanje medijev. Poganja glasovni ChatGPT, končno točko WebRTC v Realtime API in številne raziskovalne projekte.

Storitev sprejemno-oddajne enote opravlja dve operativni nalogi:

  • Signalizacija: pogajanje SDP, izbira kodekov, poverilnice ICE in vzpostavitev seje
  • Mediji: zaključevanje spodnjih povezav WebRTC in vzdrževanje zgornjih povezav z zalednimi storitvami za sklepanje in orkestracijo

Želeli smo, da storitev deluje tako kot preostala naša infrastruktura: na Kubernetesu, kjer se lahko obremenitve povečujejo in zmanjšujejo ter se premikajo med gostitelji, ko se povpraševanje spreminja. Toda običajni model WebRTC z enim portom na sejo se temu okolju slabo prilega, ker temelji na velikih obsegih javnih vrat UDP, ki jih je težko izpostaviti, zaščititi in ohraniti, ko se podi dodajajo, odstranjujejo ali prerazporejajo.2

Izčrpanje vrat

Prva težava je bil sam model z enim portom na sejo. Pri veliki sočasnosti to pomeni izpostavljanje in upravljanje zelo velikih obsegov vrat UDP.

  • Oblačni izravnalniki obremenitve in storitve Kubernetes niso zasnovani za desettisoče javnih vrat UDP na storitev. Vsak dodaten obseg poveča operativno kompleksnost v konfiguraciji izravnalnika obremenitve, preverjanju zdravja, pravilnikih požarnega zidu in varnosti uvajanja.3
  • Velike obsege vrat UDP je težko zaščititi, ker povečujejo zunanje dosegljivo površino in otežujejo revizijo omrežnih pravilnikov.
  • Prav tako se slabo ujemajo s samodejnim skaliranjem. Podi se v Kubernetesu nenehno dodajajo, odstranjujejo in prerazporejajo. Če mora vsak pod rezervirati in oglaševati velik stabilen obseg vrat, ta elastičnost postane krhka.4

Zato se številni sistemi WebRTC premikajo k enemu vratom UDP na strežnik, z demultipleksiranjem na ravni aplikacije za temi vrati.5

Lepljivost stanja

Zasnove z enim portom na strežnik rešijo število vrat, vendar uvedejo drugo težavo: ohranjanje lastništva vsake seje v celotni gruči.

ICE in DTLS sta protokola, ki hranita stanje. Proces, ki je ustvaril sejo, mora še naprej prejemati pakete te seje, da lahko preveri povezljivost, dokonča rokovanje DTLS, dešifrira SRTP in obdela poznejše spremembe seje, kot so ponovni zagoni ICE. Če paketi iste seje pristanejo v drugem procesu, lahko nastavitev odpove ali pa se mediji prekinejo.

To nam je dalo jasen cilj: javnemu internetu izpostaviti majhno, fiksno površino UDP, hkrati pa vsak paket še vedno usmeriti do sprejemno-oddajne enote, ki ima v lasti ustrezno sejo WebRTC.

Primerjava medijskih arhitektur WebRTC

Ocenili smo več načinov, kako to doseči, vključno s TURN (Traversal Using Relays around NAT), pri katerem robni rele zaključi odjemalske dodelitve in v njihovem imenu posreduje promet.2

Pristop

Prednosti

Slabosti

Enoličen IP:vrata na sejo (znano tudi kot izvorni neposredni UDP)

Neposredna pot medija od odjemalca do strežnika

Brez posredovalne plasti na podatkovni poti

Zahteva ena javna vrata UDP na sejo

Velike obsege vrat je težko izpostaviti in zaščititi

Slabo se ujema s Kubernetesom in oblačnimi izravnalniki obremenitve

Enoličen IP:vrata na strežnik

Veliko manjši javni odtis UDP kot pri izpostavitvi na sejo

Ena skupna vtičnica na strežnik lahko demultipleksira veliko sej

Dobro deluje na enem gostitelju, ne pa samostojno v deljeni gruči z izravnavanjem obremenitve

Demultipleksiranje sej na enem gostitelju pomaga šele, ko paket doseže ta gostitelj; v gruči z izravnavanjem obremenitve lahko prvi paket še vedno pristane na napačnem primerku, zato še vedno potrebujete determinističen način, da vsako sejo usmerite do procesa, ki jo ima v lasti


Rele TURN (zaključuje protokol)

Odjemalci morajo doseči le naslov in vrata releja TURN

Pravilnike je mogoče centralizirati na robu

Dodelitve TURN dodajo krožne poti pri vzpostavitvi

Premikanje ali obnavljanje dodelitev med strežniki TURN je še vedno težavno

Posredovalnik brez stanja + zaključevalnik s stanjem (OpenAI-jev rele + sprejemno-oddajna enota)

Majhen javni odtis UDP

Sprejemno-oddajna enota še vedno upravlja celotno sejo WebRTC

Doda en posredovalni skok, preden mediji dosežejo sprejemno-oddajno enoto, ki ima sejo v lasti

Zahteva usklajevanje po meri med relejem in sprejemno-oddajno enoto

Pregled arhitekture: rele + sprejemno-oddajna enota

Arhitektura, ki smo jo uvedli, ločuje usmerjanje paketov od zaključevanja protokola. Signalizacija še vedno doseže sprejemno-oddajno enoto za vzpostavitev seje, medtem ko mediji najprej vstopijo skozi rele. Rele je lahka plast za posredovanje UDP z majhnim javnim odtisom, sprejemno-oddajna enota pa je končna točka WebRTC, ki hrani stanje in stoji za njim.

Rele brez stanja posreduje pakete sprejemno-oddajni enoti

Rele ne dešifrira medijev, ne poganja mehanizmov stanja ICE in ne sodeluje pri pogajanju o kodekih. Prebere le toliko metapodatkov paketa, da izbere cilj, nato pa paket posreduje sprejemno-oddajni enoti, ki ima v lasti sejo. Sprejemno-oddajna enota še vedno vidi običajen tok WebRTC in še vedno upravlja vse stanje protokola. Z vidika odjemalca se pri seji WebRTC ne spremeni nič.

Usmerjanje na podlagi poverilnic ICE

Usmerjanje prvega paketa je ključni korak v tej postavitvi. Rele mora prvi paket od odjemalca usmeriti, še preden na sami poti paketov obstaja kakršna koli seja, zato smo usmerjanje zasnovali neposredno na poti paketa, namesto da bi čakali na zunanjo storitev za poizvedbe.

Vsaka seja WebRTC že vsebuje naravno kljuko za usmerjanje na ravni protokola: fragment uporabniškega imena ICE oziroma ufrag, kratek identifikator, ki se izmenja med vzpostavitvijo seje in ga sporočila STUN za preverjanje povezljivosti ponovijo. Strežniški ufrag ustvarimo tako, da vsebuje ravno toliko metapodatkov usmerjanja, da lahko rele sklepa o ciljni gruči in sprejemno-oddajni enoti, ki ima sejo v lasti.

Diagram zaporedja prikazuje, kako se povezava vzpostavi

Med signalizacijo sprejemno-oddajna enota dodeli stanje seje in v odgovoru SDP vrne skupni VIP releja in vrata UDP. VIP je navidezni naslov IP pred gruče relejev; v kombinaciji z vrati daje odjemalcu en sam stabilen cilj, kot je 203.0.113.10:3478, čeprav za njim stoji veliko primerkov relejev. Prvi paket na medijski poti od odjemalca je običajno zahteva STUN (Session Traversal Utilities for NAT) za vezavo, ki jo ICE uporablja za preverjanje, da lahko paketi dosežejo oglaševani naslov.

Rele razčleni ravno toliko prvega paketa STUN, da prebere strežniški ufrag, odkodira namig za usmerjanje in paket posreduje sprejemno-oddajni enoti, ki ima sejo v lasti. Vsaka sprejemno-oddajna enota posluša na skupni vtičnici UDP, kar pomeni eno končno točko operacijskega sistema, vezano na notranji IP:vrata, in ne ene vtičnice na sejo. Ko rele ustvari sejo od odjemalčevega izvornega IP:vrata do cilja sprejemno-oddajne enote, naslednji paketi DTLS, RTP in RTCP tečejo znotraj te seje brez ponovnega dekodiranja ufrag.

Seja v releju je namerno zelo preprosta; sestavlja jo le seja v pomnilniku, ki usmerja posredovanje paketov, skupaj s potrebnimi števci za nadzor in časovniki za potek seje ter čiščenje. Ta zasnovna odločitev ohranja usmerjanje paketov neposredno na poti paketa. Če se rele znova zažene in izgubi sejo, naslednji paket STUN sejo ponovno zgradi iz namiga za usmerjanje v ufrag. Da je rešitev še zanesljivejša, uporabljamo predpomnilnik Redis, ki po vzpostavitvi poti hrani preslikavo <IP odjemalca + vrata, IP sprejemno-oddajne enote + vrata>, tako da jo je mogoče obnoviti precej prej, še preden prispe naslednji paket STUN.

Global Relay in geografsko usmerjena signalizacija

Ko smo javno površino UDP zmanjšali na majhno število stabilnih naslovov in vrat, smo lahko enak vzorec releja uvedli globalno. Global Relay je naša flota geografsko porazdeljenih relejskih vhodnih točk, ki vse izvajajo enako vedenje posredovanja paketov.

Široko geografsko razpršen vstop skrajša prvi skok od odjemalca do OpenAI, ker lahko paket vstopi v naše omrežje pri releju, ki je blizu uporabnika tako geografsko kot po omrežni topologiji, namesto da bi najprej prečkal javni internet do oddaljene regije. V praksi to pomeni nižjo latenco, manj trepetanja in manj izogibnih izbruhov izgub, preden promet doseže naše hrbtenično omrežje.6

Plast Global Relay prejema pakete od odjemalca in jih posreduje gruči sprejemno-oddajnih enot

Za signalizacijo uporabljamo geografsko in bližinsko usmerjanje Cloudflare, tako da začetna zahteva HTTP ali WebSocket doseže bližnjo gručo sprejemno-oddajnih enot. Kontekst zahteve določa lokacijo seje in to, katera vhodna točka Global Relay se oglašuje odjemalcu. Odgovor SDP poda naslov Global Relay, medtem ko ufrag vsebuje dovolj informacij, da lahko Global Relay usmeri medije do določene gruče, rele pa do ciljne sprejemno-oddajne enote.

Geografsko usmerjena signalizacija in Global Relay skupaj poskrbita, da tako nastavitev kot mediji vstopijo po bližnji poti, medtem ko seja ostane zasidrana na eni sprejemno-oddajni enoti. To skrajša čas povratnega potovanja za signalizacijo in za prvo preverjanje povezljivosti ICE, kar neposredno skrajša čas čakanja uporabnika, preden se lahko začne govor.

Izvedba releja in zmogljivost

Relejsko storitev smo napisali v jeziku Go in jo namenoma ohranili ozko usmerjeno. V Linuxu omrežni sklad jedra prejme pakete UDP z omrežnega vmesnika naprave in jih dostavi vtičnici, to je končni točki operacijskega sistema, iz katere proces bere po vezavi na IP:vrata. Rele se izvaja v uporabniškem prostoru, zato običajen proces Go iz te vtičnice bere glave paketov, posodobi majhno količino stanja toka in pakete posreduje, ne da bi zaključeval WebRTC. Nismo potrebovali nobenega ogrodja za obvoz jedra, ki bi uporabniškemu procesu omogočilo neposredno anketiranje omrežnih vrst za višje stopnje paketov, a bi hkrati povečalo operativno kompleksnost.

Ključne zasnovne izbire:

  • Brez zaključevanja protokola: Rele razčleni le glave STUN oziroma ufrag; za naslednje pakete DTLS, RTP in RTCP uporablja predpomnjeno stanje, zato paketi ostanejo nepregledni.
  • Prehodno stanje: Vzdržuje majhen pomnilniški zemljevid naslovov odjemalcev do ciljnih sprejemno-oddajnih enot s kratkim časom izteka za stanje toka in opazljivost.
  • Horizontalna razširljivost: Več primerkov releja se izvaja vzporedno za izravnalnikom obremenitve. To ni trdo stanje WebRTC, zato ponovni zagoni povzročijo le minimalne izpade prometa in hitro obnovitev tokov.

Ukrepi za učinkovitost:

  • SO_REUSEPORT je možnost vtičnice v Linuxu, ki več relejskim delavcem na istem računalniku omogoča vezavo na ista vrata UDP. Jedro nato med delavce porazdeli dohodne pakete, kar prepreči ozko grlo ene same bralne zanke.
  • runtime.LockOSThread pripne vsako gorutino, ki bere UDP, na določeno nit operacijskega sistema. V kombinaciji z SO_REUSEPORT to običajno pomeni, da paketi iz istega toka (izvorni in ciljni IP:vrata ter protokol) ostanejo na istem jedru CPU, kar izboljša lokalnost predpomnilnika in zmanjša preklapljanje konteksta.
  • Vnaprej dodeljeni medpomnilniki in minimalno kopiranje ohranjajo nizke stroške razčlenjevanja in dodeljevanja, da se v Go izognemo zbiranju smeti.

Ta izvedba je obvladovala naš globalni promet medijev v realnem času z razmeroma majhnim odtisom releja, zato smo ohranili preprostejšo zasnovo, namesto da bi ubrali pot obvoza jedra.

Rezultati in spoznanja

Ta arhitektura nam omogoča izvajanje medijev WebRTC v Kubernetesu brez izpostavljanja tisočev vrat UDP. To je pomembno, ker je manjša in fiksna površina UDP lažje zaščititi in izravnavati, infrastrukturi pa omogoča skaliranje brez rezervacije velikih obsegov javnih vrat. Ob boljši podpori infrastrukture v Kubernetesu in večji varnosti zaradi manjše površine ta zasnova za odjemalce ohranja tudi standardno vedenje WebRTC ter potrjuje, da je bila zasnova brez SFU prava privzeta izbira za naše obremenitve. Večina naših sej je medtočkovna, občutljiva na latenco in lažje razširljiva, ko storitvam za sklepanje ni treba delovati kot enakovredni partnerji WebRTC.

Širše spoznanje je, da je kompleksnost najbolje dodati v tanko plast usmerjanja, ne pa v vsako zaledno storitev in ne v vedenje odjemalcev po meri. Z vdelavo metapodatkov usmerjanja v polje, ki je že naravno del protokola, smo dobili deterministično usmerjanje prvega paketa, majhen javni odtis UDP in dovolj prilagodljivosti, da vhodne točke postavimo blizu uporabnikom po vsem svetu.

Nekaj odločitev je bilo še posebej pomembnih:

  • Ohraniti semantiko protokola na robu. Odjemalci še vedno govorijo standardni WebRTC, kar ohranja združljivost med brskalniki in mobilnimi napravami.
  • Trda stanja sej naj ostanejo na enem mestu. Sprejemno-oddajna enota ima v lasti ICE, DTLS, SRTP in življenjski cikel seje; rele le posreduje pakete.
  • Usmerjati na podlagi informacij, ki so že prisotne pri nastavitvi. ICE ufrag nam je dal kljuko za usmerjanje prvega paketa brez dodajanja odvisnosti od poizvedb na vroči poti.
  • Optimizirati za najpogostejši primer, preden posežemo po obvozu jedra. Ozka izvedba v Go s skrbno uporabo SO_REUSEPORT, pripenjanjem niti in razčlenjevanjem z malo dodeljevanja je zadostovala za naše obremenitve.

Glasovna UI v realnem času deluje le, ko infrastruktura povzroči, da je latenca skoraj neopazna. Za nas je to pomenilo, da smo spremenili obliko svoje uvedbe WebRTC, ne da bi spremenili to, kar odjemalci pričakujejo od samega WebRTC.