多くのRAGチュートリアルはノートブックで終わります。いくつかの整ったPDFを読み込み、テキストを1000文字ごとに分割し、断片をベクトルデータベースに詰め込み、それをアーキテクチャと呼びます。金曜日の午後、そのデモは完璧に動作するでしょう。しかし、本番環境では、同じパイプラインが静かに足かせへと変わります。
検索システムにおける真のボトルネックは、モデルやプロンプトであることは稀です。それはインジェスチョン(データ取り込み)です。RAGパイプラインは、与えられたものしか検索できません。もし入力がノイズだらけであったり、古かったり、不完全であったりすれば、モデルは自信満々にデタラメを回答します。ユーザーが「ボットがハルシネーションを起こした」と不満を漏らすとき、その原因は多くの場合、誰も注意深く監視していないデータパイプラインのずっと上流にあります。
ホワイトボードの罠
アーキテクチャ図では、インジェスチョンは「Documents → Vector DB」というラベルの付いた一本の矢印のように描かれます。しかし、現実はもっと複雑です。ソースシステムは予告なく変更されます。HTMLレイアウトはリデザインされます。URLは汎用的なランディングページにリダイレクトされます。JavaScriptフレームワークは、最初のHTTPレスポンスの後にコンテンツを入れ替えます。インジェスチョンを一度限りのセットアップ作業として扱うことは、最初の間違いです。それは、あらゆるETLパイプラインと同様の厳密さが求められる、継続的なデータエンジニアリングの問題なのです。
なぜRAGの失敗は、たいてい入力の失敗なのか
次のような場面を想像してください。ユーザーが社内アシスタントに現在の返金ポリシーについて尋ねます。モデルはベクトルストアから上位のチャンクを取得し、「30日以内」と回答します。しかし、実際のポリシーは前四半期に60日間に変更されていました。LLMが間違った答えを捏造したわけではありません。悪い入力を信じてしまったのです。検索レイヤーが古いページを返し、そのエンベディングが意味的に十分に近く見えたため、モデルはそれを正解(ground truth)として扱ってしまいました。
このパターンは絶えず繰り返されます。コーパスがナビゲーションのフッター、重複したプレスリリース、そしてテーブルを真っ二つに分割してしまったチャンクで溢れているのに、チームはtemperature(温度)やtop-kの調整に何時間も費やしています。生成プロセスを最適化する前に、システムが「何を知識として保持することを許可されているか」を監査してください。
インジェスチョンを台無しにする7つの罠
1. 初回の実行結果は嘘である
最初のクロールで緑色のチェックマークがついたとしても、それはほとんど意味をなしません。本番データは生き物です。ドキュメントページはリファクタリングされ、ブログのパーマリンクは切れ、サイトマップからセクションが静かに消えることもあります。パイプラインがエラーを出さずに完了したことだけを確認しているなら、あなたは盲目状態で運用していることになります。出力の検証が必要です。期待されるドキュメントが存在するか、その構造が依然としてパース可能か、そしてソース側が結果のページネーション方法を変更したためにテキストの総量が激減していないかを確認してください。
2. クローリングはインジェスチョンではない
HTMLを取得するのは簡単な部分です。生のクロールは、クッキーのバナー、「関連記事」のサイドバー、広告ブロック、フッターの著作権表示など、あらゆるものをキャプチャしてしまいます。もしその生のHTMLを不用意にチャンク化すれば、あらゆるテキスト断片にナビゲーションメニューの断片が混入することになります。ユーザーがAPIのレート制限について尋ねたとき、検索エンジンがサイドバーのリンクが40%を占めるチャンクを提示してしまうかもしれません。クリーンな抽出が重要です。メインコンテンツ領域を特定し、ボイラープレートを取り除き、すべてのページで繰り返される要素を削除する必要があります。さもなければ、あなたはナレッジベースを構築しているのではなく、ウェブサイトのUI要素(chrome)を検索するためのエンジンを作っていることになります。
3. チャンキングが意味を破壊する
固定サイズのチャンキングは、ほぼすべてのクイックスタートガイドのデフォルトですが、これは危険です。文字数だけでドキュメントを分割すると、テーブルを真っ二つに切り裂き、番号付き手順のステップ4と5を分離し、箇条書きの項目をその見出しから孤立させてしまいます。価格表の後半部分だけを含むチャンクは、意味的に役に立ちません。構造を意識したチャンキング(Structure-aware chunking)は、元のフォーマットを尊重します。見出しの階層をパースしてください。可能な限りテーブルはそのまま保持してください。同じH2またはH3の下にある段落の境界で分割してください。箇条書きが十分に短い場合は、単一のチャンク内に保持してください。目標は、均一なサイズのブロックを作ることではありません。一貫性のある「意味の単位」を作ることです。
4. 新鮮さの問題
A static snapshot of an internal wiki is simple mode. Continuously ingesting from the live web is hard. You need to know when a page was last gathered, whether it has changed since then, and how long the information remains valid. Stale data does not always mean a visibly old date. Sometimes a page updates its text but keeps the same URL, so your system never notices without content hashing. Build clear refresh rules based on source volatility. A financial data feed might need hourly checks. A company about page might need quarterly checks. Record timestamps and set time-to-live boundaries, especially if your domain involves regulated or safety-critical guidance where old facts can cause real harm.
5. Duplicate Pollution
Websites are full of repetition. The same product description appears on the category page, the product page, and a promotional landing page. The same press release lives under /news/, /press/, and /blog/. Vector search does not deduplicate automatically. If ten nearly identical chunks sit in your database, they can crowd out diverse, relevant results in your top-k retrieval. You need canonical tracking or content deduplication before embedding. If two chunks say the same thing, keep the authoritative source and drop the copies. Your retriever has limited slots. Do not let them go to waste.
6. Missing Metadata
A vector database without metadata is just a dense text search engine with no memory of context. Smart retrieval depends on filtering and ranking signals that raw embeddings cannot provide. Store the source URL, the capture date, the document category, and the version number. If you ingest API documentation, versioning is essential. Without it, a query might blend v1 and v2 specs into the same answer. If you ingest HR policies, tagging by region or department lets you filter results before they ever reach the model. Metadata turns a text dump into a curated knowledge system.
7. JavaScript Gaps
Modern sites do not ship their content in the first HTML payload. They send a skeleton and hydrate it with JavaScript calls. A basic HTTP request might see nothing but a loading spinner and a layout shell. If your pipeline cannot execute JavaScript, you will ingest blank pages or partial fragments and never realize anything is wrong. Using a headless browser solves the rendering problem but introduces new ones: heavier memory use, slower throughput, and bot detection walls. Choose your trade-offs deliberately, but do not pretend a simple curl equivalent is enough for every source.
A Practical Ingestion Checklist
If you are building or reviewing a RAG feed, start here:
- Validate source coverage and pagination. A sitemap might list only the first ten articles in a category. Crawl deep and verify that paginated or dynamically loaded content is actually captured.
- Remove boilerplate before chunking. Strip navigation, ads, footers, and repeated legal disclaimers. If a phrase appears on every page, it is noise.
- Use structure-aware chunking. Respect headings, bullet lists, and tables. Split on semantic boundaries, not character counts.
- Attach rich metadata. Include URL, capture date, content category, and version. Make these fields filterable in your retrieval queries.
- Set refresh frequencies based on data volatility. High-change sources need frequent re-crawls. Static archives do not.
- Monitor the corpus, not just the job status. A pipeline can exit with code zero while producing garbage. Audit samples of stored chunks regularly for drift and quality.
- Define rules for versioning and deletions. When a source page is removed, delete its chunks. When it updates, overwrite or version them. Orphaned data is a silent killer.
The Hard Truth About Embeddings
No embedding model, no matter how advanced, can repair a missing document. It cannot guess that a page was updated last week if your feed still holds last year's copy. It cannot infer the context of a table row that got separated from its header by a bad chunk boundary. Embeddings compress meaning, but they do not create meaning where the ingestion layer failed to preserve it.
Retrieval quality starts at the ingestion layer. That layer decides whether your RAG system is a useful tool or just a confident liar with a vector database behind it.
The Real Takeaway
データ取り込みの健全性を、パイプラインのダッシュボードだけで判断するのはやめましょう。ジョブが正常に終了し、ログが綺麗であっても、コーパスがクリーンである保証にはなりません。データベースを開き、ユーザーが実際に取得することになるチャンクを直接確認してください。もしテキストが著作権表示や、崩れたテーブル、古いポリシーページばかりであれば、問題はLLMにあるのではありません。まずはデータフィードを修正してください。それ以外はすべて、ゴミの上にチューニングを重ねているに過ぎないのです。
