ハルシネーション入門|LLM誤生成の対策

Claude Code活用

※ この記事にはアフィリエイトリンクが含まれています。詳細はプライバシーポリシーをご確認ください。

LLMの出力をそのまま信じて公開資料に貼ったら、数値や日付が事実と違っていた。こうした事故の根本原因がハルシネーションです。

この記事は、コードが書けるエンジニア向けにハルシネーションを実装視点で整理します。発生する仕組み、検出の3つのアプローチ、対策の実装パターン、業務適用での切り分けまでをコード付きで解説します。

僕は普段、Claude CodeやAPIで自動化スクリプトを書きながら、生成結果の事実検証で痛い目を見てきました。本記事はそこで効いた検証パターンだけを抜き出した実装ガイドです。

本記事はAI学び直し|エンジニアの実務スキル4階層シリーズの第8回(最終回)にあたります。横断トピックである「品質・運用」の中核として、ハルシネーション対策を取り上げます。

こんな方に読んでほしい

  • LLMの出力を業務スクリプトや公開資料に組み込んでいて、誤生成のリスクを下げたい方
  • RAGを実装したが、それでも誤った回答が混じる原因を知りたい方
  • ハルシネーションの検出と対策を、抽象論ではなくコードで学びたい方
  • 「事実検証必須の業務」と「そうでない業務」の切り分け基準を整理したい方

ハルシネーションとは何か

結論:事実と異なる出力をもっともらしく生成する現象

ハルシネーションとは、LLMが事実と異なる、または根拠のない情報をもっともらしい文体で生成する現象です。日本語では「幻覚」「誤生成」と訳されます。

AIに業務を任せる範囲が広がる2026年、ここを甘く見ると誤った情報を顧客や社内に出してしまう事故に直結します。仕組みで潰すしかない、というのが実装視点での結論です。

厄介なのは、出力の文体が自信に満ちていて、人間が一読しただけでは誤りに気づきにくい点です。「実在しない論文を引用する」「存在しないAPIを案内する」「日付を1年ずらす」といった形で表れます。

業務での向き合い方は各社の公式情報が参考になります。Anthropic Reduce hallucinationsOpenAI Evals guideは、評価と緩和の実装視点で読むと理解が深まります。

なぜ起きるのか:3つの構造的要因

ハルシネーションは、LLMの設計上避けられない構造的な要因から生じます。

  • 確率的な生成:LLMは次のトークンを確率分布から選ぶ仕組みで、事実検索エンジンではありません
  • 学習データのバイアス:ネット上の不正確な情報も学習しており、誤った情報を「もっともらしさ」として記憶します
  • 知識のカットオフ:学習データの収集時点以降の情報は持たず、それでも推測で答えてしまうケースがあります

つまり「LLMは検索エンジンではない」という前提を理解しないまま使うと、確実にハルシネーションを踏みます。賢く見える出力ほど、構造上は推測である可能性が残っています。

検出の3つのアプローチ

ハルシネーション対策は、まず検出できる仕組みを持つところから始まります。代表的なアプローチは3つです。

ハルシネーション発生→検出→対策フロー|Self-check/Citation/RAG/検証パスの組み合わせ

Self-consistency check:複数回投げて多数決

同じ質問を複数回投げて、回答が揺れるかを見るアプローチです。揺れる質問は、LLMが確信を持っていない可能性が高いと判断できます。

実装は単純で、temperatureを上げて3回投げ、結果の一致度を見ます。

Citation照合:根拠の有無を確認

出力に「根拠URL」を含ませ、後段でそのURLを取得して内容を照合する手法です。LLMの出力単体では信用しない、という割り切りが本質です。

RAG(外部情報を検索して回答に使う仕組み)と組み合わせると効果が高くなります。RAGは前回のMCP記事でも触れたとおり、外部情報を取り込む基本的な仕組みです。

複数モデル比較:別系統のLLMで再検証

OpenAIのモデルとAnthropicのモデルなど、系統の違うLLMで同じ質問を試すアプローチです。両方が同じ結論なら信頼度が上がり、食い違うなら要確認の合図になります。

同じファミリーのモデル(GPT-4とGPT-4o)で比較しても、共通のバイアスを引き継いでいる可能性があるため、別ベンダーで突き合わせるのが定石です。

対策の実装パターン

検出できたら、次は対策です。実務でよく使う4パターンをコード例で示します。

パターン1:Self-consistency check

同じ質問を3回投げ、結果が一致するか確認する最小実装です。

// Self-consistency check の最小実装
async function selfConsistencyCheck(
  question: string,
  attempts = 3
): Promise<{ answer: string; confidence: number }> {
  const results: string[] = [];
  for (let i = 0; i < attempts; i++) {
    const res = await llm.chat({
      system: "簡潔に1文で回答してください。",
      user: question,
      temperature: 0.7,
    });
    results.push(res.content.trim());
  }
  // 多数決で最頻値を選ぶ
  const counts = new Map<string, number>();
  results.forEach(r => counts.set(r, (counts.get(r) ?? 0) + 1));
  const [answer, count] = [...counts.entries()].sort((a, b) => b[1] - a[1])[0];
  return { answer, confidence: count / attempts };
}

confidence値が1.0未満の質問は要レビューフラグを立てる、といった運用に組み込めます。「3回投げても揺れる質問はLLM単体に任せない」という基本ルールが作れます。

パターン2:Citation強制と検証

出力に必ず根拠URLを含ませ、後段でURL取得して照合します。

const prompt = `
質問: ${question}

回答は以下のJSONスキーマに従ってください。
{
  "answer": "回答文",
  "citations": ["根拠URL1", "根拠URL2"]
}

citationsに含めるURLは、回答内容を直接裏付ける一次情報のみです。
推測で記載してはいけません。確証がない場合は空配列にしてください。
`;

const res = await llm.chat({
  user: prompt,
  response_format: { type: "json_object" },
  temperature: 0,
});

const parsed = JSON.parse(res.content);
// 後段でURLを実際に取得し、内容と回答の整合をチェック
for (const url of parsed.citations) {
  const page = await fetch(url).then(r => r.text());
  // 検証ロジック(キーワード一致/別LLMでの再評価等)
}

注意点として、LLMはURL自体をハルシネーションすることがあります。実在しないURLを「それっぽく」生成するため、後段での実取得チェックは必須です。

パターン3:別LLMによるSelf-check

生成結果を別のLLMに「批判的に評価させる」パターンです。同じLLMでチェックすると同じ誤りを正解扱いするリスクがあるため、別系統のモデルで突き合わせるのが鉄則です。

// 生成はOpenAI、検証はAnthropicなど系統を分ける
async function crossModelVerify(
  question: string,
  answer: string
): Promise<{ ok: boolean; reason: string }> {
  const verifyPrompt = `
次の質問と回答を批判的に評価してください。
質問: ${question}
回答: ${answer}

事実誤認・論理矛盾・根拠不足のいずれかがあれば ok=false にしてください。
出力: { "ok": boolean, "reason": string }
`;
  const res = await anthropic.chat({
    user: verifyPrompt,
    response_format: { type: "json_object" },
    temperature: 0,
  });
  return JSON.parse(res.content);
}

検証側のプロンプトでは「批判的に」「根拠不足」などの語を入れると、肯定バイアスが弱まります。両モデルがOKと判断した結果のみを採用する運用にすれば、誤生成の混入率は大きく下がります。

パターン4:RAGと組み合わせたCitation付き生成

RAGで取得した文書のみを根拠にして回答させる、最も実務に近いパターンです。

// RAG検索 → 検索結果のみを根拠にCitation付きで回答
const docs = await vectorStore.search(question, { topK: 5 });
const context = docs.map((d, i) => `[${i + 1}] ${d.text}`).join("\n\n");

const prompt = `
以下の参考資料のみを根拠にして質問に回答してください。
参考資料に書かれていない事実は使わず、不明な場合は「資料外」と回答してください。

参考資料:
${context}

質問: ${question}

出力は { "answer": string, "used_refs": number[] } のJSON形式。
used_refs には実際に根拠とした参考資料の番号を入れてください。
`;

「資料外なら資料外と答える」という逃げ道を明示することが重要です。これがないと、LLMは根拠がなくても無理やり答えを作ろうとします。used_refsを返させると、後段で参照箇所を画面に表示する設計にも繋がります。

業務適用での切り分け

すべての業務にハルシネーション対策をフル装備する必要はありません。事実検証が必須の領域とそうでない領域を切り分けるのが現実的な落とし所です。

切り分けの基準

領域 事実検証の必要性 推奨パターン
公開資料/顧客向け回答 必須 RAG+Citation+人間レビュー
社内ナレッジQA RAG+Citation
コードレビュー支援 人間が最終判断
アイデア出し/文章下書き そのまま使用可

業務の性質ごとに必要な対策レベルが変わります。すべてに最大コストの検証パスを敷くと、運用が回らなくなります。

僕の経験でも、検証強度を一律で揃えると「アイデア出し用途」が遅すぎて使われなくなりました。タスクごとに「事実誤りが起きたときの被害規模」を見積もり、被害が大きい領域だけに重い検証を載せるのが現実解です。

評価指標:FactScoreとTruthfulQA

研究領域では、ハルシネーションの定量評価指標がいくつか提案されています。

  • FactScore:生成文を事実単位に分解し、それぞれが裏付け可能か判定して比率を出す指標です
  • TruthfulQA:人間が誤答しやすい質問群でLLMの真実度を測るベンチマークです

業務で完全に再現するのは重いですが、「事実単位に分解して各々を検証する」という発想はそのまま実務に使えます。長文を一括で評価せず、文や箇条書き単位で検証する設計が筋がよいです。

よくある失敗パターン

初学者がハマりやすい3つのパターンを共有します。

失敗1:「LLMは賢いから事実は正しい」という過信

「最新のフラッグシップモデルなら正しい答えを返すはずだ」という前提でファクトチェックを省く運用は、確実に事故ります。モデルが賢くなるほど、誤りも文体的に巧妙になるのが厄介な点です。

賢さと正確さは別物だという前提に立ち、検証パスは必ず残しておきます。LLMの精度向上は「人間がチェックすべき箇所」を減らすのではなく、「チェックの効率を上げる」方向に効くと考えるとバランスが取りやすくなります。

失敗2:Self-checkを同じLLMで回す

「自分の出力を自分で評価させる」だけでは、同じバイアスを共有しているため誤りを誤りと判断できません。違う系統のモデルで突き合わせるか、ルールベースの後処理を組み合わせるのが定石です。

同じモデルファミリー(GPT-4とGPT-4o等)でも、誤りパターンが類似することが多いです。検証は必ずベンダーをまたぐ設計にします。

失敗3:数値や日付を精査せずに公開する

料金、統計値、日付、固有名詞は、LLMが最も間違えやすい情報です。「ChatGPT Plusの料金は20ドル」のような事実でさえ、時期によって変動します。

記事や公開資料に組み込む前に、数値と日付は必ず一次情報で確認します。LLMの出力を一次情報の代わりに使ってはいけません。これはRAGやCitationを使っていても同じで、最終的に人間が裏取りする工程は省けません。

もっと深く学ぶなら

ハルシネーションを評価・対策する技術は、機械学習の評価指標と地続きです。データ分析・機械学習を体系的に学び直したいフェーズに入ったら、スタアカ(スタビジアカデミー)が選択肢になります。

  • デメリット:数学・SQLが薄い人には序盤がしんどい
  • メリット:月額固定で長期の学び直しに耐える/評価指標まで踏み込む内容

スタアカ(スタビジアカデミー)の有料プランを確認する

シリーズ完結|AI学び直し8語の振り返り

本記事をもって、AI学び直し|エンジニアの実務スキル4階層シリーズは完結です。エンジニアが押さえておくべき8つの基礎用語を、実装視点で順に取り上げてきました。

シリーズ全体を改めて並べると次の通りです。

テーマ 階層上の位置づけ
第1回 プロンプトエンジニアリング 第1階層:生成AI活用の入口
第2回 コンテキストウィンドウ 第1階層:扱える情報量の上限
第3回 Embedding 第2階層:意味の数値表現
第4回 RAG 第2階層:外部知識の活用
第5回 Function Calling 第3階層:外部実行の橋渡し
第6回 AIエージェント 第3階層:自律的な実行ループ
第7回 MCP 第3階層:エージェント連携の標準
第8回 ハルシネーション(本記事) 横断:品質・運用

第1〜2回は「指示と入力」、第3〜4回は「意味検索と外部知識」、第5〜7回は「外部実行と自律化」、そして本記事の第8回が全体に効く品質・運用の横串です。8つの用語は独立した点ではなく、入力→意味処理→実行→品質という1本の流れに並びます。

シリーズを書ききって思うのは、AI活用の鍵は「賢いモデルを使うこと」ではなく「ワークフローのどこに何を組み込むか」を設計できることだという点です。プロンプトもRAGもエージェントも、組み合わせて初めて業務に効く形になります。

進展や新しい知見があれば、このブログで継続的に共有していきます。シリーズで取り上げきれなかった評価フレームワークや実運用のログ設計についても、できたら定点観測の記事を書いてみたいと考えています。

まとめ|LLMは検索エンジンではない、を前提にする

ハルシネーションは、LLMの確率的な生成という構造から避けられない現象です。「LLMは検索エンジンではない」という前提から運用を組み立てるのが出発点になります。

検出はSelf-consistency check、Citation照合、複数モデル比較の3アプローチが基本です。対策はRAGとCitation強制を軸に、Self-checkは別系統モデルで回し、業務領域ごとに検証レベルを切り分けます。

明日からの実務で、まず「数値と日付は一次情報で裏取りする」運用ルールから始めてみてください。それだけで公開資料の事故率は大きく下がります。本シリーズが、AIを「賢く見える道具」ではなく「設計して使う道具」に変えるきっかけになれば嬉しく思います。

コメント

タイトルとURLをコピーしました