大規模な本番環境でのRAG:1日1万件以上の求人情報を処理して得た教訓

求人サイト向けのRAGパイプラインを構築しました。ステージング環境では動作していましたが、実際の負荷がかかると苦戦しました。毎日数千件の求人情報を処理するには、単に優れたベクトルストアを用意するだけでは不十分です。システムがどこで破綻するのかを理解する必要があります。

ここでは、チャンキング、埋め込み(embeddings)、コスト、そしてオブザーバビリティ(可観測性)に関する教訓を紹介します。

1. チャンキング戦略を勘に頼らない

ほとんどのチュートリアルでは、チャンキングを単なる設定項目として扱っています。しかし、本番環境においては、その戦略が精度とコストを左右します。

求人情報に対して3つの手法をテストしました:

  • 固定サイズ・チャンク(Fixed-size chunks): これは失敗でした。「要件」や「福利厚生」といったセクションがランダムな箇所で分割されてしまい、検索結果にノイズが混じる原因となりました。
  • セマンティック・チャンキング(Semantic chunking): これ better でしたが、一貫性に欠けました。チャンクが長すぎたり、逆に短すぎたりすることがありました。
  • オーバーラップを用いた再帰的文字分割(Recursive character splitting with overlap): これが最も効果的でした。改行と文章単位で分割し、サイズは400トークン、オーバーラップは50トークンに設定しました。これにより、2つのチャンクにまたがる文章が適切に接続されるようになります。

プロのヒント: チャンキングの前にデータを正規化してください。GreenhouseやLeverといった異なるソースからは、異なるフォーマットでデータが返ってきます。チャンカーが一貫した構造を認識できるように、まずはテキストをクリーニングしましょう。

2. 埋め込み(Embeddings):コスト vs 精度

Ollama経由のLlama 3.1と、OpenAIのtext-embedding-3-smallを比較テストしました。 ローカルモデルは無料ですが、「equity compensation(株式報酬)」のようなドメイン固有の用語に弱く、ノイズの多い結果を生成しました。 OpenAIはコストがかかりますが、正確なマッチングを実現しました。検索精度が低いと、その後のLLM呼び出しのコストが増大するため、私はOpenAIを選択しました。

時間を節約するために、リクエストをバッチ処理しています。1回の呼び出しで最大100個のチャンクを送信することで、レイテンシを抑え、パイプラインの速度を維持しています。

3. ベクトルストアのトレードオフ

プロトタイプ作成には、セットアップが容易なPineconeを使用しました。しかし、規模が拡大するにつれてコストが膨大になりました。

そこで、PostgreSQL内のpgvectorに切り替えました。

  • セットアップの手間は増えました。
  • しかし、大幅なコスト削減につながりました。
  • また、トランザクションの整合性も確保できました。

埋め込みデータが求人データと同じデータベース内に存在するため、単一の「信頼できる情報源(source of truth)」を持つことができます。2つの異なるシステムを同期させる必要はありません。

4. LLMコストの制御

すべての求人情報をGPT-4oでスコアリングするのは高額です。コストを下げるために、以下の3つの戦術を用いました:

  • OpenAI Batch API: スコアリングのジョブを夜間にまとめて処理します。これにより大幅な割引が受けられます。
  • キャッシング: 繰り返し現れる候補者プロファイルの結果をキャッシュします。
  • モデルの階層化(Model tiering): 「Sales Representative(営業担当)」のような一般的な職種にはGPT-4o-miniを使用します。精度が極めて重要なニッチな職種にのみ、GPT-4oを使用します。

5. まずオブザーバビリティを構築する

私のパイプラインは、かつてエラーを出さずに静かに失敗したことがありました。不正な形式のデータによって空のチャンクが生成され、システムがエラーを出さずにそれをスキップしてしまったのです。

これを解決するために、相関ID(correlation ID)を用いた構造化ロギングを追加しました。これにより、データの取り込みからスコアリングまで、特定の求人情報を追跡できるようになりました。その結果、どのデータソースが失敗の原因となっているのかを特定できるようになりました。

最大の教訓: ほとんどの問題はAIではなく、乱雑なデータから発生します。まずはデータの配管(data plumbing)を整えましょう。

Source: https://dev.to/abdul___rehman/production-rag-at-scale-lessons-from-processing-10000-listings-daily-22gm

Optional learning community: https://t.me/GyaanSetuAi