Your RAG pipeline clears a standard load test with flying colors. p95 latency looks healthy. Error rates sit near zero. Yet users report replies that dodge the question, cite documents that do not exist, or dredge up irrelevant paragraphs from a white paper uploaded six months ago. The dashboard says everything is fine. The experience says it is broken.
そのRAGパイプラインは、標準的な負荷テストを余裕でクリアしています。p95レイテンシは健全で、エラー率もほぼゼロです。しかし、ユーザーからは「質問をはぐらかされる」「存在しないドキュメントを引用される」「6ヶ月前にアップロードされたホワイトペーパーから無関係な段落を掘り起こしてくる」といった報告が上がっています。ダッシュボード上ではすべて正常ですが、実際の体験としては壊れています。
That disconnect exists because conventional performance testing was built for request-response systems, not for systems that think. When you fire a thousand parallel requests at a REST endpoint, you learn whether your servers stay upright. You learn nothing about whether your retrieval layer fetches the right chunks, whether your prompt template preserves context, or whether the model invents sources when the vector store comes up empty. Standard load testing measures speed. RAG applications demand that you measure understanding.
この乖離が生じる理由は、従来のパフォーマンス・テストが「考えるシステム」ではなく、「リクエスト・レスポンス型システム」向けに構築されているからです。RESTエンドポイントに対して1,000件の並列リクエストを投げたとき、わかるのはサーバーが耐えられるかどうかだけです。検索レイヤーが正しいチャンクを取得できているか、プロンプトテンプレートがコンテキストを維持できているか、あるいはベクターストアが空のときにモデルがソースを捏造していないか、といったことは何もわかりません。標準的な負荷テストは「速度」を測定しますが、RAGアプリケーションに求められるのは「理解度」の測定です。
Beyond Status Code 200
ステータスコード200の先へ
A typical API load test checks three things: availability, latency, and throughput. It asks whether the server answered, how long it took, and how many concurrent users it survived. For a RAG application, those numbers are prerequisites, not conclusions. A fast wrong answer is still a wrong answer, and wrong answers at scale cost more than slow ones.
一般的なAPI負荷テストでは、可用性、レイテンシ、スループットの3点を確認します。サーバーが応答したか、どれくらい時間がかかったか、どれだけの同時ユーザー数に耐えられたかを問うものです。RAGアプリケーションにおいて、これらの数値は前提条件であって、結論ではありません。速い誤回答は、依然として誤回答であり、大規模な環境での誤回答は、遅い回答よりも大きなコストを招きます。
RAG adds two distinct phases to every request. First, the system turns a user question into an embedding, queries a vector store, and pulls back a set of context chunks. Second, it stuffs those chunks into a prompt, sends everything to a language model, and streams back a completion. Traditional tests often collapse these into a single "response time" metric. They treat the retrieval engine and the generator as one black box.
RAGは、すべてのリクエストに2つの明確なフェーズを追加します。第一に、システムがユーザーの質問をエンベディングに変換し、ベクターストアにクエリを投げ、一連のコンテキスト・チャンクを取得します。第二に、それらのチャンクをプロンプトに詰め込み、すべてを言語モデルに送信して、回答をストリーミングで返します。従来のテストでは、これらを単一の「レスポンスタイム」という指標にまとめてしまいがちです。検索エンジンと生成器を一つのブラックボックスとして扱ってしまうのです。
You need to pry that box open. If your vector database slows down under load, retrieval latency climbs. The LLM might still respond quickly, but it is responding based on garbage context fetched in a hurry. Alternatively, the vector search stays snappy while the LLM queue backs up, increasing time-to-first-token until users stare at a blinking cursor. A single end-to-end timer hides both failures.
そのボックスをこじ開ける必要があります。負荷によってベクタデータベースが低速化すれば、検索レイテンシが上昇します。LLMは依然として素早く応答するかもしれませんが、それは急いで取得されたゴミのようなコンテキストに基づいた応答です。あるいは、ベクタ検索は軽快なままなのにLLMのキューが滞留し、ユーザーが点滅するカーソルを眺めることになるまでTime-to-first-tokenが増大することもあります。単一のエンドツーエンドのタイマーでは、これら両方の失敗が隠されてしまいます。
Test the Retrieval, Not Just the Database
データベースだけでなく、検索(Retrieval)をテストする
Most teams run a quick vector search benchmark and call the retrieval layer tested. That benchmark usually measures how fast the database returns nearest neighbors for a hand-picked query. It rarely measures whether those neighbors actually contain the answer.
ほとんどのチームは、手早くベクタ検索のベンチマークを実行し、検索レイヤーのテストが完了したと見なします。しかし、そのベンチマークは通常、あらかじめ選ばれたクエリに対してデータベースがいかに速く最近傍を返すかを測定しているに過ぎません。それらの最近傍に、実際に答えが含まれているかどうかを測定することは滅多にありません。
Retrieval quality shifts with load in subtle ways. Under concurrent pressure, approximate nearest neighbor indexes can behave differently than they do in isolation. Chunking strategies that looked perfect in a notebook start bleeding context across boundaries when ten thousand documents compete for the same embedding space. A query that returns the ideal paragraph in a quiet environment might surface a misleading marketing slide when the index is rebuilding or when filtering metadata gets stripped under request pressure.
検索の品質は、負荷によって微妙に変化します。並列処理の圧力下では、近似最近傍(ANN)インデックスは単独で動作しているときとは異なる挙動を示すことがあります。ノートブック上では完璧に見えたチャンク分割戦略も、1万個のドキュメントが同じエンベディング空間を奪い合うようになると、境界を越えてコンテキストが漏れ出し始めます。静かな環境では理想的な段落を返すクエリも、インデックスの再構築中であったり、リクエストの圧力によってメタデータのフィルタリングが剥がれ落ちたりすると、誤解を招くようなマーケティング資料を提示してしまうかもしれません。
To test this properly, you need a ground-truth dataset. Curate questions where you already know which source documents should appear. Run those questions at varying concurrency levels and check whether the expected chunks land in the top-k results. Track hit rate, not just query duration. If your top-five chunks miss the critical source entirely, your retrieval pipeline failed before the LLM even woke up.
これを適切にテストするには、グラウンドトゥルース(正解)データセットが必要です。どのソースドキュメントが表示されるべきかをあらかじめ知っている質問をキュレーションしてください。それらの質問をさまざまな同時実行レベルで実行し、期待されるチャンクがtop-kの結果に含まれているかを確認します。単なるクエリの実行時間ではなく、ヒット率を追跡してください。もし上位5つのチャンクに重要なソースが全く含まれていなければ、LLMが起動する前に検索パイプラインは失敗しています。
You should also stress-test the edges. Submit queries that have no answer in the corpus. Submit ambiguous questions that could map to multiple domains. Submit long questions that exceed your embedding model's token limit and get silently truncated. Watch what the retrieval layer hands back. In each case, the failure mode matters more than the milliseconds elapsed.
また、エッジケースのストレス・テストも行うべきです。コーパスの中に答えが存在しないクエリを投げてください。複数のドメインにマッピングされ得る曖昧な質問を投げてください。エンベディングモデルのトークン制限を超えて、静かに切り捨てられてしまうような長い質問を投げてください。検索レイヤーが何を返してくるかを注視してください。いずれの場合も、経過したミリ秒数よりも、どのような失敗モードが発生したかの方が重要です。
When the Model Chokes Quietly
モデルが静かに窒息するとき
Once the chunks reach the LLM, standard load testing continues to lie
チャンクがLLMに到達すると、標準的な負荷テストは嘘をつき続けます
