ベクトル検索の「沼」から抜け出すための、もう一つの選択肢
「RAG(Retrieval-Augmented Generation)を構築してみたが、思うような精度が出ない」
最近、こうした課題を抱える組織が増加しています。チャンクサイズの調整、埋め込みモデルの選定、ベクトルデータベースのチューニング、そしてリランク(Re-ranking)処理の実装など、検索精度を上げるために積み上げたエンジニアリングの塔が、いつしか複雑怪奇な「技術的負債」となりつつあるケースが少なくありません。
そこに登場したのが、Geminiモデルに代表されるLong Context(長文コンテキスト)対応モデルです。100万、200万トークンという広大なウィンドウサイズは、「検索処理を省き、マニュアルやドキュメントをすべてプロンプトに含めてしまえばよいのではないか」というアプローチをシステム開発の現場に提示しています。
結論から言えば、そのアプローチは半分正解であり、半分間違いです。
確かに、全データをコンテキストに含めることで、検索漏れによる回答不能は防ぐことができます。文脈を分断することなく、ドキュメント全体を俯瞰した推論が可能になる点も大きなメリットです。しかし、ここで重要になるのが、コンピュータサイエンスの基本原則であるGIGO(Garbage In, Garbage Out:ゴミを入れればゴミが出る)です。
自然言語処理であれ画像認識であれ、モデルに入力するデータの「純度」と「構造」が推論精度を決定づけるという事実は変わりません。広大なコンテキストウィンドウは、無秩序にデータを放り込む場所ではなく、AIが論理的に思考するための「作業スペース」として捉える必要があります。
本記事では、RAGの構築・運用コストに課題を感じ、Long Contextへの移行を検討しているエンジニアの方々に向けて、「AIが理解しやすい」データ加工の鉄則を解説します。単にテキストをコピー&ペーストするのではなく、いかにしてデータを前処理(ETL)し、構造化して渡すべきか。データ分析とシステム開発の観点から、実用的なエンジニアリング手法を共有します。
なぜLong Contextでも「データ加工」が必要なのか
「すべてのデータを読み込めるのであれば、加工は不要ではないか」
そう思われるかもしれません。しかし、LLM(大規模言語モデル)の仕組み、特にTransformerアーキテクチャの根幹である注意機構(Attention Mechanism)の特性を理解すれば、無加工データを入力するリスクが明らかになります。
「全部入り」でも発生する幻覚(ハルシネーション)のメカニズム
Attention機構は、入力されたトークン間の関係性を計算し、どの情報に「注目」すべきかを決定します。コンテキスト長が伸びるということは、それだけ「注目すべき候補」が爆発的に増えることを意味します。
もし、入力データの中に、古い仕様書の記述(ノイズ)や、文脈と無関係なヘッダー・フッター情報が大量に含まれていたらどうなるでしょうか。モデルのAttentionは分散し、本来注目すべき「正解データ」への重み付けが弱まります。結果として、モデルは自信を持って回答できず、もっともらしい不正確な情報(ハルシネーション)を生成したり、誤った情報を拾い上げたりするリスクが高まります。
Lost in the Middle現象と情報の優先順位
また、「Lost in the Middle(中だるみ)」現象も考慮する必要があります。多くのLLMは、コンテキストの冒頭と末尾にある情報を重視し、中間にある情報を忘却、あるいは軽視する傾向があります。
Google公式サイト等の情報によると、Geminiモデルや、その後継となるGeminiの最新モデル(Geminiの最新モデルシリーズ等)では、適応型思考(Adaptive Thinking)などの新技術により、長大なコンテキストに対する耐性が飛躍的に向上しています。しかし、モデルがいかに進化しようとも、情報の密度が薄いテキストを大量に入力すれば、重要な記述がノイズの中に埋没する物理的なリスクは否定できません。
トークン課金コストと情報密度のROI
さらに、実務的な観点ではコストが重要な課題となります。Geminiの最新ラインナップ(Flashモデル等)では、処理速度の向上とともにトークン使用量の削減やコスト効率化が進んでいますが、無意味な改行、重複した定型文、不要なメタデータにまで毎回課金されるのは、システム開発として最適とは言えず、財務的にも非効率です。
情報の密度を高め、モデルが処理しやすい形に整形すること。これは、推論精度の向上とコスト削減の両面において、モデルの世代を問わず必須のプロセスと言えます。
Step 1: データ収集とスコープ定義
それでは、具体的なデータパイプラインの構築について解説します。最初のステップは、組織内に散在するドキュメントの中から「何を入力データとして採用するか」を選定することです。
ドキュメントの「鮮度」と「信頼性」によるフィルタリング
RAGシステムで頻発する課題の一つが、ファイルサーバーにあるドキュメントをクローラーで無差別に収集してしまうことです。Long Context戦略においても、これはシステムの精度低下を招く要因となります。
まず実施すべきは、ファイルメタデータやファイル名に基づくフィルタリングです。
- 更新日時: 例えば「最終更新が3年以上前のファイル」は、現在の業務ルールと乖離している可能性が高いため除外、または「アーカイブ」としてタグ付けします。
- ファイル名:
_old,_bak,コピー ~といった文字列が含まれるファイルは、重複や旧版である確率が高いため、スクリプトで自動的に除外リストに追加します。
重複コンテンツの排除戦略
同じマニュアルのPDF版とWord版、あるいはWikiのページとそれを印刷用に整形したPDFなどが混在しているケースも多々あります。これらを両方入力すると、トークンを無駄に消費するだけでなく、情報の重複によりモデルが混乱する原因になります。
ハッシュ値(MD5やSHA-256)を用いた完全一致の排除はもちろん、SimHashやMinHashなどのアルゴリズムを用いて「類似度が高いドキュメント」を検出し、代表的な1つだけを残す処理(Deduplication)を実装することを推奨します。
テキスト以外の情報(表、画像)の扱い方
Geminiはマルチモーダルモデルであり、画像認識技術により画像やPDFのレイアウトを直接理解することが可能です。しかし、純粋なテキスト情報として抽出できるものは、テキスト化した方がトークン効率が良い場合があります。
- 複雑な図表・グラフ: 画像として切り出し、Geminiに入力する(マルチモーダル入力)。
- 単純な表: Markdownの表形式やCSVテキストに変換する。
- 装飾的な画像: 処理対象から除外する。
この振り分けを行うことで、コンテキストの「情報密度」を最大化できます。
Step 2: データクレンジングとノイズ除去
収集したデータをテキスト化(OCRやPDF抽出)した後、そのままLLMに渡すことは推奨されません。最新のAI-OCR技術は進化していますが、ここでのクレンジングが、最終的な回答精度を左右する重要な工程となります。
ヘッダー・フッター・定型文の削除処理
業務ドキュメントには、全ページに共通のヘッダー(ロゴ、文書番号)やフッター(ページ番号、「取り扱い注意」などの警告文)が含まれていることが一般的です。これらが数千ページ分繰り返されると、モデルにとっては強力なノイズとなります。
Pythonであれば、正規表現を用いてこれらのパターンを除去することが可能です。
import re
# ページ番号や警告マークの削除例
def clean_text(text):
# ページ番号 (例: - 12 -)
text = re.sub(r'\n\s*-\s*\d+\s*-\s*\n', '\n', text)
# フッターの定型文
text = re.sub(r'Confidential\s+Property\s+of\s+Organization', '', text)
# 連続する空行を1つにまとめる
text = re.sub(r'\n{3,}', '\n\n', text)
return text
このように、意味を持たないトークンを削ぎ落とすことで、モデルは「本文」の解析に集中できるようになります。
個人情報(PII)と機密情報のマスキング
ドキュメント活用において避けて通れないのがセキュリティの確保です。特に、電話番号やメールアドレスなどが含まれている場合、LLMに入力すること自体がリスクになり得ます。
Microsoft PresidioのようなPII(Personal Identifiable Information)検出ライブラリや、正規表現を用いたパターンマッチングで、これらの情報を <PHONE_NUMBER>, <EMAIL> といったプレースホルダーに置換します。最新の商用OCR製品の中には、マスキング機能を標準搭載するものも登場していますが、データ分析のパイプライン側でも二重のチェックを行うことで、セキュリティリスクを低減しつつ文脈構造を維持できます。
OCRノイズと表記ゆれの訂正プロセス
PDFや紙文書からのテキスト抽出において、OCRエンジンの選定と後処理は極めて重要です。
2025年末から2026年にかけてのトレンドとして、主要なAI-OCR製品は、ETL機能の統合やレイアウト認識精度の向上を果たしています。最新版では、複雑な帳票の「仕切り紙」自動判定や、表構造の維持、さらには読み取り結果のCSV加工までをOCR側で完結できるケースが増えています。また、各種クラウドサービスも、図表構造を維持したままドキュメント化する能力を進化させています。
しかし、Geminiのようなロングコンテキストモデルに入力する際は、OCRツールが出力する生のテキストをそのまま使うのではなく、以下の点に注意して正規化を行う必要があります。
- 不自然な改行の結合: 日本語ドキュメント特有の、行末で単語が分断される現象をルールベースで結合します。
- メタデータの削除: 高機能なOCRほど詳細な位置情報や信頼度スコアを出力しますが、LLMの推論には不要なタグ情報となるため削除します。
- 表記ゆれの統一: OCRの誤認識による表記のばらつき(例: 「l」と「1」、「O」と「0」など)を、軽量な言語モデルや辞書ベースで補正します。
OCR側で処理できる範囲(レイアウト解析や一次的なデータ加工)と、パイプライン側で担うべき範囲(LLM向けの意味的な正規化)を明確に分けることが、高品質なコンテキスト設計の鍵となります。
Step 3: XMLタグによる情報の構造化
ここが本記事の重要なポイントです。Gemini(および多くの高性能LLM)は、XMLタグで構造化されたデータを非常に効率的に処理できます。単なる平文の羅列ではなく、タグを使って情報の「境界線」と「属性」を明示することで、モデルの理解度は飛躍的に向上します。
Geminiが理解しやすいXMLタギングのベストプラクティス
プロンプトエンジニアリングの一般的なガイドラインでも推奨されていますが、複数のドキュメントをコンテキストに含める際は、以下のようなXML構造を採用することが効果的です。
<documents>
<document index="1">
<source>server_manual_v3.pdf</source>
<category>Troubleshooting</category>
<created_at>2024-01-15</created_at>
<content>
サーバーが起動しない場合の対処法について説明します。...
</content>
</document>
<document index="2">
<source>network_config.docx</source>
<category>Configuration</category>
<created_at>2023-11-20</created_at>
<content>
ネットワーク設定の手順は以下の通りです。...
</content>
</document>
</documents>
ドキュメントごとのメタデータ(日付、著者、カテゴリ)付与
上記の例にある <source>, <created_at>, <category> といったメタデータが重要です。ユーザーが「最新のマニュアルに基づいて教えて」と質問した際、モデルはこの <created_at> タグを参照して、古いドキュメントよりも新しいドキュメントの情報を優先すべきだと判断できるようになります。
平文の中に「これは2024年1月15日の文書です」と記述するよりも、タグとして明示した方が、モデルにとってはるかに処理しやすい(Attentionを向けやすい)情報となります。
セクション区切りと階層構造の明示
ドキュメント内部も、可能な限り構造化します。見出しレベルに合わせて <section title="..."> や <h2_header> といったタグを挿入することで、モデルは文書の論理構造を把握しやすくなります。
特に長いマニュアルでは、どこからどこまでが「トラブルシューティング」の章なのかをタグで囲むことで、文脈の混同を防ぐことができます。
Step 4: コンテキストアセンブリとプロンプト統合
データが準備できたら、それをプロンプトの中にどう配置するか(アセンブリ)を設計します。
システム命令とデータブロックの配置順序
一般的に、以下の順序でプロンプトを構成するのが効果的です。
- System Instruction(役割定義): 「あなたはヘルプデスクのAIアシスタントです...」
- Context Data(加工済みデータ): 先ほどのXML構造化データ群。
- Task Instruction(具体的な指示): 「以下のドキュメントに基づき、ユーザーの質問に回答してください。ドキュメントにない情報は『不明』と答えてください。」
- User Input(ユーザーの質問): 実際の質問。
特に重要なのは、データブロック(2)を、システム命令(1)と具体的な指示(3)で挟み込む「サンドイッチ構造」にすることです。データ量が膨大になると、冒頭の命令が薄れることがあるため、データの直後にもう一度制約事項(「事実に基づかない回答を避ける」「ソースを明示する」など)を念押しすることが有効です。
Few-Shot事例の効果的な配置(動的挿入)
回答のフォーマットを固定したい場合(例えば、必ず「結論→理由→参照元」の順で答えるなど)、数件の回答例(Few-Shot)をプロンプトに含めます。これはTask Instructionの直前、または直後に配置すると効果的です。
キャッシュ活用(Context Caching)を前提としたデータ構成
Geminiシリーズ(最新のGeminiの最新モデルやGeminiの最新モデルを含む)では、Context Caching機能が利用可能です。これは、一度送信した大量のコンテキストをキャッシュし、2回目以降の入力コストと処理時間を大幅に削減する機能です。
公式サイトの情報によると、Geminiの最新モデルへの移行が進む現在でも、このキャッシュ機能は大規模コンテキストを扱う上で中心的な役割を果たします。特にFlashモデルなどでは、処理速度の向上と合わせて高い費用対効果が期待できます。
この機能を最大限に活用するためには、プロンプトの前半部分(System Instruction + Context Data)を固定する必要があります。ユーザーの質問ごとに変わる部分はプロンプトの末尾に配置し、重たいドキュメントデータ部分は変更しないように設計することで、キャッシュのヒット率を高め、運用コストを劇的に下げることができます。
品質検証と運用サイクルの確立
最後に、構築したシステムが正しく機能しているかを確認する方法について述べます。RAGと同様、Long Contextアプローチでも評価は必須です。特にモデルの進化は速く、公式サイト(2026年1月時点)によると、GeminiモデルからGeminiの最新モデルへの移行が段階的に進んでいます。最新モデルの特性を活かすためにも、継続的な検証サイクルが重要になります。
Needle In A Haystack(干し草の中の針)テストの自社版作成
「Needle In A Haystack」は、大量のテキストの中に隠された特定の事実(針)を、モデルが正確に抽出できるかを測るテストです。これを実際の運用データで行います。
例えば、マニュアルの隅にしか書かれていない特定のエラーコードの意味や、マイナーな製品の仕様を質問するテストセットを作成します。
さらに、最新のGeminiの最新モデルなどでは「適応型思考(Adaptive Thinking)」機能により推論能力が強化されています。そのため、単に事実を抜き出すだけでなく、ドキュメント内の離れた場所にある複数の情報を統合して回答させるような、より高度なテストケースを含めることも有効です。これを定期的に実行することで、コンテキスト量が増えた際や、モデルのバージョンアップ時に精度が維持されているかを監視します。
回答精度とトークン消費量のモニタリング
運用フェーズでは、回答のフィードバック(Good/Bad)だけでなく、1クエリあたりのトークン消費量も監視することが推奨されます。
コスト管理の観点では、モデルの選択も重要です。Googleの公式情報によると、Geminiの最新モデルは従来モデルと比較してトークン使用量が20~30%削減され、処理速度も向上しています。難易度の高い推論にはProモデル、高速な応答が必要な場合はFlashモデルといった使い分けを検討すべきでしょう。
不要なドキュメントがコンテキストに含まれ続けていないか、キャッシュが有効に機能しているかをチェックし、定期的にデータの整理と再構造化を行うサイクルを回します。
まとめ
Geminiモデルから始まり、現在のGeminiの最新モデルへと続くLong Contextの進化は、RAGの複雑なパイプラインを不要にする可能性を秘めています。しかし、それは「何もしなくていい」という意味ではありません。むしろ、「検索のエンジニアリング」から「データのエンジニアリング」へと、注力すべきポイントがシフトしたと捉えるべきです。
- 不要なデータを捨て、純度を高める(クレンジング)。
- XMLタグで意味の境界線を引く(構造化)。
- キャッシュを意識して配置する(アセンブリ)。
この3点を徹底すれば、モデルが本来持っている高度な推論能力や「適応型思考」を最大限に引き出す土台が整います。RAGでは到達できなかった包括的で深い回答を、よりシンプルなアーキテクチャで実現できるはずです。
コメント