すべての記事

再クロール問題:RAGパイプラインの鮮度を保つ

RAGのナレッジベースは、リリースしたその週から陳腐化が始まります。エンジニアリング予算を圧迫することなく、数百のバーティカルなソースを再クロールする方法を解説します。

課題

バーティカルAIのスタートアップは、2ヶ月目あたりで一様に同じ壁にぶつかります。彼らはサポートコパイロット、法的リサーチアシスタント、またはコンプライアンスボットをリリースします。最初のデモで顧客を獲得します。その後、データが古くなり、回答が現実から乖離し始めます。

私たちは、多くのチームがAI側をきれいに構築する一方で、データ側を後回しにするのを見てきました。インジェストパイプラインは、誰かのノートPCで動く1つの Python スクリプトにすぎません。それが200個のソース URL を一度スクレイピングし、きれいな Markdown を vector store にダンプして、全員で祝杯をあげます。6週間後、回答の半分は削除されたページ、非推奨の API、あるいは3月にリリースされ5月に再び変更された製品機能を引用するようになります。

解決策はシンプルに思えます。すべてのソースを毎週リクロールすることです。しかし、現実はもっと厄介です。2026年までに、信頼できるサイトの約60%がAIクローラーをブロックしており(2023年末の23%から上昇)、その防御策はもはや単純な User-Agent チェックではありません。セッションの挙動、request のリズム、そしてハンドシェイクレベルのシグナルを監視しています。1月に動いていた単純なスクリプトは、3月には静かに空のページを返すようになります。

さらに悪いことに、一部のサイトは現在、embeddings を汚染するまでターピット(tarpit)コンテンツ(本物の文章のように見えるマルコフ連鎖生成のデタラメなテキスト)を提供します。その結果、エンジニアは製品をリリースする代わりに、週の半分をスクレイパーのパッチ当てに費やすことになります。検索(retrieval)の品質が低下し、顧客がそれに気づき、AIを構築するために雇ったチームはスクレイパーのメンテナンスショップと化してしまいます。

アプローチ

リクロール問題は、すべての request で発生する3つの具体的な決定に分解されます。

  1. レンダリングするか否か? ほとんどのドキュメントポータルはクリーンな HTML を返します。しかし、Next.js で構築されたものやクライアントサイドレンダリングを使用しているものなど、有用なコンテンツを返すために完全なブラウザレンダリングを必要とする割合が増えています。
  2. どの proxy を使うか? レジデンシャル、データセンター、モバイル、ジオピン(地域固定)、ISP特定。適切な選択はターゲットによって異なります。
  3. 実際に機能したか? 空のボディを持つ200や、CAPTCHA の HTML ページは、HTTP request としては成功ですが、クロールとしては失敗です。

FourA のようなプラットフォームは、これらすべてを最優先事項として処理します。

レンダリングの決定において、安価で高速なケースには Single を呼び出し、JSを多用するターゲットには Browser を呼び出します。呼び出しのボディは同じ形状であるため、インジェストコードは100個のサイト固有の癖に対応する代わりに、ソースごとのフラグで1回分岐するだけで済みます。

proxy 選択については、すべての Single、Browser、および Auto の呼び出しの一部として Proxy Finder が実行されます。プラットフォームは request ごとに稼働している出口を選択し、その不透明なIDを response の meta.proxy で返します。同じ出口を維持する必要がある場合は、後続の呼び出しでそのIDを再利用します。クローラーが独自の proxy ランキングアルゴリズムを持つ必要はありません。(プールサイズが差別化要因でなくなった理由については、Why Proxy Pool Size Stopped Mattering in 2026 で解説しています。)

そして「実際に機能したか」という問いに対しては、すべての request が validate ブロックをサポートしています。許容されるステータスコード、必須の header 値、出現する必要がある(またはあってはならない)ボディ文字列など、何をもって成功とするかを宣言します。FourA は7つの結果のいずれかを返し、課金対象となるのは success のみです。コンテンツルールに違反した200は application_fail と刻印され、データセットに入ることはありません。

以下は、JSレンダリングを必要とするドキュメントポータルのリクロール呼び出しの例です。ここでは Auto にオーケストレーションを任せています。これは適切な製品(Single、Proxy、または Browser)を選択し、ボット防御を処理し、次のリクロールで同じ出口を維持できるようにセッショントリプルを返します。

import requests

r = requests.post(
    "https://api.foura.ai/api/auto",
    headers={"Authorization": "Bearer pk_live_..."},
    json={
        "url": "https://docs.example.com/changelog",
        "validate": {
            "status": {"accept": [200]},
            "data":   {"accept": ["<article"], "fail": ["captcha", "Just a moment"]},
        },
    },
).json()

# r["data"]    — rendered body
# r["meta"]    — { "proxy": "<base36 id>", "cookies": [...], "userAgent": "..." }
# On the next recrawl, pass r["meta"]["proxy"] back as `ignoreProxies: [<id>]` to avoid
# the same exit, or via /api/single with `proxy: <id>` to stick to it.

ターゲットが Cloudflare のインターシャル(中間ページ)を返した場合、validate.data.fail ルールがそれをキャッチします。使用状況に記録される結果は application_fail になります。これに対する料金は発生せず、インジェストコードは「Just a moment...」ページを embeddings に投入する代わりに、別の proxy で再試行することを認識できます。

より広範なコーパスについては、既存のジョブキューに同じパターンを組み込みます。私たちが話を聞いたチームは、前回のクロールとの差分を毎晩実行し、実際に変更されたドキュメントのみを再 embed し、500個のソースコーパスを実時間で数時間のうちに更新しています。ジョブキューは皆様のもののままです。proxy の入れ替え、レンダリングの決定、成功の判定は私たちの役割です。

結果

インフラストラクチャがボトルネックでなくなったときの、鮮度維持ループの様子は以下の通りです(バーティカルAIチーム全体で見られるパターンに基づく説明用のシナリオ):

  • 毎週500個のソース URL をリクロール(ローンチ時の200個の URL の一発勝負の代わりに)
  • スクレイパーにかけるエンジニアリング時間:週2時間未満(1〜2日から短縮)
  • 検索(retrieval)の鮮度低下ウィンドウ:5〜7日(無制限の代わりに)
  • vector store 内のガベージ率がほぼゼロに。Cloudflare のインターシャルやターピットページは、embedding モデルに到達する前に validate レイヤーで拒否されるためです。
  • ソースごとのコストが予測可能に。失敗したクロールは請求に反映されないためです。

重要なのは、これらが魔法のようだということではありません。重要なのは、これらが「退屈」だということです。そして、本番環境のAIに必要なのは、まさにその退屈さです。(ホスト型 LLM 抽出で採算が合わなくなるケースの詳細については、When LLM Extraction Stops Paying for Itself をご覧ください。)

重要なポイント

バーティカルAIを構築するほとんどのチームは、優位性(moat)がプロンプト、モデルの選択、または検索アルゴリズムにあると考えています。実際はそうではありません。優位性とは鮮度維持ループ、つまりナレッジベースを毎週正確に保ち続ける、地味なインフラストラクチャのことです。

2026年にかけてバーティカルAIで勝利するチームは、最も巧妙なプロンプトを持つチームではありません。データが常に最新であるため、ユーザーがその事実にすら気づかないようなチームです。