Hallucinationer i röst-AI är det enskilt största skälet till att företags röstagenter fastnar i pilot och aldrig når produktion. Inte latensen. Inte dialekterna. Inte SIP. En textchattbot som hittar på en returpolicy är ett irritationsmoment som användaren kan läsa om och avfärda. En röstagent som med varm, självsäker, mänskligt klingande röst säger "Yes, your appointment is confirmed for Tuesday at 3pm" — när ingen sådan tid finns — är en risk som ditt driftteam får kännedom om när kunden står utanför ett tomt kontor.
Det här är ingenjörshandboken för att lansera en faktatrogen röstagent: hård grounding så att modellen bara får tala utifrån hämtad sanning, tvingad strukturerad utdata i transaktionella turer, en refusal-struktur som gör "jag vet inte" till ett fullvärdigt utfall, RAG med låg latens som ryms i budgeten för en samtalstur, och ett eval-harness för röst-AI som bevisar groundedness innan du riktar riktiga telefonnummer mot den.
Varför röstmodaliteten förstärker hallucinationsrisken
Samma LLM-hallucination som är uthärdlig i chatt blir farlig i telefon av tre strukturella skäl.
Ingen historik att bläddra i. Chattanvändare skummar, läser om och avslöjar modellen när den motsäger sig själv två meddelanden upp. Rösten är flyktig — när påståendet väl sagts är det borta, och den enda dokumentationen finns i kundens minne (oftast fel) eller i en transkribering som ingen läser förrän det blir en tvist. Det finns ingen visuell ledtråd om att agenten är osäker.
Rösten i sig är en förtroendesignal. Prosodi, tempo och en naturlig TTS-röst registreras av den mänskliga hjärnan som kompetens. Inom CX bedömer de som ringer genomgående självsäkert klingande agenter som mer korrekta, oavsett om de faktiskt hade rätt. Ditt TTS-lager är i praktiken en självsäkerhetsförstärkare fastskruvad på en modell som inte har en aning om när den har fel.
Turtrycket pressar modellen att bestämma sig. En röstagent kan inte sitta tyst i 4 sekunder medan den "tänker" — död luft bryter samtalet. Avkodningen sker alltså under latenstryck, modellen fyller luckan, och att fylla luckan är precis när LLM:er konfabulerar. Samma tidsbudget som får rösten att kännas mänsklig (se vårt arbete om röstarkitektur under 300 ms) är den budget som frestar modellen att gissa.
Sammantaget: rösten tar en LLM:s värsta felläge och tar bort alla skyddsräcken användaren tidigare hade. Därför är noggrannhet hos en AI-röstagent ett arkitekturproblem, inte ett promptjusteringsproblem.
De fyra fellägen du faktiskt måste stoppa
Generella råd om att "minska hallucinationer" är värdelösa, eftersom de fyra sätt en röstagent ljuger på har olika skadeområde och olika åtgärder.
- Påhittad policy. "You can return that any time within 90 days." Den verkliga fristen är 30 dagar. Modellen interpolerade en rimlig siffra. Åtgärd: svara enbart utifrån hämtning — se nästa avsnitt.
- Påhittat pris. "That plan is $49 a month." Det kostar 59 dollar. Siffror är de mest riskfyllda tokens en LLM producerar: billiga att generera, dyra att ha fel om. Åtgärd: tvinga strukturerad utdata — låt aldrig priser passera genom fritextgenerering.
- Falsk bekräftelse. "You're all set, confirmation number A-4471." Ingen bokning skrevs. Modellen berättade om ett lyckat verktygsanrop som aldrig ägde rum (eller hallucinerade fram id:t innan verktyget hann svara). Åtgärd: grounding mot verktygsresultatet — agenten får bara bekräfta det som API:et faktiskt returnerade.
- Falsk eskalering / falskt löfte. "I'm transferring you to a specialist who'll call back within the hour." Någon sådan kö finns inte. Åtgärd: refusal-struktur plus en allowlist över de åtgärder agenten faktiskt är inkopplad för att utföra.
Koppla varje skyddsräcke du bygger till ett av dessa fyra. Om en kontroll inte minskar något av dem är den teater.
Hård grounding: svar enbart från hämtning och tvingad strukturerad utdata
Grundprincipen: modellens uppgift är att formulera hämtade fakta, inte att minnas dem. Parametriskt minne — det LLM:en "kan" från förträningen — är bannlyst när affärsfrågor ska besvaras.
För informativa turer (policy, öppettider, priser, behörighet) använder du ett hämtningsmönster för röst-AI där systemprompten förbjuder påståenden utan källa:
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.
Enbart den prompten är nödvändig men inte tillräcklig — prompter läcker. För transaktionella turer (allt som rör ett pris, ett datum, ett antal, ett id eller ett ja/nej-åtagande) slutar du generera fritext helt och tvingar fram strukturerad utdata. Låt modellen producera ett typat objekt som din applikation validerar och deterministiskt renderar till tal:
{
"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
}
}
Sedan är det din kod — inte modellen — som slår upp price_cents i pristabellen med plan_id som nyckel, och som vägrar tala om source_doc_id inte motsvarar ett riktigt dokument. Modellen väljer vilken plan; systemet äger siffran. Ett påhittat pris blir strukturellt omöjligt, eftersom modellen aldrig är källan till siffrorna.
Samma disciplin dödar falska bekräftelser. Agenten får inte säga "det är bekräftat" utifrån en genererad sträng. Den skickar ett book_appointment-verktygsanrop, väntar på det riktiga API-svaret, och en mallad bekräftelserad fylls från det returnerade bokningsobjektet. Inget verktygsresultat, ingen bekräftelse — punkt slut. Det här är den naturliga förlängningen av det tillståndsmaskinsangreppssätt vi går igenom när vi bygger deterministiska AI-agenter: transaktionella turer är tillstånd med typade övergångar, inte öppen chatt.
Refusal-struktur: gör "jag vet inte" till ett elegant och designat utfall
De flesta hallucinationer är modellen som vägrar att vägra. Den hittar hellre på än erkänner en lucka, eftersom ingenting i samtalet belönar ett erkännande. Du måste designa avfarten.
En bra refusal gör tre saker: den låtsas inte, den håller värmen, och den lotsar den som ringer någonstans användbart. Bygg upp den explicit:
# 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.
Kombinera prompten med en strukturerad refusal-åtgärd så att systemet avgör routningen och modellen inte kan lova en överkoppling som inte finns:
{
"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 valideras mot de kanaler du faktiskt kopplat in. Om human_handoff inte är konfigurerad för den här linjen nedgraderar systemet till nästa tillgängliga väg (återuppringning, SMS) i stället för att låta agenten berätta en påhittad historia. Så eliminerar du felläge nr 4. Rätt gjord höjer en elegant refusal CSAT — de som ringer litar mer på en agent som känner sina gränser än på en som har fel med full övertygelse varannan gång.
RAG med låg latens för röst: få grounding att rymmas i turbudgeten
Grounding är värdelös om den spränger latensbudgeten och agenten tystnar. Rösten ger dig ungefär 800 ms–1,2 s tur och retur som tak innan samtalet känns trasigt, och RAG måste leva innanför det, inte ovanpå. Sikta på under 200 ms p90 för hämtning, så att merparten av budgeten blir kvar till ASR, LLM och TTS.
Tre saker gör röst-RAG tillräckligt snabb:
- Hybridsökning, inte ren vektorsökning. Kombinera BM25/nyckelord med täta embeddings och slå ihop rankningarna (reciprocal rank fusion). De som ringer säger artikelnummer, plannamn och interna smeknamn på policyer — exakta lexikala tokens som ren vektorhämtning missar. Hybriden fångar upp dem. Håll embedding-modellen liten och kvantiserad; du behöver ingen 7B-reranker i den heta vägen.
- Chunka för örat, inte för ögat. Webb-RAG chunkar på 500–1000 tokens. För röst chunkar du till ett talat svar — 1–3 meningar, självbärande, utan "som visas i tabellen ovan". En chunk ska vara något TTS kan läsa upp ordagrant och som ändå går ihop. Lagra ett kort, uttalbart
answer-fält vid sidan av källtexten. - Förvärm och cacha. Cacha embeddings för de vanligaste intenten, håll indexet i minnet och placera hämtningstjänsten hos orkestratorn för att slippa ett hopp mellan regioner. Samma latensingenjörskonst som vi tillämpar på SIP och mediapipelines gäller här: varje nätverksgräns är en skatt du betalar i varje tur.
En praktisk p90-fördelning inom en budget på 1 s: ASR-slutförande ~150 ms, hämtning ~180 ms, första LLM-token ~250 ms, första TTS-ljudet ~200 ms — med strömning, så att den som ringer hör tal innan hela svaret är avkodat.
Eval-harnesset för röst: bevisa groundedness före lansering
Du kan inte leverera noggrannhet hos en AI-röstagent på magkänsla. Du behöver ett offline-harness som poängsätter agenten mot undanhållna, verkliga transkriberingar och som grindar dina deployer. Fyra mått spelar roll:
- Faktakorrekthet — är varje påstående sant mot sanningskällan?
- Groundedness — har varje påstående stöd i den hämtade kontexten agenten faktiskt hade? (Ett påstående kan vara sant men ogrundat — det är tur, inte ett system.)
- Refusal-korrekthet — när svaret inte gick att hämta, avstod agenten i stället för att hitta på? Och omvänt: avstod den inte i onödan på frågor som gick att besvara?
- Transaktionell integritet — motsvarade varje uttalad bekräftelse ett verkligt verktygsresultat?
Bygg harnesset av anonymiserade produktionstranskriberingar (eller red team-manus) märkta med facit och med om frågan över huvud taget gick att besvara. Poängsätt varje tur med en deterministisk kontroll där det går och med en LLM som domare där det inte går:
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",
}
Aggregera till en groundedness-frekvens och en hallucinationsfrekvens, sätt en release-grind (t.ex. hallucinationsfrekvens < 0,5 % på det undanhållna datat, refusal-korrekthet > 98 %) och låt deployen falla om en prompt- eller modelländring försämrar den. Kör sviten vid varje modellbyte — en "bättre" basmodell kan i tysthet byta groundedness mot flyt. Det här är regressionstestning för sanning, och det är artefakten som förvandlar "vi tror att den är korrekt" till en siffra du kan visa en kund.
Skyddsräcken i produktion: konfidenströsklar och människa i loopen
Offline-evaler fångar kända felformer. Produktion behöver levande skyddsnät för de okända.
- Konfidenströsklar för hämtning. Om den högst rankade chunkens sammanslagna poäng ligger under ett golv, behandla det som "ingen grounding" och routa till refusal — svara inte utifrån en svag träff. En svag hämtning är en hallucination som väntar på att bli uttalad.
- Människa i loopen för intent med höga insatser. Tagga intent efter skadeområde. Öppettider och butiksadress: full autonomi. Avbokningar, återbetalningar över ett tröskelvärde, medicinska eller juridiska frågor, allt som flyttar pengar eller innebär ett åtagande: kräv en verktygsvaliderad väg, en bekräftande återläsning ("Just to confirm, you want to cancel order 4471 — yes or no?") eller en varm överlämning. Agentens befogenhet bör skala omvänt mot kostnaden för att ha fel.
- Logga varje påstående med dess källa. Varje uttalat faktapåstående bör bära med sig det
source_doc_iddet kom från i samtalsloggen. När en tvist uppstår kan du svara på "vad sa agenten och varför" på sekunder i stället för att gissa. Det matar också ditt eval-set — tvister från produktion är de mest värdefulla undanhållna fallen du någonsin får.
Stapla det här och de fyra fellägena har ingenstans att gömma sig: påhittad policy och påhittade priser blockeras av grounding och strukturerad utdata, falska bekräftelser av bindningen till verktygsresultatet, falska eskaleringar av allowlistan över vägar — och allt nytt slår i en konfidenströskel och landar i en elegant refusal.
Så löser Finn det här direkt ur lådan
Finns röstagenter är groundade som standard: svar enbart från hämtning, tvingad strukturerad utdata i varje transaktionell tur, ett refuse-and-route-lager kopplat till dina verkliga eskaleringskanaler och hybridhämtning under 200 ms inom budgeten för en samtalstur. Eval-harnesset följer med plattformen — rikta det mot dina transkriberingar och få en siffra på groundedness och hallucinationer före ett enda skarpt samtal. Vill du se din hallucinationsfrekvens på dina egna samtalsdata? Boka en teknisk Finn-demo.
Vanliga frågor
Kan promptteknik ensam stoppa hallucinationer i röst-AI? Nej. En grounding-prompt är nödvändig men läcker under belastning. Du behöver tvingad strukturerad utdata i transaktionella turer, bindning till verktygsresultat för bekräftelser och en eval-grind. Prompter sänker frekvensen; arkitekturen tar bort felläget.
Vad är skillnaden mellan faktakorrekthet och groundedness? Faktakorrekthet frågar "är påståendet sant?". Groundedness frågar "har påståendet stöd i den kontext agenten faktiskt hämtade?". Ett påstående kan vara sant av ren tur och ändå vara ogrundat — då fick ditt system rätt svar av fel skäl och kommer förr eller senare att få fel. Följ båda; grinda på groundedness.
Hur snabb måste RAG vara för röst? Sikta på under 200 ms p90 för hämtning så att den ryms i en konversationell tur och retur på ~800 ms–1,2 s utan att skapa död luft. Använd hybridsökning (nyckelord + vektor), små kvantiserade embeddings, ett index i minnet och placera hämtningen hos orkestratorn.
Hur vet jag att min röstagent inte hallucinerar innan den går live? Kör ett offline-eval-harness över undanhållna, märkta transkriberingar som poängsätter faktakorrekthet, groundedness, refusal-korrekthet och transaktionell integritet. Sätt en release-grind (t.ex. hallucinationsfrekvens under 0,5 %) och kör om den vid varje prompt- eller modelländring.




