Torna al blog
Implementazione2 settembre 20267 min di letturaAggiornato 5 settembre 2026

Costruire un sistema di streaming robusto per chatbot IA: riconnessione, risposte parziali e messaggi di stato accessibili

Come i chatbot web gestiscono in modo affidabile le risposte in streaming in caso di disconnessioni di rete, tentativi di reinvio e screen reader, evitando risposte doppie o incomplete.

Un tecnico collega moduli luminosi numerati su un banco di lavoro per creare una catena di segnale continua
Lo streaming robusto rende ogni segmento tracciabile e consente di riprendere la trasmissione in modo sicuro dopo un'interruzione.

Lo streaming rende un chatbot IA apparentemente più veloce, poiché le prime parole appaiono prima che l'intera risposta sia stata calcolata. Dal punto di vista tecnico, tuttavia, ciò crea un processo distribuito: server, provider del modello, proxy, browser e interfaccia utente mantengono lo stato insieme per diversi secondi o minuti. Le reti mobili cambiano cella, una scheda passa in background, un proxy interrompe una connessione inattiva o un utente invia per errore la richiesta una seconda volta. Senza un protocollo chiaro, parti di testo vengono visualizzate due volte, affermazioni incomplete vengono contrassegnate come concluse o la stessa azione del tool viene attivata due volte.

Un chatbot web robusto tratta quindi lo streaming come una macchina a stati e non come una semplice animazione. Questa guida mostra come combinare ID evento, ripresa della connessione, completamento atomico e notifiche discrete per screen reader.

Un messaggio ha bisogno di un'identità permanente

Assegnate un ID richiesta lato client al momento dell'invio e un ID messaggio immutabile lato server. Ogni segmento dello stream riceve inoltre un numero di sequenza progressivo. Se la stessa richiesta viene ricevuta nuovamente dopo un errore di connessione, il server non deve avviare un secondo processo indipendente, ma restituire lo stato esistente o proseguire in modo sicuro.

Le diverse identità svolgono ruoli differenti: l'ID richiesta rende l'operazione di scrittura idempotente, l'ID messaggio identifica il risultato e il numero di sequenza ordina i frammenti. Un semplice timestamp non è sufficiente, poiché le richieste parallele potrebbero entrare in collisione o arrivare in ritardo.

Separare il trasporto dallo stato applicativo

L'uso di Server-Sent Events, Fetch Streams o WebSocket non modifica il ciclo di vita applicativo. Modellate almeno gli stati: accettato, in corso, completato, interrotto e fallito. Solo un evento di completamento esplicito rende vincolante una risposta. Al contrario, la chiusura di una connessione TCP non equivale automaticamente a un esito positivo.

Per i Server-Sent Events, lo standard HTML descrive la riconnessione automatica e l'invio dell'ultimo ID evento. Questo meccanismo è utile, ma non sostituisce la cronologia lato server. Il server deve sapere quali frammenti appartengono a un messaggio e se una nuova richiesta può saltare le sequenze già trasmesse.

Riconnessione senza duplicazione del testo

Mantenete un buffer di eventi limitato per ciascun messaggio in corso. In caso di riconnessione, il client invia l'ultima sequenza confermata. Il server trasmette solo gli eventi successivi. Se il buffer è scaduto, non risponde con frammenti ipotetici, ma con uno snapshot dell'intero testo corrente e una nuova sequenza di base.

Il client elabora gli eventi in modo idempotente: le sequenze con un valore inferiore o uguale a quello applicato per ultimo vengono ignorate. Lacune più ampie attivano la richiesta di uno snapshot. In questo modo la visualizzazione rimane corretta, anche se un proxy ripete i dati o il browser torna online dopo un breve periodo disconnesso.

Le risposte parziali non devono attivare azioni

Il testo generato in streaming è provvisorio. I link potrebbero essere incompleti, una precisazione fondamentale potrebbe comparire solo nella frase successiva e gli argomenti strutturati dei tool sono sintatticamente non validi fino alla fine. Mostrate il testo in modo progressivo, ma attivate le azioni ad alto rischio solo dopo il completamento e dopo una convalida separata.

Questo vale in particolare per ordini, prenotazioni di appuntamenti, modifiche ai dati dei clienti o invio di e-mail. L'esecuzione di un tool necessita di un proprio ID azione idempotente, di una verifica delle autorizzazioni e, se necessario, di una conferma visibile. Una riconnessione non deve mai eseguire due volte la stessa azione.

Trattare l'interruzione come un vero evento di protocollo

Un pulsante di arresto non dovrebbe limitarsi a bloccare l'interfaccia visiva. Il client invia una richiesta di interruzione contenente l'ID messaggio; il server contrassegna l'esecuzione e termina, se possibile, le operazioni del modello e dei tool. I frammenti che arrivano successivamente vengono scartati. Nell'interfaccia utente rimane evidente che la risposta è stata interrotta.

Se la richiesta di interruzione non raggiunge il server, l'elaborazione potrebbe proseguire in background. Per questo motivo, anche il server verifica regolarmente lo stato. Le metriche di costo e latenza dovrebbero conteggiare separatamente i processi interrotti, altrimenti compariranno come normali errori o scompariranno del tutto dall'analisi.

Rendere gli errori comprensibili e gestibili

Distinguete almeno tra interruzione di rete, timeout, errore del provider, blocco di sicurezza e convalida applicativa. Il messaggio destinato all'utente non deve rivelare dettagli tecnici interni, ma deve indicare chiaramente il passaggio successivo in sicurezza. „Connessione interrotta – ripresa della risposta in corso“ è diverso da „Questa azione non è stata eseguita“.

Un pulsante „Riprova“ riutilizza l'ID richiesta originale solo se si desidera proseguire il medesimo processo. Per una nuova generazione completa viene creato un nuovo ID, impedendo che l'interfaccia mostri le due versioni come un unico risultato.

Non sommergere gli screen reader con ogni singolo token

I contenuti dinamici devono essere percepibili dalle tecnologie assistive. Le specifiche WAI-ARIA definiscono a questo scopo le Live Region e diversi livelli di urgenza. Una regione aggiornata a ogni singolo token con aria-live può tuttavia generare centinaia di interruzioni vocali. È preferibile utilizzare un indicatore visivo di streaming affiancato da un canale di stato separato e discreto.

Inviate ad esempio la notifica „Generazione della risposta in corso“, seguita a intervalli regolari da una frase o sezione completata e, infine, dal messaggio „Risposta completata“. Utilizzate aria-live="polite" per i normali avanzamenti; assertive è riservato esclusivamente agli errori davvero urgenti. Il focus rimane nel campo di input o nella posizione selezionata dall'utente, senza saltare a ogni frammento ricevuto.

Impostate aria-busy="true" sull'area della risposta fino a quando il contenuto è incompleto e rimuovetelo al momento del completamento atomico. Il pulsante di arresto necessita di un'etichetta chiara e deve essere accessibile da tastiera. Verificate inoltre la resa con impostazioni di movimento ridotto, zoom elevato e schermi mobili di piccole dimensioni.

Testare in modo mirato la macchina a stati

Un test del caso ideale (happy path) non è sufficiente. Automatizzate almeno i seguenti scenari:

  • Interrompere la connessione dopo diversi frammenti e riprenderla senza duplicazioni di testo.
  • Inviare lo stesso evento due volte e verificare che venga applicato una sola volta.
  • Omettere una sequenza e richiedere uno snapshot.
  • Mettere in pausa la scheda, cambiare rete e verificare che alla fine venga mostrato lo stato di completamento corretto.
  • Annullare l'operazione durante la preparazione di un tool ed evitare qualsiasi esecuzione.
  • Contrassegnare come incompleto un timeout avvenuto dopo una risposta parziale visibile.
  • Verificare che i messaggi per lo screen reader abbiano una frequenza adeguata e che il focus rimanga stabile.

Monitorate il tempo fino al primo segmento visibile, il tempo fino al completamento totale, il tasso di riconnessione, le sequenze duplicate o scartate e il successo delle interruzioni. Il solo valore del tempo per il primo token può sembrare eccellente, anche se molte risposte non giungono mai a termine in modo affidabile.

Un piano di implementazione graduale

  1. Definire gli stati dei messaggi e degli eventi lato server.
  2. Implementare gli ID idempotenti e le sequenze prima delle animazioni nell'interfaccia utente.
  3. Aggiungere la riconnessione con buffer e fallback su snapshot.
  4. Separare rigorosamente le azioni dei tool dal testo provvisorio.
  5. Verificare i messaggi di stato tramite tastiera e screen reader.
  6. Testare la gestione degli errori con reti limitate o instabili.
  7. Solo a questo punto attivare gradualmente lo streaming per il traffico di produzione.

Conclusione: visibilità rapida, completamento univoco

Un sistema di streaming di qualità combina la velocità percepita con un modello di stato rigoroso. ID permanenti, eventi ordinati, completamento atomico e una riconnessione sicura evitano risposte doppie o incomplete. Una Live Region usata con discrezione rende il processo accessibile senza interrompere l'utente di uno screen reader a ogni token.

Come passo successivo, testate una chat reale sotto una connessione mobile instabile. Se dopo un'interruzione e una riconnessione non è chiaro quale messaggio sia completo e quale azione sia stata effettivamente eseguita, è il protocollo a dover essere corretto, non l'animazione di caricamento.

Fonti

Trasforma le visite al sito in conversazioni migliori

Riduci il carico del supporto mantenendo coerenza nelle risposte

Offri supporto istantaneo sul sito, smista i casi limite al tuo team e mantieni ogni risposta allineata alla knowledge base approvata.

Articoli correlati

Continua la lettura