Come abbiamo creato in sei mesi un sistema in tempo reale per un'IA vocale reattiva
Di Justin Uberti e Zahan Malkani, membri dello staff tecnico
Per l'IA vocale, capire quando parlare è più difficile di quanto sembri. Le persone si passano la parola senza sforzo in una frazione di secondo, ma i precedenti sistemi di IA vocale non riuscivano a sostenere questo ritmo. La loro architettura basata sui turni dipendeva da piccoli modelli detti rilevatori di turno, ai quali spettava un compito ingrato: decidere troppo presto significava interrompere l'utente; decidere troppo tardi rendeva lenta la risposta. Solo dopo la decisione del rilevatore poteva entrare in funzione il ben più grande LLM.
GPT‑Live, il nostro sistema vocale di terza generazione, elimina il rilevatore di turno dal percorso audio. Il suo modello vocale è full-duplex, cioè può ascoltare e parlare contemporaneamente. Questo elimina la necessità di un rilevatore separato e rende la conversazione più immediata e naturale. Quando servono un ragionamento più profondo o l'uso di strumenti, GPT‑Live può anche consultare i nostri modelli di frontiera, come GPT‑5.5, senza interrompere il flusso della conversazione. Insieme, queste capacità offrono a GPT‑Live una combinazione senza precedenti di reattività conversazionale e intelligenza.
Offrire questa esperienza su larga scala ha richiesto una nuova architettura di sistema ottimizzata per una bassa latenza. A differenza della tipica inferenza richiesta-risposta, il nostro sistema trasmette in streaming l'audio in ingresso al modello vocale e la voce in uscita all'utente, gestendo la delega su un percorso asincrono separato. Negli ultimi sei mesi abbiamo riprogettato l'inferenza del modello, la gestione del contesto e il trasporto multimediale per mantenere fluido il parlato da un'estremità all'altra.
L'architettura crea inoltre un confine netto tra il percorso vocale principale e la logica applicativa. Ciò consente di personalizzare facilmente il comportamento dell'applicazione senza influire sulla reattività. Questa base supporta una gamma crescente di funzionalità di ChatGPT Voce, tra cui la nuova capacità di controllare il computer e coordinare gli agenti nell'app desktop di ChatGPT.
In questo articolo spiegheremo perché i precedenti sistemi basati sui turni non soddisfacevano le nostre esigenze e come abbiamo progettato il nuovo sistema per essere reattivo a ogni livello. Parleremo di inferenza con stato, gestione dinamica del contesto, delega asincrona e ottimizzazione a livello di protocollo: tutti elementi che collaborano per rendere GPT‑Live davvero live.
Le precedenti architetture vocali ereditavano la natura basata sui turni degli LLM testuali, ma ogni turno era rappresentato da un blocco audio distinto anziché dal testo. Nei sistemi a cascata, riconoscimento vocale, LLM e sintesi vocale venivano eseguiti in sequenza. Questa sequenza aumentava la latenza e ignorava segnali come il tono e il ritmo.
I modelli da voce a voce hanno migliorato questo approccio elaborando direttamente l'audio. Addestrare il modello a comprendere e generare nativamente il parlato gli ha consentito di preservare dettagli persi nella trascrizione e di rispondere più rapidamente. Il sistema continuava però ad affidarsi al rilevatore di turno per decidere quando avviare l'inferenza. Il modello gestiva una parte maggiore dell'interazione, che rimaneva tuttavia basata sui turni.
GPT‑Live affida al modello vocale il controllo della conversazione: l'audio fluisce in entrata e in uscita dal modello, mentre il ragionamento più profondo e l'uso degli strumenti avvengono in modo asincrono. Il compito principale del sistema è mantenere un ciclo multimediale ininterrotto. Le altre attività, come richiamare i modelli di frontiera e rendere persistente la conversazione, avvengono fuori dal percorso in tempo reale.
Mantenere ininterrotto questo ciclo multimediale non è sempre semplice. Qualsiasi ritardo nel trasporto, nell'elaborazione o nell'inferenza può trasformarsi in una pausa o in un artefatto udibile. Un precedente sistema basato sui turni poteva tollerare una certa variabilità nel momento in cui arrivava un blocco audio. Un sistema multimediale dal vivo, invece, deve consegnare puntualmente ogni frame audio.
Il lavoro svolto in precedenza su ChatGPT Voce e sulla Realtime API ci ha fornito una base importante. Avevamo già ricostruito la nostra infrastruttura vocale per trasmettere audio e video in streaming direttamente da e verso i nostri sistemi, con una latenza inferiore e più prevedibile. GPT‑Live ha portato questo progetto oltre, trasmettendo i contenuti multimediali fino al modello attraverso un nuovo sistema di inferenza con stato, creato per la conversazione continua.
L'inferenza in streaming, tuttavia, era solo una parte della soluzione. Per farla funzionare bene in produzione, dovevamo anche garantire la trasmissione affidabile dell'audio dal client allo stack di inferenza e affrontare le difficoltà legate alla gestione dello stato.
Una delle prime decisioni è stata separare esplicitamente il flusso multimediale dalla logica applicativa e di business. L'audio viaggia tra il client e il modello vocale lungo un percorso veloce dedicato. La delega, l'uso degli strumenti e le altre attività applicative avvengono oltre un confine RPC asincrono. Una chiamata lenta a uno strumento o a un servizio backend può ritardare il proprio risultato, ma non può bloccare il flusso multimediale.
Questa separazione offre inoltre al sistema un confine netto per la personalizzazione. Le applicazioni possono modificare strumenti, criteri e comportamento del backend senza influire sul frontend multimediale responsabile di garantire la continuità del flusso audio. Il percorso in tempo reale rimane essenziale, prevedibile e concentrato sulle attività che devono avvenire in tempo reale.
Abbiamo scritto in Go il frontend multimediale e la logica di inferenza, sostituendo una precedente implementazione Python basata su asyncio. Questo ha reso la trasmissione dei frame molto più fluida: il p95 del nuovo sistema equivale al p50 di quello precedente.
WebRTC fornisce la base per il trasporto. È progettato per contenuti multimediali a bassa latenza e può continuare a funzionare nonostante perdita di pacchetti, deriva dell'orologio e cambiamenti nella connessione del client. Se i pacchetti arrivano in ritardo, WebRTC può dilatare impercettibilmente l'audio per evitare interruzioni e poi accelerare brevemente la riproduzione per riallinearsi al tempo reale.
Riducendo al minimo buffering e blocchi nell'intero sistema, possiamo offrire i tempi di risposta inferiori al secondo che le persone si aspettano da una conversazione.
L'inferenza con stato comporta compromessi operativi specifici. Una sessione vocale può rimanere attiva a lungo, ma il suo contesto cresce continuamente e le istanze del modello vengono avviate e arrestate in base alla domanda.
Per affrontare questi aspetti, abbiamo creato un meccanismo di passaggio fluido tra le istanze del modello. Quando serve una transizione, possiamo preparare un'istanza sostitutiva del modello accanto a quella esistente, precaricarla con il contesto della sessione corrente, eseguire l'inferenza su entrambe in parallelo e passare alla nuova istanza quando è completamente pronta.
Lo stesso meccanismo di base supporta anche il compattamento dinamico del contesto. Con il progredire della conversazione, il contesto accumulato può finire per superare il limite di contesto del modello. Il compattamento può ridurre le dimensioni del contesto per rispettare il limite, ma l'operazione richiede tempo. Inoltre, poiché modifica il contesto passato, invalida la cache chiave-valore (KV) del modello, che memorizza le chiavi e i valori di attenzione dei token elaborati in precedenza. Ricostruire questo stato richiede un nuovo prefill, introducendo un ulteriore ritardo.
Trattiamo invece il compattamento come un'altra transizione gestita. Mentre l'istanza originale del modello continua a conversare, il sistema compatta il contesto e prepara un'istanza sostitutiva del modello con il nuovo contesto. Quando l'istanza è pronta, possiamo effettuare il passaggio senza interrompere il flusso multimediale. Ciò consente al sistema di supportare chiamate prolungate, eseguendo il compattamento ogni volta che è necessario.
Le operazioni più impegnative restano fuori dal percorso in tempo reale, così la conversazione non perde mai il ritmo, nemmeno durante un passaggio.
La capacità di GPT‑Live di richiamare i modelli di frontiera esistenti gli conferisce grande potenza, separando di fatto il "parlare" dal "pensare" più in profondità. Per far percepire questa architettura a due modelli come un unico sistema, però, abbiamo dovuto risolvere due problemi di ingegneria correlati.
Delega per lavori più approfonditi
GPT-Live offre risposte rapide e naturali, mentre GPT-5.5 gestisce la ricerca in background
Innanzitutto, i risultati devono tornare abbastanza rapidamente da essere utili nello scambio in corso. Abbiamo quindi dovuto ridurre al minimo la latenza nell'intero percorso di delega, dall'instradamento e dall'elaborazione del prompt fino all'inferenza e alle chiamate agli strumenti. Allo stesso tempo, altri sistemi del prodotto hanno ancora bisogno di messaggi distinti, perciò dovevamo rappresentare la conversazione in corso in una forma comprensibile per loro.
Quando viene avviata una delega, ottimizziamo il tempo necessario al modello di frontiera per produrre qualcosa di utile alla conversazione. Il modello vocale può mantenere brevemente vivo lo scambio mentre un modello di frontiera ragiona o usa strumenti, ma non può mascherare una risposta eccessivamente lenta. Abbiamo quindi incluso l'intero ciclo di delega — instradamento, elaborazione del prompt, inferenza e chiamate agli strumenti — nel budget di reattività.
La prima ottimizzazione consiste nel predisporre il modello di frontiera e gli eventuali strumenti necessari prima che venga richiesta la delega. All'avvio di una sessione vocale, il server applicativo crea una sessione di inferenza per il modello di frontiera e la precarica con il contesto iniziale della conversazione, assicurando che il prompt sia stato elaborato completamente prima della prima richiesta delegata.
Manteniamo poi disponibile la sessione di inferenza per l'intera durata della conversazione vocale e usiamo un'affinità di sessione stabile per le richieste successive. Insieme alla memorizzazione nella cache del prompt, queste tecniche migliorano la latenza, pur consentendo un facile ripristino in caso di errore di un worker.
Anche l'intensità del ragionamento, i limiti di output, gli schemi degli strumenti e i round trip tra modello e strumenti incidono sui tempi di ricezione di un risultato utile; abbiamo quindi regolato questi parametri per ottenere risposte più rapide. Riducendo al minimo il lavoro necessario nel percorso di delega, abbiamo permesso al modello vocale di integrare rapidamente i risultati dei nostri modelli di frontiera.
Sebbene il modello vocale operi su flussi continui di parlato, molti sistemi circostanti funzionano ancora in base ai turni dell'utente e dell'assistente, tra cui l'interfaccia di conversazione di ChatGPT e parti della nostra infrastruttura di analisi e sicurezza. Il server applicativo separa quindi la conversazione sovrapposta e talvolta ambigua in messaggi distinti.
Man mano che arriva l'audio, il server usa trascrizioni parziali e segnali temporali per dedurre chi ha la parola e creare una coda di messaggi. Il messaggio più recente rimane provvisorio: testo, tempistiche e attribuzione del parlante possono cambiare con l'arrivo di altro parlato. Quando un parlante mantiene la parola abbastanza a lungo da rendere affidabile l'attribuzione, il server finalizza il messaggio corrispondente.
La sovrapposizione tra i parlanti complica il processo. Un breve segnale di assenso dell'assistente mentre l'utente parla (ad esempio "mm hmm" oppure "okay") non deve necessariamente diventare un messaggio a sé. Un intervento sostanziale dell'assistente, invece, spesso dovrebbe esserlo. Analogamente, diamo priorità alla coerenza delle risposte dell'assistente visualizzate, anche quando l'utente interviene nel mezzo.
Ogni criterio di segmentazione comporta un compromesso tra tempestività e certezza. Confermare troppo presto produce una cronologia frammentata e un ordinamento instabile; aspettare troppo ritarda le trascrizioni e le funzionalità che dipendono da esse. Il sistema mantiene quindi due viste correlate della conversazione: una vista speculativa dello stato corrente e una registrazione autorevole di quanto è stato detto. La vista della conversazione nell'interfaccia dell'applicazione può gestire gli aggiornamenti, quindi usa la vista speculativa. La registrazione nella pipeline di analisi richiede invece una trascrizione definitiva.
In questo modo, il resto di ChatGPT dispone di una vista stabile dello scambio senza imporre turni al percorso vocale in tempo reale.
La reattività inizia non appena l'utente fa clic sul pulsante. Con GPT‑Live, prima che inizi la conversazione il sistema deve stabilire il percorso multimediale e iniziare a fornire audio al modello. Questo rende critica ogni fase della sequenza di avvio.
Come osservato sopra, WebRTC offre una solida base per il tempo reale, ma avviare una sessione WebRTC standard richiede un numero sorprendente di handshake di protocollo e round trip di rete. WebRTC è precedente all'attenzione per la riduzione dei round trip che ha plasmato protocolli successivi come QUIC. Di conseguenza, quando vengono usati insieme, i protocolli sottostanti talvolta ripetono le stesse operazioni. Ad esempio, ogni protocollo includeva un proprio meccanismo anti-DoS, anche quando non era necessario nel contesto dello stack WebRTC completo.
Abbiamo analizzato lo stack e sviluppato il WebRTC Abridged Roundtrip Protocol (WARP(si apre in una nuova finestra)), che riduce l'avvio di contenuti multimediali e dati da sei round trip di rete a uno solo. WARP raggiunge questo risultato con una serie di miglioramenti dei protocolli compatibili con le versioni precedenti: integra l'handshake DTLS in ICE (SPED(si apre in una nuova finestra)), usa il più rapido handshake DTLS 1.3(si apre in una nuova finestra), pre-negozia l'handshake SCTP (SNAP(si apre in una nuova finestra)) e pre-negozia i canali dati anziché usare DCEP(si apre in una nuova finestra).
Abbiamo progettato WARP come un insieme di specifiche aperte, collaborando con membri della comunità WebRTC, affinché l'intero ecosistema possa beneficiare di questo lavoro. Stiamo portando avanti le proposte nel gruppo di lavoro TSVWG dell'IETF e il supporto per WARP è già stato aggiunto sia a libwebrtc sia a Pion, mentre sono in corso interventi su altre implementazioni WebRTC.
Dopo aver ottimizzato l'handshake multimediale, restava un ritardo evidente: lo scambio di segnalazione usato per condividere i parametri SDP prima che WebRTC possa connettersi. Per rimuovere questo scambio dal percorso critico, abbiamo sviluppato ciò che chiamiamo Instant Connect. Instant Connect negozia questi parametri in anticipo, senza riservare capacità del server e senza modificare le implementazioni WebRTC esistenti.
Instant Connect viene eseguito parallelamente al flusso di segnalazione standard. Se i parametri pre-negoziati sono validi, il server può materializzare la sessione all'arrivo del primo pacchetto multimediale. Se sono obsoleti o non validi, il flusso di segnalazione è già in corso, quindi il client può ricorrervi senza ulteriore latenza.
Insieme, Instant Connect e WARP riducono drasticamente il tempo che intercorre tra l'intenzione dell'utente e l'avvio del flusso multimediale in tempo reale. Con lo scambio SDP fuori dal percorso critico e WARP che accorpa l'handshake di trasporto, il client può ora avviare una sessione con un unico pacchetto UDP. Il server può rispondere immediatamente, consentendo al resto del sistema di iniziare a svolgere il lavoro che interessa davvero all'utente: ascoltare e rispondere.
Un sistema può sembrare veloce sulla carta e bloccarsi comunque con traffico vocale reale. Prima di consentire a GPT‑Live di conversare con gli utenti, abbiamo eseguito un test silenzioso che indirizzava una quota piccola e gradualmente crescente delle sessioni di ChatGPT Voce in produzione sia verso l'esperienza esistente della modalità vocale avanzata sia verso il nostro nuovo sistema. La modalità vocale avanzata ha continuato a servire gli utenti come di consueto, mentre il percorso parallelo eseguiva l'inferenza in modalità di sola lettura. In questo modo il sistema è stato esposto a client, reti, durate delle sessioni e distribuzioni geografiche reali, senza cambiare ciò che gli utenti sentivano.
Una delle prime lezioni è stata che la capacità non poteva ridursi alla capacità di elaborazione delle GPU. Le sessioni vocali restano aperte e inviano frame continuamente, quindi gestori dei flussi lato CPU, code e percorsi di rete devono scalare insieme all'inferenza. Sotto un carico reale, un componente di supporto ha raggiunto la saturazione prima di quanto previsto dai test di carico, causando l'accumulo delle richieste di inferenza e un progressivo aumento della latenza. Abbiamo riformulato la domanda sulla capacità, passando da «Quante richieste può gestire una GPU?» a «Quante sessioni simultanee può sostenere il sistema mantenendo puntuale ogni frame?»
Il test ha inoltre reso la geografia una priorità assoluta. Indirizzare una sessione verso risorse lontane può aggiungere ritardi in diversi punti durante l'avvio e lo streaming. Abbiamo iniziato a convalidare i rollout dei modelli insieme alla capacità regionale e alla configurazione dell'instradamento del traffico, per poi scomporre la latenza in base all'area geografica di origine. Avvicinare l'inferenza agli utenti è stato utile, ma ha anche confermato una lezione più generale: la reattività end-to-end dipende da ogni servizio lungo il percorso, non solo dal server del modello.
Altri problemi si sono manifestati solo nell'arco di cicli di vita realistici delle sessioni. Le sessioni prolungate hanno evidenziato problemi di memoria e persistenza. Le riconnessioni hanno messo alla prova il compattamento e il ripristino dello stato. Le normali disconnessioni dei client hanno rivelato race condition nell'handshake di chiusura. Questi problemi emergevano raramente nei test di carico brevi, perché dipendevano dal tempo, dallo stato accumulato e dai comportamenti oltre i confini dei singoli servizi.
Infine, i test in produzione ci hanno costretto a migliorare l'osservabilità e i controlli sul rollout. Abbiamo trovato metriche che confondevano diverse fonti di latenza, dashboard i cui dati aggregati nascondevano singoli motori malfunzionanti e divergenze di configurazione tra i sistemi testati e quelli distribuiti. In risposta, abbiamo aggiunto telemetria più granulare, convalida rispetto a configurazioni note e affidabili, incrementi graduali e la possibilità di isolare o disabilitare rapidamente i singoli percorsi. Il test silenzioso è diventato una prima prova generale del lancio, non solo per verificare quanto traffico potesse accettare il sistema, ma anche quanto rapidamente potessimo rilevare, contenere e risolvere un guasto.
Portare GPT‑Live alla scala di ChatGPT ha richiesto un sistema completamente nuovo, costruito attorno a un principio fondamentale: la voce deve fluire. L'inferenza in streaming alimenta continuamente il modello full-duplex con l'audio. Un percorso multimediale dedicato garantisce una trasmissione affidabile dei frame. La delega asincrona consente di svolgere in parallelo le elaborazioni più profonde. Un trasporto ottimizzato mantiene reattiva l'esperienza fino all'utente.
L'architettura alla base di GPT‑Live sta già diventando una piattaforma più ampia per le interazioni in tempo reale. Supporta ChatGPT Voce nella sua evoluzione dalla conversazione al coordinamento agentico e sarà alla base della prossima API GPT‑Live. Nel tempo, consentirà di estendere le esperienze vocali a più dispositivi, app e modalità, senza sacrificare l'immediatezza che rende la conversazione vocale davvero dal vivo.
Se sono questi i problemi di ingegneria che vuoi risolvere, vieni a lavorare con noi.

