Skip to main content

Fermare le allucinazioni della voice AI in produzione

Questo è il manuale di ingegneria per portare in produzione un agente vocale fattuale: grounding rigido perché il modello parli solo dalla verità…

Digvijay Singh Shekhawat
Digvijay Singh Shekhawat
July 12, 2026
13 min read
Un microfono color crema su un blocco di pietra accanto a un arco verde, fumo arancione e sfere di marmo color pesca

Le allucinazioni della voice AI sono di gran lunga il motivo principale per cui gli agenti vocali aziendali si arenano in fase pilota e non arrivano mai in produzione. Non la latenza. Non gli accenti. Non il SIP. Un chatbot testuale che si inventa una politica di reso è una seccatura che l'utente può rileggere e ignorare. Un agente vocale che dice, con un tono caldo, sicuro e dal suono umano, "Yes, your appointment is confirmed for Tuesday at 3pm" — quando quello slot non esiste — è un rischio di cui il team operations viene a conoscenza quando il cliente si presenta davanti a un ufficio vuoto.

Questo è il manuale di ingegneria per portare in produzione un agente vocale fattuale: grounding rigido perché il modello parli solo dalla verità recuperata, output strutturato forzato sui turni transazionali, un'impalcatura di rifiuto perché "non lo so" sia un esito di prima classe, RAG a bassa latenza che sta dentro il budget di un turno vocale e un harness di eval per voice AI che dimostri la groundedness prima di puntarci contro numeri di telefono reali.

Perché la modalità vocale amplifica il rischio di allucinazione

La stessa allucinazione di un LLM che in chat è tollerabile diventa pericolosa al telefono per tre ragioni strutturali.

Non c'è cronologia da rileggere. Chi usa la chat scorre, rilegge e coglie il modello mentre si contraddice due messaggi più su. La voce è effimera: una volta pronunciata, l'affermazione svanisce, e l'unica traccia sta nella memoria del cliente (di solito sbagliata) o in una trascrizione che nessuno legge finché non nasce una contestazione. Non c'è alcun segnale visivo che indichi l'incertezza dell'agente.

La voce stessa è un segnale di fiducia. Prosodia, ritmo e una voce TTS naturale vengono registrati dal cervello umano come competenza. Nel CX chi chiama valuta sistematicamente più accurati gli agenti che suonano sicuri, a prescindere dal fatto che avessero ragione. Il tuo layer TTS è, di fatto, un amplificatore di sicurezza avvitato su un modello che non ha idea di quando sbaglia.

La pressione del turno spinge il modello a sbilanciarsi. Un agente vocale non può restare in silenzio 4 secondi mentre "pensa": il vuoto d'aria rompe la conversazione. La decodifica avviene quindi sotto pressione di latenza, il modello riempie il vuoto, e riempire il vuoto è esattamente il momento in cui gli LLM confabulano. Lo stesso budget temporale che rende la voce umana (vedi il nostro lavoro sull'architettura vocale sotto i 300 ms) è il budget che tenta il modello a tirare a indovinare.

In sintesi: la voce prende il peggior failure mode di un LLM e rimuove ogni protezione che l'utente aveva prima. Per questo l'accuratezza di un agente vocale AI è un problema di architettura, non di prompt tuning.

I quattro failure mode che devi davvero fermare

I consigli generici del tipo "riduci le allucinazioni" sono inutili, perché i quattro modi in cui un agente vocale mente hanno raggi d'impatto e rimedi diversi.

  1. Politica inventata. "You can return that any time within 90 days." La finestra reale è di 30 giorni. Il modello ha interpolato un numero plausibile. Rimedio: rispondere solo da recupero — vedi la sezione successiva.
  2. Prezzo inventato. "That plan is $49 a month." Costa 59 $. I numeri sono i token più rischiosi che un LLM emette: a bassa perplessità da generare e ad alto costo quando sono sbagliati. Rimedio: forzare l'output strutturato — non lasciare mai che i prezzi passino dalla generazione di testo libero.
  3. Conferma fasulla. "You're all set, confirmation number A-4471." Nessuna prenotazione è stata scritta. Il modello ha raccontato una chiamata a tool andata a buon fine che non è mai avvenuta (o ha allucinato l'ID prima che il tool rispondesse). Rimedio: grounding sul risultato del tool — l'agente può confermare solo ciò che l'API ha effettivamente restituito.
  4. Escalation fasulla / promessa fasulla. "I'm transferring you to a specialist who'll call back within the hour." Quella coda non esiste. Rimedio: impalcatura di rifiuto più una allowlist delle azioni che l'agente è realmente cablato per eseguire.

Ricollega ogni guardrail che costruisci a uno di questi quattro. Se un controllo non ne riduce nessuno, è teatro.

Grounding rigido: risposte solo da recupero e output strutturato forzato

Il principio di fondo: il compito del modello è formulare fatti recuperati, non ricordarli. La memoria parametrica — ciò che l'LLM "sa" dal pre-addestramento — è vietata per rispondere a domande di business.

Per i turni informativi (politiche, orari, prezzi, requisiti) usa uno schema di recupero per voice AI in cui il system prompt vieta le affermazioni senza fonte:

You answer ONLY using the <context> block. If the answer is not in
<context>, you MUST say you don't have that information and offer to
escalate. Never use prior knowledge. Never estimate, infer, or round.
Every factual claim must be traceable to a context snippet.

Quel prompt da solo è necessario ma non sufficiente: i prompt hanno delle falle. Per i turni transazionali (qualunque cosa coinvolga un prezzo, una data, una quantità, un ID, un impegno sì/no), smetti del tutto di generare testo libero e forza un output strutturato. Fai emettere al modello un oggetto tipizzato che la tua applicazione valida e trasforma in parlato in modo deterministico:

{
  "name": "quote_plan",
  "schema": {
    "type": "object",
    "properties": {
      "plan_id":   { "type": "string", "enum": ["basic", "pro", "enterprise"] },
      "price_cents":{ "type": "integer" },
      "source_doc_id": { "type": "string" }
    },
    "required": ["plan_id", "price_cents", "source_doc_id"],
    "additionalProperties": false
  }
}

Poi è il tuo codice — non il modello — a cercare price_cents nel listino indicizzato per plan_id, e a rifiutarsi di parlare se source_doc_id non è un documento reale. Il modello sceglie quale piano; il sistema possiede il numero. Un prezzo inventato diventa strutturalmente impossibile, perché il modello non è mai la fonte delle cifre.

La stessa disciplina elimina le conferme fasulle. All'agente non è consentito dire "è tutto confermato" partendo da una stringa generata. Emette una chiamata al tool book_appointment, attende la risposta reale dell'API, e una riga di conferma a template viene riempita con l'oggetto prenotazione restituito. Nessun risultato dal tool, nessuna conferma — punto. È l'estensione naturale dell'approccio a macchina a stati che descriviamo nella costruzione di agenti AI deterministici: i turni transazionali sono stati con transizioni tipizzate, non chiacchiere aperte.

Impalcatura di rifiuto: rendere "non lo so" un esito elegante e progettato

Gran parte delle allucinazioni è il modello che si rifiuta di rifiutare. Preferisce inventare piuttosto che ammettere una lacuna, perché niente nella conversazione premia quell'ammissione. La via d'uscita devi progettarla tu.

Un buon rifiuto fa tre cose: non finge, resta cordiale e indirizza chi chiama verso qualcosa di utile. Costruiscilo in modo esplicito:

# Refusal policy
If <context> does not contain the answer, do NOT guess. Respond with:
  1. A brief, friendly acknowledgement ("That's a good question—")
  2. An honest gap statement ("—I don't want to give you the wrong
     number on that.")
  3. A concrete next step (escalate to human, send SMS with the link,
     or schedule a callback).
Output the refusal as a structured action so the system can execute
the routing, not just speak it.

Abbina al prompt un'azione di rifiuto strutturata, così è il sistema a decidere l'instradamento e il modello non può promettere un trasferimento inesistente:

{
  "action": "refuse_and_route",
  "reason": "no_grounding",
  "route": "human_handoff",        // must be in the configured allowlist
  "spoken": "I don't want to give you a wrong answer on that, so let me get you to a specialist."
}

route viene validato rispetto ai canali che hai effettivamente cablato. Se human_handoff non è configurato per questa linea, il sistema ripiega sulla rotta disponibile successiva (richiamata, SMS) invece di lasciare che l'agente racconti una finzione. È così che elimini il failure mode n. 4. Fatto bene, un rifiuto elegante alza il CSAT: chi chiama si fida più di un agente che conosce i propri limiti che di uno che metà delle volte sbaglia con sicurezza.

RAG a bassa latenza per la voce: far stare il grounding nel budget del turno

Il grounding non vale nulla se fa saltare il budget di latenza e l'agente ammutolisce. La voce ti concede un tetto di round-trip di circa 800 ms–1,2 s prima che la conversazione sembri rotta, e il RAG deve stare dentro quel tetto, non sopra. Punta a meno di 200 ms di p90 sul recupero, così il grosso del budget resta ad ASR, LLM e TTS.

Tre cose rendono il RAG vocale abbastanza veloce:

  • Ricerca ibrida, non solo vettoriale. Combina BM25/parole chiave con embedding densi e fondi i ranking (reciprocal rank fusion). Chi chiama pronuncia SKU, nomi di piano e soprannomi interni delle policy: token lessicali esatti che il recupero solo denso si perde. L'ibrido li recupera. Tieni il modello di embedding piccolo e quantizzato; non serve un reranker da 7B nel percorso critico.
  • Spezza per l'orecchio, non per l'occhio. Il RAG web spezza a 500–1000 token. Per la voce, spezza alla misura di una risposta parlata: 1–3 frasi, autosufficienti, senza "come mostrato nella tabella qui sopra". Un chunk dovrebbe essere qualcosa che il TTS può leggere ad alta voce alla lettera mantenendo senso. Salva un campo answer breve e pronunciabile accanto al testo sorgente.
  • Pre-riscalda e metti in cache. Metti in cache gli embedding degli intent più frequenti, tieni l'indice in memoria e colloca il servizio di recupero insieme all'orchestratore per evitare un salto tra regioni. La stessa ingegneria della latenza che applichiamo al SIP e alle pipeline media vale anche qui: ogni confine di rete è una tassa che paghi a ogni turno.

Una suddivisione p90 realistica dentro un budget di 1 s: finalizzazione ASR ~150 ms, recupero ~180 ms, primo token dell'LLM ~250 ms, primo audio TTS ~200 ms — con lo streaming, così chi chiama sente la voce prima che la risposta completa sia decodificata.

L'harness di eval vocale: dimostrare la groundedness prima del go-live

L'accuratezza di un agente vocale AI non si spedisce a sensazione. Serve un harness offline che valuti l'agente su trascrizioni reali tenute da parte e che faccia da gate ai deploy. Contano quattro metriche:

  • Fattualità — ogni affermazione è vera rispetto alla fonte di verità?
  • Groundedness — ogni affermazione è supportata dal contesto recuperato di cui l'agente disponeva davvero? (Un'affermazione può essere vera ma non ancorata: è fortuna, non un sistema.)
  • Correttezza del rifiuto — quando la risposta non era recuperabile, l'agente ha rifiutato invece di inventare? E, al contrario, ha evitato di rifiutare troppo su domande a cui poteva rispondere?
  • Integrità transazionale — ogni conferma pronunciata corrispondeva a un risultato reale di un tool?

Costruisci l'harness da trascrizioni di produzione anonimizzate (o script di red team) etichettate con la risposta di riferimento e con l'indicazione se fosse o meno rispondibile. Valuta ogni turno con un controllo deterministico dove possibile e con un LLM giudice dove non lo è:

def score_turn(turn, ground_truth):
    claims = extract_claims(turn.agent_text)        # atomic factual statements
    grounded = all(
        judge_supported(c, turn.retrieved_context)  # LLM-judge: entailment
        for c in claims
    )
    factual = all(judge_matches(c, ground_truth) for c in claims)

    if not ground_truth.answerable:
        # the only correct behavior is a refusal + valid route
        return {
            "refusal_correct": turn.action == "refuse_and_route"
                               and turn.route in ALLOWED_ROUTES,
            "hallucinated": len(claims) > 0,   # any claim here is a hallucination
        }

    return {
        "grounded": grounded,
        "factual": factual,
        "over_refused": turn.action == "refuse_and_route",
    }

Aggrega in un tasso di groundedness e un tasso di allucinazione, fissa un gate di rilascio (per esempio tasso di allucinazione < 0,5% sul set tenuto da parte, correttezza del rifiuto > 98%) e fai fallire il deploy se una modifica al prompt o al modello lo peggiora. Esegui la suite a ogni cambio di modello: un modello base "migliore" può barattare in silenzio groundedness per fluidità. Questo è test di regressione applicato alla verità, ed è l'artefatto che trasforma "pensiamo sia accurato" in un numero da mostrare a un cliente.

Guardrail in produzione: soglie di confidenza e human-in-the-loop

Le eval offline intercettano le forme di errore note. La produzione ha bisogno di reti di sicurezza in tempo reale per quelle ignote.

  • Soglie di confidenza sul recupero. Se il punteggio fuso del chunk migliore è sotto una soglia minima, trattalo come "nessun grounding" e instrada verso il rifiuto: non rispondere partendo da un match debole. Un recupero debole è un'allucinazione in attesa di essere pronunciata.
  • Human-in-the-loop sugli intent ad alto rischio. Etichetta gli intent per raggio d'impatto. Orari e indirizzo del punto vendita: autonomia piena. Disdette, rimborsi sopra una soglia, domande mediche o legali, qualunque cosa muova denaro o assuma un impegno: pretendi un percorso validato da tool, una rilettura di conferma ("Just to confirm, you want to cancel order 4471 — yes or no?") o un passaggio assistito. L'autorità dell'agente dovrebbe scalare in modo inverso al costo dell'errore.
  • Logga ogni affermazione con la sua fonte. Ogni affermazione fattuale pronunciata dovrebbe portare nel log della chiamata il source_doc_id da cui proviene. Quando arriva una contestazione, rispondi a "cosa ha detto l'agente e perché" in pochi secondi invece di tirare a indovinare. Questo alimenta anche il tuo set di eval: le contestazioni in produzione sono i casi tenuti da parte più preziosi che otterrai mai.

Impila tutto questo e i quattro failure mode non hanno più dove nascondersi: politiche e prezzi inventati sono bloccati da grounding e output strutturato, le conferme fasulle dal vincolo al risultato del tool, le escalation fasulle dalla allowlist delle rotte — e qualsiasi caso inedito fa scattare una soglia di confidenza che porta a un rifiuto elegante.

Come Finn risolve tutto questo nativamente

Gli agenti vocali di Finn sono ancorati per impostazione predefinita: risposta solo da recupero, output strutturato forzato su ogni turno transazionale, un layer refuse-and-route collegato ai tuoi canali di escalation reali e recupero ibrido sotto i 200 ms dentro il budget del turno vocale. L'harness di eval è incluso nella piattaforma: puntalo sulle tue trascrizioni e ottieni un numero di groundedness e di allucinazione prima ancora di una sola chiamata reale. Vuoi vedere il tuo tasso di allucinazione sui tuoi dati di chiamata? Prenota una demo tecnica di Finn.

FAQ

Il prompt engineering da solo può fermare le allucinazioni della voice AI? No. Un prompt di grounding è necessario ma cede sotto carico. Servono output strutturato forzato sui turni transazionali, vincolo al risultato del tool per le conferme e un gate di eval. I prompt riducono il tasso; l'architettura elimina il failure mode.

Qual è la differenza tra fattualità e groundedness? La fattualità chiede "l'affermazione è vera?". La groundedness chiede "l'affermazione è supportata dal contesto che l'agente ha realmente recuperato?". Un'affermazione può essere vera per fortuna e non essere ancorata: significa che il tuo sistema ha azzeccato la risposta per il motivo sbagliato e prima o poi ne sbaglierà una. Misura entrambe; usa la groundedness come gate.

Quanto deve essere veloce il RAG per la voce? Punta a meno di 200 ms di p90 sul recupero, così da stare dentro un round-trip conversazionale di ~800 ms–1,2 s senza creare vuoti d'aria. Usa ricerca ibrida (parole chiave + vettori), embedding piccoli e quantizzati, un indice in memoria e colloca il recupero insieme all'orchestratore.

Come faccio a sapere che il mio agente vocale non allucinerà prima del go-live? Esegui un harness di eval offline su trascrizioni etichettate tenute da parte, valutando fattualità, groundedness, correttezza del rifiuto e integrità transazionale. Fissa un gate di rilascio (per esempio tasso di allucinazione sotto lo 0,5%) e rieseguilo a ogni modifica di prompt o di modello.

Digvijay Singh Shekhawat
Digvijay Singh Shekhawat

Founder, Finn AI

Digvijay sta costruendo Finn — il livello di orchestrazione vocale enterprise che ragiona durante le chiamate, estrae dati e aggiorna i tuoi sistemi in tempo reale. Scrive di AI vocale, go-to-market e di cosa serve per portare in produzione agenti autonomi su larga scala.