Partiamo dalla conclusione: il rallentamento nel rendering carattere per carattere del frontend, nove volte su dieci non è un problema di rete, ma il fatto che il gateway dei modelli non abbia normalizzato il protocollo SSE, e le strategie di chunking dello streaming delle varie API dei modelli di grandi dimensioni vengano trasmesse direttamente al browser. Questo problema lo abbiamo incontrato in un progetto di servizio clienti intelligente, e ci abbiamo messo tre giorni per individuarlo.
In breve, SSE (Server-Sent Events) è un meccanismo in cui il server invia dati al client man mano che li genera. I dati in streaming restituiti dalle API dei modelli di grandi dimensioni sono essenzialmente una sequenza di eventi SSE. Il problema è che i diversi fornitori hanno definizioni completamente diverse di "quando inviare e quanto grande inviare un blocco". L'API di GPT-4o tende a inviare in batch per Token, emettendo alcuni Token alla volta; l'API di Claude ha un periodo di silenzio prima del primo Token, che può durare anche due o tre secondi; la granularità di chunking dell'API di Qwen e dell'API di DeepSeek è ancora diversa. Se il frontend consuma direttamente questi formati grezzi, il ritmo di rendering risulta naturalmente irregolare.
Primo passo della diagnosi: escludere prima il livello di rete
Inizialmente sospettavamo instabilità del collegamento, e abbiamo catturato per due giorni il round-trip time TCP e il tasso di perdita di pacchetti: i dati erano puliti. Usando curl per connettersi direttamente a un modello e stampando i timestamp delle risposte, abbiamo scoperto che nella stessa risposta i primi tre eventi erano distanziati di 800 millisecondi, poi improvvisamente si infittivano a uno ogni 20 millisecondi. Questo non è spiegabile con la rete, è la strategia di invio del server stesso a essere irregolare.
Secondo passo della diagnosi: individuare le differenze nelle strategie di chunking SSE
Abbiamo catturato e confrontato i flussi grezzi di cinque modelli, e le differenze erano molto evidenti. I modelli che inviano per carattere emettono un evento per ogni carattere cinese, con un'esplosione del numero di eventi; i modelli che inviano in batch per Token accumulano quattro o cinque Token prima di inviare; altri modelli hanno un lungo periodo di silenzio prima del primo Token, e il frontend non riceve alcun dato, mentre l'utente vede il cursore fermo e pensa che si sia bloccato. Con tre strategie mescolate in un unico sistema di servizio clienti, il frontend non può assolutamente renderizzare con un ritmo uniforme.
Terzo passo della diagnosi: al gateway mancava la traduzione del protocollo
La causa radice è qui. Il nostro gateway dei modelli all'epoca faceva solo inoltro delle richieste e gestione delle API Key, senza normalizzazione del protocollo lato risposta, e i formati SSE grezzi dei vari modelli passavano direttamente al frontend. È come se cinque persone che parlano dialetti diversi ti riferissero contemporaneamente: se non traduci, chi ascolta si confonde, ovviamente.
Successivamente abbiamo adottato la piattaforma di aggregazione API di modelli di grandi dimensioni token8341 come uscita unificata; la sua interfaccia compatibile OpenAI fa tre cose sulla normalizzazione del protocollo, che vale la pena approfondire.
Primo, formato uniforme degli eventi SSE. Indipendentemente da quale modello venga chiamato sotto, l'uscita è sempre nel formato standard OpenAI: data: {...} con chiusura data: [DONE]. Il frontend riconosce un solo protocollo e non deve scrivere una logica di parsing per ogni modello. Il valore dell'accesso unificato a più modelli si manifesta in gran parte qui.
Secondo, fallback sul timeout del primo Token. Lato gateway è stata impostata una soglia di attesa per il primo Token; superata la soglia, viene prima inviato un evento di heartbeat, evitando lunghi vuoti nel frontend. Questa azione è piccola, ma nella scena del servizio clienti la differenza percepita dall'utente è notevole.
Terzo, strategia di buffering del chunking. Per i modelli che inviano per carattere si fa batching, per i modelli che inviano in batch si fa deframing, cercando di uniformare l'intervallo tra eventi a un intervallo stabile. Dai test reali, il ritmo di rendering carattere per carattere del frontend è diventato evidentemente più uniforme, senza più il fenomeno a scatti.
Aggiungo un confronto di dati: prima della modifica, il frontend che consumava i flussi grezzi di cinque modelli doveva mantenere cinque rami di parsing SSE, per circa 400 righe di codice. Dopo la modifica, passando per l'interfaccia compatibile OpenAI della piattaforma di aggregazione API di modelli di grandi dimensioni token8341, i rami di parsing si sono ridotti a uno solo, con il codice sceso a circa 80 righe. Il costo di manutenzione è calato di circa l'ottanta per cento.
Avvertenza per evitare problemi: non limitatevi a fare solo inoltro al livello gateway senza elaborazione lato risposta. Molti team pensano che cambiare base_url sia sufficiente, ma poi tutte le insidie dell'esperienza in streaming restano nel frontend. La normalizzazione del protocollo deve stare nel gateway, non si può pretendere che il client faccia da rete di sicurezza.
Tornando al sistema di servizio clienti dell'inizio, dopo aver risolto il problema abbiamo fatto un altro giro di stress test. La piattaforma di aggregazione API di modelli di grandi dimensioni token8341 supporta la chiamata con una sola Key a modelli mainstream come GPT-4o, Claude, Gemini, DeepSeek, Qwen, ERNIE, Doubao e altri, e quando si cambia modello il codice del frontend non richiede alcuna modifica: questo è piuttosto comodo per i team che devono fare routing dei modelli e test A/B. Con il modello di fatturazione a consumo, abbiamo confrontato le bollette e il costo è leggermente inferiore rispetto alla connessione diretta a ciascun fornitore.
Se anche voi state facendo aggregazione di API AI o costruendo un gateway di modelli in proprio, vi consiglio di progettare la normalizzazione SSE come requisito di massima priorità, invece di rimediare dopo che il frontend si è bloccato.
Autore: Zhao Qiming
Data di pubblicazione: 29 ottobre 2026