Un frammento visibile non equivale a un output utilizzabile
Un’interfaccia può mostrare il testo man mano che arriva da un modello e, al tempo stesso, mantenere una frontiera rigorosa tra quel testo e lo stato del sistema. Questa frontiera è importante perché un delta di streaming comunica soltanto che è stata ricevuta una parte di una generazione. Non dimostra che il messaggio sia terminato, che il suo significato non cambierà, che un oggetto strutturato sia completo o che una chiamata a uno strumento abbia argomenti validi.
La latenza percepita e la validità sono proprietà distinte. Lo streaming può ridurre il tempo al primo frammento e fornire segnali utili di attività alla persona che usa il prodotto. Tuttavia, il risultato che attiva un’operazione deve soddisfare requisiti aggiuntivi: ricezione di una terminazione inequivocabile, assemblaggio completo, validazione sintattica e semantica, associazione a una generazione specifica e, quando il rischio lo richiede, conferma umana. Un’applicazione che confonde questi livelli può creare record incompleti, indicizzare affermazioni poi ritirate o eseguire due volte un’azione dopo un’interruzione.
È opportuno trattare ciò che viene visualizzato durante la trasmissione come una proiezione provvisoria. Può essere utile per lettura, revisione e annullamento, ma deve essere identificato come bozza. Lo stato di business, invece, deve derivare da una rappresentazione finale controllata dal server o da un componente affidabile. Questa regola si applica tanto agli assistenti conversazionali quanto all’estrazione documentale, alla generazione di codice, all’automazione amministrativa e agli agenti dotati di strumenti.
Le API dei fornitori non usano tutte gli stessi nomi per gli eventi né offrono esattamente le stesse garanzie. Alcune documentano eventi incrementali, identificatori di risposta e un evento di completamento; altre descrivono stati di esecuzione o un segnale di risultato. L’integrazione deve basarsi sul contratto concreto dell’API scelta e non dedurre la completezza dal fatto che per alcuni secondi non arrivi traffico.
Progettare una macchina a stati esplicita
Il modo più chiaro per impedire che l’interfaccia diventi un canale di esecuzione consiste nel modellare il ciclo di vita di ogni generazione. L’identificatore interno della generazione deve essere creato prima di aprire la connessione e collegato, quando disponibile, all’identificatore restituito dal fornitore. Deve anche essere correlato alla sessione, all’utente o soggetto autorizzato, alla versione del prompt o della configurazione applicata e all’operazione di business richiesta.
Il primo stato è ricevuto: è arrivato un evento con metadati di trasporto, ma il suo contenuto non è ancora stato accettato. In seguito, l’evento passa al buffer provvisorio, dove viene conservato secondo l’ordine di sequenza o la posizione definita dal protocollo. Il client può leggere questo buffer per renderizzare una bozza. Se il flusso consegna parti di più elementi, come testo, ragionamento non esposto e argomenti di strumenti, devono essere mantenuti buffer separati per elemento e per tipo.
Nello stato di assemblaggio, il consumatore trasforma i frammenti in una rappresentazione candidata completa: testo finale, oggetto strutturato o richiesta di strumento. Questo passaggio non costituisce una validazione. Per esempio, il fatto che una concatenazione possa essere interpretata come JSON non prova che contenga i campi consentiti, che i valori rientrino negli intervalli accettabili o che l’utente abbia autorizzato l’azione conseguente.
Un output passa a validato solo dopo aver verificato l’evento terminale o lo stato finale documentato, l’ordine e l’integrità degli eventi necessari, lo schema atteso e le regole di business. Risultato confermato significa inoltre che il sistema ha persistito la versione validata con una chiave stabile e ha registrato la decisione. Azione eseguita è uno stato successivo, non un sinonimo di validata: richiede una policy di autorizzazione, una chiave di idempotenza e una prova del suo risultato.
Gli stati terminali alternativi meritano un trattamento dedicato. Annullata indica che l’utente o il sistema ha richiesto di fermare l’esperienza; incompleta indica che manca una parte necessaria o che il fornitore ha comunicato una conclusione non soddisfacente; fallita rappresenta un errore gestibile; scaduta indica che non è più sicuro riprendere. Nessuno di questi stati deve promuovere il buffer provvisorio a risultato finale.
Transizione consigliata di una generazione
- 01Creare una generazione interna e registrare lo scopo dell’operazione.
- 02Ricevere gli eventi e verificare che appartengano alla generazione attesa.
- 03Ordinare o deduplicare gli eventi prima di aggiungerli ai buffer provvisori.
- 04Mostrare soltanto la proiezione provvisoria consentita dall’interfaccia.
- 05Dopo il segnale terminale documentato, assemblare la rappresentazione candidata.
- 06Validare integrità, schema, regole di business e autorizzazione.
- 07Persistire una versione confermata e immutabile dell’output validato.
- 08Se è presente uno strumento, richiedere conferma quando applicabile ed eseguire con una chiave di idempotenza.
Decidere cosa può essere mostrato, salvato, indicizzato o eseguito
La policy non deve dipendere soltanto dal fatto che il contenuto appaia ragionevole. Deve dipendere dal suo stato e dalla classe di flusso. Una chat informativa tollera che l’utente veda una bozza contrassegnata come tale. Un’estrazione che alimenta una base di conoscenza richiede una versione finale prima dell’indicizzazione. Uno strumento che crea una prenotazione, invia una comunicazione o modifica permessi necessita di controlli aggiuntivi, anche se i suoi argomenti hanno già superato uno schema.
Salvare telemetria di trasporto non equivale a persistere l’output come contenuto di business. Può essere legittimo conservare un registro minimo dell’evento ricevuto per analizzare interruzioni e riconciliare sessioni, nel rispetto delle policy applicabili di privacy e conservazione. Questo va distinto dalla memorizzazione del testo parziale come risposta approvata. Allo stesso modo, un log non deve trasformare segreti, dati personali o istruzioni potenzialmente sensibili in una copia priva di controlli.
L’indicizzazione richiede una decisione particolarmente prudente. I frammenti parziali possono contenere una conclusione intermedia che scompare al termine della risposta. Indicizzarli crea recuperi futuri di materiale non confermato e rende più difficile spiegare che cosa ha visto una persona e quale versione è stata adottata dal sistema. Indicizzate la versione validata, con il suo identificatore di generazione e di versione, e rendete possibile ritirare o sostituire tale versione in modo verificabile.
Matrice decisionale per stato
| Stato | Mostrare alla persona | Persistire come risultato | Indicizzare | Eseguire un’azione esterna |
|---|---|---|---|---|
| Evento ricevuto | Non necessariamente; prima verificare appartenenza e formato | No | No | No |
| Buffer provvisorio | Sì, come bozza e con possibilità di annullamento | Solo tracce tecniche minime, se la policy lo consente | No | No |
| Oggetto assemblato | Facoltativamente, ancora come provvisorio | Non come risultato confermato | No | No |
| Output validato | Sì, come risultato finale | Sì, con versione e identificatore | Sì, se il flusso lo richiede | Non ancora per impostazione predefinita |
| Risultato confermato | Sì | Sì | Sì, quando opportuno | Solo se la policy di azione lo autorizza |
| Azione eseguita | Sì, con stato e ricevuta disponibili | Sì, registrare decisione e risultato | Non applicabile | Già eseguita; non ripetere senza idempotenza |
Consumare il trasporto senza supporre che i pacchetti siano messaggi
In un flusso basato su eventi inviati dal server, il protocollo definisce come vengono formati gli eventi e contempla le riconnessioni. Il trasporto usa testo codificato in UTF-8 e il confine di un pacchetto di rete non equivale al confine di un carattere, di una riga di evento o di un oggetto JSON. Per questo il consumatore deve usare un decodificatore incrementale e un analizzatore di eventi; non deve convertire ogni lettura di byte in una stringa indipendente e presumere che contenga un evento completo.
Dopo aver ricostruito un evento del protocollo, resta ancora da interpretare il contratto dell’API. Un testo può arrivare tramite delta; gli argomenti di una chiamata a funzione possono arrivare suddivisi; gli elementi di output possono essere intercalati. Il consumatore deve raggruppare secondo gli identificatori documentati, come generazione, elemento o indice di output, e applicare numeri di sequenza quando disponibili. Un arrivo ripetuto non deve duplicare caratteri, creare due oggetti né provocare una seconda esecuzione.
Anche la chiusura della connessione non è una prova sufficiente di successo. La connessione può chiudersi per un annullamento, un proxy, un timeout o un errore. Solo il segnale terminale e lo stato documentato dal fornitore consentono di classificare la generazione come completata, incompleta o fallita. Se manca questa evidenza, lo stato corretto è incerto o incompleto e vengono bloccate sia la promozione sia l’esecuzione.
Non tutte le API forniscono checksum, versione finale o un meccanismo di ripresa. Se esistono un identificatore della risposta e un cursore di sequenza, conservateli insieme all’ultimo evento accettato. Se non esistono, una riconnessione può richiedere di creare una nuova generazione dal punto di vista del business. Non è sicuro dedurre che due sequenze simili siano la stessa risposta soltanto in base al loro contenuto.
Tool calling: completare non significa autorizzare
Le chiamate a strumenti meritano una barriera indipendente perché trasformano testo generato in effetti esterni al modello. Il fatto che compaia il nome di una funzione o una parte dei suoi argomenti non costituisce una richiesta eseguibile. Gli argomenti devono essere accumulati fino al relativo segnale di completamento, convertiti in una rappresentazione strutturata e validati rispetto a uno schema rigoroso. Campi sconosciuti, conversioni implicite e valori fuori policy devono essere rifiutati o richiedere una nuova interazione.
La validazione dello schema è necessaria ma insufficiente. Uno strumento di trasferimento può ricevere un importo formalmente corretto e tuttavia superare un limite, non disporre dell’autorizzazione necessaria o essere diretto a un destinatario non consentito. Le regole di business devono essere eseguite nel servizio che controlla l’azione, non soltanto nel client che visualizza la conversazione. Per operazioni significative, una conferma utente deve mostrare una descrizione stabile dell’azione derivata dagli argomenti già validati.
L’esecuzione deve usare una chiave di idempotenza calcolata o assegnata dal server. Tale chiave deve essere collegata all’intenzione confermata, non a ogni ritentativo di rete. Prima di ritentare, l’esecutore consulta il registro delle operazioni per verificare se quella chiave abbia già un risultato. Questo è rilevante perché HTTP avverte che ritentare un’operazione non idempotente è pericoloso quando non è possibile sapere se la richiesta originaria sia stata applicata.
Anche il risultato dello strumento necessita di riconciliazione. Se il fornitore esterno accetta l’operazione ma la risposta va persa, lo stato non è «non eseguita»: è sconosciuto finché non viene consultato un identificatore dell’operazione o applicata una procedura di compensazione. Progettare questo caso fin dall’inizio evita che un pulsante di ripetizione diventi un ordine duplicato.
Controlli per uno strumento esterno
| Fase | Controllo minimo | Risultato in caso di errore |
|---|---|---|
| Argomenti parziali | Accumulare per identificatore della chiamata; non interpretare per eseguire | Mantenere la bozza o scartare |
| Argomenti completi | Validare JSON, schema e campi consentiti | Rifiutare la chiamata |
| Intenzione | Applicare autorizzazione, limiti e regole di business | Bloccare e spiegare il motivo |
| Conferma | Richiederla quando la policy di rischio lo esige | Non creare l’ordine esterno |
| Esecuzione | Usare una chiave di idempotenza e registrare il tentativo | Consultare lo stato prima di ritentare |
| Risposta esterna | Salvare identificatore e risultato verificabile | Contrassegnare come stato sconosciuto o in attesa di riconciliazione |
Interruzioni, annullamenti, ripresa ed esperienza di prodotto
In caso di interruzione, l’applicazione deve preservare la distinzione tra ciò che è stato visto e ciò che è stato confermato. Può lasciare visibile la bozza con un avviso di interruzione, offrire un nuovo tentativo o cercare di riprendere quando il protocollo e il fornitore lo supportano. Se riprende, deve richiedere o elaborare soltanto gli eventi successivi all’ultimo cursore confermato e deduplicare ogni ripetizione. Se non è possibile dimostrare la continuità, è preferibile avviare una nuova generazione e contrassegnarla come tale.
L’annullamento da parte dell’utente richiede due operazioni diverse: smettere di visualizzare o richiedere ulteriore contenuto e decidere cosa accade al lavoro già avviato. Annullare la sottoscrizione non implica necessariamente che il fornitore abbia fermato il calcolo. Il sistema deve registrare la richiesta di annullamento, evitare promozioni successive indesiderate e trattare ogni evento che arrivi dopo secondo una policy definita. Un’azione esterna già inviata richiede una verifica o una compensazione, non un’assunzione basata sul fatto che l’interfaccia sia stata chiusa.
Nel prodotto, gli indicatori devono comunicare attività senza promettere il completamento. Un cursore di digitazione, uno stato «in generazione» e un’opzione per interrompere sono appropriati per la bozza. Un’etichetta come «risultato pronto» deve essere riservata all’output validato. Se è consentito modificare la bozza, la modifica umana deve creare un ramo o una versione separata: non deve essere confusa con la risposta confermata dal sistema.
Il recupero di una sessione deve poter spiegare cosa è accaduto. Conservate la relazione tra generazione, eventi accettati, ultimo cursore, versione validata e, se presente, operazione esterna. Questa tracciabilità non richiede di memorizzare tutto il testo indefinitamente; il livello di dettaglio deve adattarsi alla sensibilità dei dati e agli obblighi di conservazione.
Risposta a una disconnessione
- 01Contrassegnare la trasmissione come interrotta senza dichiarare il successo.
- 02Conservare l’ultimo identificatore o cursore accettato e lo stato dei buffer.
- 03Tentare di riprendere soltanto con il meccanismo documentato dal fornitore.
- 04Deduplicare gli eventi tramite sequenza, identificatore dell’evento o entrambi.
- 05Richiedere di nuovo un segnale terminale valido prima di validare l’output.
- 06Se non esiste continuità dimostrabile, chiudere come incompleta e offrire una nuova generazione.
- 07Bloccare ogni strumento in attesa finché non viene ricostruita e validata un’intenzione completa.
Telemetria e test prima del rilascio
Le metriche devono separare la rapidità percepita dalla correttezza. Registrate il tempo fino al primo frammento, il tempo fino alla terminazione, il tempo fino alla validazione e, nei flussi con strumenti, il tempo fino alla conferma e all’esecuzione. Registrate inoltre abbandoni, annullamenti, riconnessioni, eventi scartati come duplicati, generazioni incomplete e discrepanze tra il contenuto provvisorio e la versione confermata. Questi segnali consentono di rilevare se un miglioramento visivo sta nascondendo un degrado di completezza.
Non usate il testo completo come unica base dell’osservabilità. Un identificatore di generazione, l’identificatore del fornitore quando disponibile, la sequenza, il tipo di evento, le transizioni di stato e le ragioni del rifiuto sono spesso sufficienti per indagare molti incidenti. Quando occorre conservare contenuto per audit, applicate controlli di accesso, minimizzazione e una policy esplicita di conservazione.
I test di caos devono intervenire in ogni frontiera, non limitarsi a disconnettere prima del primo token. Simulate interruzioni nel mezzo di un carattere multibyte, tra righe di evento, dentro JSON, dopo argomenti di strumento apparentemente completi e immediatamente prima del segnale terminale. Simulate reinvii di eventi, cambiamenti d’ordine quando il contratto non li vieta, risposte terminali di errore, annullamenti tardivi e perdita della risposta del sistema esterno. Il criterio principale è che nessun caso trasformi contenuto incompleto in risultato confermato né provochi una seconda azione per lo stesso scopo.
Come verifica di rilascio, controllate che il client non disponga di credenziali in grado di eseguire direttamente azioni sensibili; che la validazione sia centralizzata; che l’archivio di idempotenza sopravviva a riavvii ragionevoli; e che le dashboard distinguano una generazione abbandonata da un’azione confermata. Consultate anche le sezioni interne Imparare, Confrontare e Scoprire per allineare questa decisione di integrazione ai modelli e alle capacità del prodotto.
Questioni aperte
- La disponibilità di identificatori di sequenza, cursori di ripresa ed eventi terminali inequivocabili varia tra API e versioni.
- La possibilità di riprendere una trasmissione e il comportamento in presenza di eventi ripetuti devono essere verificati nel contratto specifico del fornitore.
- Le regole che richiedono conferma umana dipendono dal rischio dello strumento, dall’autorizzazione dell’utente e dalle policy di ciascuna organizzazione.
- La conservazione di buffer, tracce e contenuto confermato deve essere definita in base alla sensibilità dei dati e ai requisiti applicabili.
Continua a esplorare
Fonti consultate
Correzioni e trasparenza
Se trovi un dato errato o non aggiornato, inviaci la pagina e la fonte da verificare.
Proponi una correzione