← すべての記事

再クロールの課題: RAGパイプラインを新鮮に保つ

RAGナレッジベースはリリースしたその週に古くなります。エンジニアリング予算を圧迫せずに数百の垂直ソースを再クロールする方法を解説します。

課題

バーティカルAIのスタートアップは、立ち上げから約2か月で誰もが同じ壁に直面します。サポート用コパイロット、法務調査アシスタント、コンプライアンスBotなどをリリースし、最初のデモで顧客を獲得します。しかし、データが古くなるにつれて、回答と現実の乖離が始まります。

AI側の構築は綺麗に行うものの、データ側を後回しにするチームを多く見てきました。取り込みパイプラインは誰かのラップトップで動く1つのPythonスクリプトに過ぎません。200のソースURLを一度スクレイピングし、クリーンなMarkdownをベクトルストアに投入して成功を祝います。その6週間後、回答の半数は削除されたページ、非推奨のAPI、あるいは3月にリリースされ5月に再変更されたプロダクト機能を参照するようになります。

解決策は単純に見えます。すべてのソースを毎週再クロールすることです。しかし現実はより過酷です。2026年までに、信頼性の高いサイトの約60%がAIクローラーをブロックしており(2023年末の23%から増加)、その保護機能はもはや単純なUser-Agentチェックではありません。セッションの振る舞い、リクエストの間隔、ハンドシェイクレベルのシグナルを監視しています。1月に動作していた単純なスクリプトは、3月にはサイレントに空のページを返すようになります。

さらに悪いことに、一部のサイトは埋め込みを汚染するまでターピットコンテンツ(自然な文章に見えるマルコフ連鎖生成の無意味なテキスト)を返します。結果としてエンジニアはプロダクトの開発ではなく、スクレイパーの修正に週の半分を費やすことになります。検索品質が低下し、顧客がそれに気づき、AIを構築するために雇ったチームがスクレイパーのメンテナンス部隊と化してしまいます。

アプローチ

再クロールの課題は、リクエストごとに実行すべき3つの具体的な判断に分けられます。

  1. レンダリングの要否 多くのドキュメントポータルはクリーンなHTMLを提供します。しかし増加傾向にある対象(Next.jsベースのサイトやクライアントサイドレンダリングを使用するサイト)は、有用なコンテンツを取得するために完全なブラウザレンダリングを必要とします。
  2. 使用するプロキシ レジデンシャル、データセンター、モバイル、地域指定、特定ISP。適切な選択肢はターゲットごとに変化します。
  3. 実際に成功したか 本文が空の200応答や認証ページは、HTTPリクエストとしては成功でもクロールとしては失敗です。

FourAのようなプラットフォームは、これらの要素を主要な関心事として処理します。

レンダリングの判断においては、低コストで高速なケースにはSingleを、JSを多用するターゲットにはBrowserを呼び出します。呼び出しのボディ構造は同一であるため、取り込みコードはサイト固有の多数の例外処理を抱えることなく、ソースごとのフラグで一度分岐するだけで済みます。

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

また、「実際に機能したか」という疑問に対しては、すべての request が validate ブロックをサポートしています。許容するステータスコード、必須の header 値、含める(または含めてはならない)body 文字列など、成功とみなす条件を定義します。FourA は7つの結果のうち1つを返し、請求対象となるのは success のみです。コンテンツルールを満たさない 200 は application_fail として記録され、データセットに入ることはありません。

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

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"] or r["body"]   — rendered content (Auto runs the right sub-product per host;
#                            Single populates "data", Browser populates "body")
# r["session"]              — { "proxy": "<base36 id>", "cookies": [...], "userAgent": "..." }
# On the next recrawl, pass r["session"]["proxy"] back as `ignoreProxies: [<id>]` to avoid
# the same exit, or via /api/single with `proxy: <id>` to stick to it.

ターゲットがCloudflareのインターstitial画面を返した場合、validate.data.failルールがそれを検知します。使用量に対して記録される結果はapplication_failとなります。これに対して課金は発生せず、取り込みコード側では「Just a moment...」ページを埋め込みモデルに渡すことなく、別のproxyで再試行すべきだと判断できます。

コーパス全体に対しても、既存のジョブキュー内で同じパターンを適用できます。実際にヒアリングしたチームでは、前回のクロールとの差分を毎晩取得し、変更のあったドキュメントのみを再埋め込みすることで、500ソースのコーパスを実時間わずか数時間で更新しています。ジョブキューの管理はユーザー側で行い、proxyの切り替え、レンダリング判定、成功の判定はFourA側が処理します。

Results

インフラがボトルネックでなくなった場合の鮮度維持ループの姿は以下のようになります(バーティカルAIチームでよく見られるパターンに基づくモデルケース):

  • 毎週500件のソースURLを再クロール(ローンチ時に200件を1度だけクロールする運用からの改善)
  • スクレイパーにかけるエンジニアリング工数: 週2時間未満(週1〜2日から削減)
  • 検索データの鮮度遅延ウィンドウ: 5〜7日(無制限の放置状態からの改善)
  • ベクトルストア内の不要データ混入率がほぼゼロに(Cloudflareのインターstitial画面やtarpitページは、埋め込みモデルに到達する前にvalidateレイヤーで破棄されるため)
  • ソースごとのコストが予測可能(失敗したクロールは課金対象外となるため)

重要なのは、これらが魔法のような仕組みであることではなく、極めて堅実で退屈な技術であるという点です。そして本番環境のAIに必要なのは、まさにその「退屈さ」です。(ホスト型LLMによる抽出の採算が合わなくなる境界についての詳細は、When LLM Extraction Stops Paying for Itselfを参照してください。)

Key Takeaway

バーティカルAIを開発する多くのチームは、競争優位性(moat)がプロンプト、モデルの選定、または検索アルゴリズムにあると考えがちです。しかし実際はそうではありません。競争優位性とは鮮度維持ループ、すなわちナレッジベースの正確性を毎週保ち続ける、目立たないインフラそのものなのです。

2026年にかけてバーティカルAIで勝者となるのは、最も巧妙なプロンプトを作成するチームではありません。データが常に最新であるため、ユーザーがその鮮度を意識することすら不要なシステムを構築したチームです。