音声AIのハルシネーションは、企業の音声エージェントがパイロットで止まり本番に到達できない最大の理由です。レイテンシーでも、話者のなまりでも、SIPでもありません。返品ポリシーをでっち上げるテキストチャットボットは、利用者が読み返して受け流せる程度の煩わしさで済みます。しかし、温かく自信に満ちた人間らしい声で "Yes, your appointment is confirmed for Tuesday at 3pm" と言い切る音声エージェントは——そんな枠が存在しないにもかかわらず——顧客が誰もいないオフィスに現れて初めて運用チームが気づく類のリスクです。
本記事は、事実に忠実な音声エージェントを本番投入するためのエンジニアリング指南書です。モデルが取得済みの事実からしか話せないようにする厳格なグラウンディング、トランザクション的なターンでの構造化出力の強制、「わかりません」を一級の結果として扱う拒否のスキャフォールディング、音声ターンの時間予算に収まる低レイテンシーRAG、そして実際の電話番号を接続する前にグラウンデッドネスを証明する音声AI評価ハーネス。この5点です。
なぜ音声というモダリティはハルシネーションのリスクを増幅するのか
チャットなら許容できる同じLLMのハルシネーションが、電話では危険になります。構造的な理由が3つあります。
さかのぼって読み返せない。 チャットの利用者は流し読みし、読み返し、2つ前のメッセージと矛盾していることに気づきます。音声は消えていきます。いったん発話されれば主張は残らず、記録は顧客の記憶(たいてい不正確)か、トラブルになるまで誰も読まない書き起こしの中にしかありません。エージェントが自信を持てていないことを示す視覚的な手がかりも存在しません。
声そのものが信頼のシグナルになる。 抑揚、話す速さ、自然なTTSの声は、人間の脳に能力の高さとして登録されます。カスタマーサポートの現場では、実際に正しかったかどうかに関係なく、自信ありげに聞こえるエージェントほど正確だと評価される傾向が一貫して見られます。TTSレイヤーは事実上、自分がいつ間違っているかまったく分からないモデルに、自信の増幅器を後付けしているのです。
ターンの時間的な圧力がモデルに断定を迫る。 音声エージェントは「考えている」あいだ4秒も黙っていられません。無音は会話を壊します。つまりデコードはレイテンシーの圧力下で行われ、モデルは空白を埋めようとします。そして空白を埋めるまさにその瞬間こそ、LLMが作話するときなのです。音声を人間らしく感じさせるのと同じ時間予算(300ミリ秒未満の音声アーキテクチャに関する当社の取り組みを参照)が、モデルを当てずっぽうへと誘惑します。
まとめると、音声はLLMの最悪の障害モードを取り込みながら、利用者がそれまで持っていた安全網をすべて取り去ります。だからこそ**AI音声エージェントの正確性**はプロンプト調整の問題ではなく、アーキテクチャの問題なのです。
実際に止めるべき4つの障害モード
「ハルシネーションを減らそう」という一般論は役に立ちません。音声エージェントが嘘をつく4つの経路は、被害の範囲も対策もそれぞれ違うからです。
- 捏造されたポリシー。 "You can return that any time within 90 days." 実際の期間は30日です。モデルはもっともらしい数字を補間しました。対策は取得結果のみに基づく応答——次のセクションで扱います。
- 捏造された価格。 "That plan is $49 a month." 正しくは59ドルです。数字はLLMが出力するトークンの中で最もリスクが高いものです。生成コストは低いのに、間違えたときの代償が大きいからです。対策は構造化出力の強制。価格を自由文生成の経路に通してはいけません。
- 偽の確定通知。 "You're all set, confirmation number A-4471." 予約は1件も書き込まれていません。モデルは、実際には起きていないツール呼び出しの成功を語りました(あるいはツールが応答する前にIDをハルシネーションしました)。対策はツール実行結果へのグラウンディング。エージェントはAPIが実際に返した内容しか確定として伝えられません。
- 偽のエスカレーション、偽の約束。 "I'm transferring you to a specialist who'll call back within the hour." そんなキューは存在しません。対策は拒否のスキャフォールディングに加えて、エージェントが実際に実行できるよう配線されたアクションの許可リストです。
構築するガードレールは、必ずこの4つのいずれかに紐づけてください。どれも減らさない制御は、単なる見せかけです。
厳格なグラウンディング:取得結果のみの応答と構造化出力の強制
中心となる原則は、モデルの仕事は取得した事実を言葉にすることであって、思い出すことではないという点です。パラメトリックメモリ——LLMが事前学習から「知っている」こと——は、業務上の質問への回答には使用禁止とします。
情報提供のターン(ポリシー、営業時間、価格、対象条件)では、システムプロンプトが出典のない主張を禁じる音声AI向けの取得パターンを使います。
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.
このプロンプトだけでは必要条件ではあっても十分条件になりません。プロンプトは漏れるからです。トランザクション的なターン(価格、日付、数量、ID、はい/いいえの確約が関わるもの全般)では、自由文の生成を完全にやめて構造化出力を強制します。アプリケーション側で検証し、決定論的に音声へレンダリングできる型付きオブジェクトをモデルに出力させてください。
{
"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
}
}
そのうえで、モデルではなく自分のコードが plan_id をキーに価格テーブルから price_cents を引き、source_doc_id が実在の文書でなければ発話を拒否します。モデルが選ぶのはどのプランかであり、数値はシステムが握ります。モデルが数字の出どころになることが一切ないので、価格の捏造は構造的に起こり得なくなります。
同じ規律が偽の確定通知も封じます。エージェントは生成された文字列から「確定しました」と言うことを許されません。book_appointment のツール呼び出しを発行し、本物のAPIレスポンスを待ち、返ってきた予約オブジェクトからテンプレート化された確定文が埋められます。ツールの結果がなければ確定もなし。例外はありません。これは決定論的なAIエージェントの構築で扱っているステートマシン的アプローチの自然な延長です。トランザクション的なターンは型付き遷移を持つ状態であって、自由な雑談ではありません。
拒否のスキャフォールディング:「わかりません」を設計された優雅な着地点にする
ハルシネーションの多くは、モデルが拒否することを拒否している状態です。会話の中に知識の欠落を認めることへの報酬が何もないため、モデルは認めるより作り出すほうを選びます。降り口はこちらで設計しなければなりません。
良い拒否は3つのことをします。取り繕わない、温かさを保つ、そして発信者を役に立つ場所へ導く。これを明示的に組み立てます。
# 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.
このプロンプトに構造化された拒否アクションを組み合わせ、ルーティングを決めるのはシステムにして、存在しない転送をモデルが約束できないようにします。
{
"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 は実際に配線済みのチャネルに照らして検証されます。この回線で human_handoff が設定されていなければ、システムはエージェントに作り話をさせるのではなく、次に利用可能な経路(折り返し電話、SMS)へ降格させます。これが4番目の障害モードを消し去る方法です。うまく設計された優雅な拒否はCSATを押し上げます。発信者は、半分の確率で自信満々に間違えるエージェントより、自分の限界をわきまえたエージェントを信頼するからです。
音声向けの低レイテンシーRAG:グラウンディングをターン予算に収める
レイテンシー予算を食い潰してエージェントが黙り込むなら、グラウンディングに価値はありません。音声では、会話が壊れていると感じられるまでの往復の上限はおおむね800ミリ秒〜1.2秒であり、RAGはその上に載せるのではなく、その中に収めなければなりません。予算の大半をASR、LLM、TTSに残すため、取得のp90を200ミリ秒未満に狙いを定めてください。
音声向けRAGを十分に速くする要素は3つあります。
- 純粋なベクトル検索ではなくハイブリッド検索。 BM25/キーワード検索と密ベクトルの埋め込みを組み合わせ、ランキングを融合します(reciprocal rank fusion)。発信者は品番、プラン名、社内での通称を口にします。これらは密ベクトルのみの取得が取りこぼす、字面どおりの語彙トークンです。ハイブリッドならこれを拾えます。埋め込みモデルは小さく量子化したものにとどめてください。ホットパスに7Bのリランカーは不要です。
- 目ではなく耳のためにチャンクを切る。 ウェブ向けRAGは500〜1000トークンで区切ります。音声では1回の発話で答え切れる単位、つまり1〜3文、単体で完結し、「上の表に示すとおり」といった表現を含まない形に切ります。チャンクは、TTSがそのまま読み上げても意味が通るものであるべきです。原文と並べて、短く読み上げやすい
answerフィールドを保存しておきましょう。 - 事前ウォームアップとキャッシュ。 上位インテントの埋め込みをキャッシュし、インデックスをメモリ上に置き、リージョンをまたぐホップを避けるために取得サービスをオーケストレーターと同居させます。SIPやメディアパイプラインに適用しているのと同じレイテンシー設計がここでも通用します。ネットワーク境界はすべて、毎ターン支払う税金です。
1秒の予算内での現実的なp90の内訳は、ASRの確定に約150ミリ秒、取得に約180ミリ秒、LLMの初回トークンまで約250ミリ秒、TTSの初回音声まで約200ミリ秒。応答全体のデコードを待たずに発信者が音声を聞き始められるよう、ストリーミングを併用します。
音声評価ハーネス:公開前にグラウンデッドネスを証明する
AI音声エージェントの正確性を勘で出荷することはできません。ホールドアウトした実データの書き起こしでエージェントを採点し、デプロイのゲートにするオフラインのハーネスが必要です。重要な指標は4つです。
- 事実正確性 — 各主張は正となる情報源に照らして真か。
- グラウンデッドネス — 各主張は、エージェントが実際に手にしていた取得コンテキストに裏づけられているか。(真ではあるがグラウンディングされていない主張はあり得ます。それは運であって、システムではありません。)
- 拒否の妥当性 — 答えが取得できなかったとき、エージェントは捏造せずに拒否したか。逆に、答えられる質問に対して過剰に拒否していないか。
- トランザクションの整合性 — 発話されたすべての確定通知が、本物のツール実行結果に対応していたか。
ハーネスは、匿名化された本番の書き起こし(またはレッドチームのスクリプト)に、正解と「そもそも回答可能だったか」のラベルを付けて構築します。各ターンは可能な限り決定論的なチェックで、それが無理な部分はLLMによる判定で採点します。
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",
}
結果を集計してグラウンデッドネス率とハルシネーション率を出し、リリースゲートを設定し(例:ホールドアウトセットでハルシネーション率が < 0.5%、拒否の妥当性が98%超)、プロンプトやモデルの変更でこれが悪化したらデプロイを失敗させます。モデルを差し替えるたびにスイートを回してください。「より優れた」ベースモデルが、流暢さと引き換えにグラウンデッドネスをひそかに手放すことがあります。これは真実に対する回帰テストであり、「たぶん正確だと思う」を顧客に見せられる数値へと変える成果物です。
本番のガードレール:信頼度のしきい値と人間による介入
オフライン評価が捉えるのは既知の障害の形です。未知のものに対しては、本番に稼働中のセーフティネットが必要です。
- 取得の信頼度しきい値。 最上位チャンクの融合スコアが下限を下回ったら「グラウンディングなし」として扱い、拒否へルーティングします。弱い一致から答えを組み立ててはいけません。弱い取得結果は、発話されるのを待っているハルシネーションです。
- 影響の大きいインテントには人間を介在させる。 インテントを被害範囲でタグ付けします。営業時間や店舗の場所なら完全に自律で構いません。解約、一定額を超える返金、医療や法律に関する質問、金銭が動くものや確約を伴うものは、ツールで検証された経路、確認の復唱("Just to confirm, you want to cancel order 4471 — yes or no?")、または人への丁寧な引き継ぎを必須にします。エージェントの権限は、間違えたときのコストに反比例させるべきです。
- すべての主張を出典付きで記録する。 発話された事実の主張はすべて、通話ログの中に由来する
source_doc_idを持たせてください。トラブルが起きたとき、「エージェントは何をなぜ言ったのか」に推測ではなく数秒で答えられます。これは評価セットの供給源にもなります。本番で発生したトラブル事例は、手に入る中で最も価値の高いホールドアウトケースです。
これらを積み重ねれば、4つの障害モードに隠れ場所はなくなります。ポリシーと価格の捏造はグラウンディングと構造化出力が止め、偽の確定通知はツール実行結果への束縛が止め、偽のエスカレーションは経路の許可リストが止めます。そして未知の事象は信頼度のしきい値に引っかかり、優雅な拒否へと流れます。
Finnはこれをどう標準で解決しているか
Finnの音声エージェントは初期状態からグラウンディングされています。取得結果のみに基づく応答、トランザクション的なターンごとの構造化出力の強制、実際のエスカレーションチャネルに接続された拒否・ルーティングのレイヤー、そして音声ターンの予算内に収まる200ミリ秒未満のハイブリッド取得。評価ハーネスはプラットフォームに同梱されており、自社の書き起こしに向けるだけで、1件の実通話も行う前にグラウンデッドネスとハルシネーションの数値が得られます。自社の通話データでハルシネーション率を確認しませんか。Finnの技術デモを予約する。
よくある質問
プロンプトエンジニアリングだけで音声AIのハルシネーションを止められますか。 止められません。グラウンディング用のプロンプトは必要ですが、負荷がかかると漏れます。トランザクション的なターンでの構造化出力の強制、確定通知に対するツール実行結果への束縛、そして評価によるゲートが必要です。プロンプトは発生率を下げますが、障害モードそのものを取り除くのはアーキテクチャです。
事実正確性とグラウンデッドネスの違いは何ですか。 事実正確性は「その主張は真か」を問います。グラウンデッドネスは「その主張は、エージェントが実際に取得したコンテキストに裏づけられているか」を問います。主張がたまたま真でありながらグラウンディングされていないこともあり、その場合は誤った理由で正しい答えにたどり着いたということなので、いずれ誤った答えを返します。両方を追跡し、ゲートはグラウンデッドネスで設けてください。
音声ではRAGはどのくらい速い必要がありますか。 無音を生まずに約800ミリ秒〜1.2秒の会話往復に収まるよう、取得のp90を200ミリ秒未満に狙ってください。ハイブリッド検索(キーワード+ベクトル)、小さく量子化した埋め込み、メモリ上のインデックスを用い、取得処理をオーケストレーターと同居させます。
公開前に音声エージェントがハルシネーションしないとどう確認できますか。 ホールドアウトしたラベル付きの書き起こしに対してオフラインの評価ハーネスを走らせ、事実正確性、グラウンデッドネス、拒否の妥当性、トランザクションの整合性を採点します。リリースゲート(例:ハルシネーション率0.5%未満)を設定し、プロンプトやモデルを変更するたびに再実行してください。




