1. アーキテクチャを正しくする: 2段階リトリーバル
再ランキングは単独のリトリーバル手法ではありません。これはパイプラインの第2段階です。1
候補抽出
ベクター検索 または BM25 を使って、コーパス全体から候補セットを取り出します。この段階は
高速 である必要があり、オーバーフェッチ すべきです。目的は「答えがこの中のどこかにある」ことであり、
「答えが最初にある」ことではありません。
2
再ランキング
候補セットとクエリを
bge-reranker-v2-m3 に送ってスコアリングし、再ソートします。
この段階は 高精度 である必要があります。目的は、正しい答えを上位に押し上げることです。3
切り詰めて LLM に渡す
再ランキング後の上位 3–5 件を prompt に入れます。これがより正確であるほど、モデルの幻覚は減り、必要なコンテキストも少なくなります。
なぜ recall と rerank をすべて省略できないのか: クロスエンコーダーは、何かを計算する前にクエリを必要とするため、事前にオフラインで計算しておくことはできません。数百万件のドキュメントを1件ずつスコアリングするのは、コストとレイテンシの両面で現実的ではありません。候補抽出で数百万件を数百件に絞り込み、再ランキングでその数百件を正しく並べ替えます。
完全な動作例
これは、最小構成ながら完全な2段階リトリーバーです —text-embedding-3-small による候補抽出、bge-reranker-v2-m3 による再ランキングで、どちらも同じ APIYI token を使います:
2. 何件の候補を検索すべきですか?
測定レイテンシ(短い文書、各段で 5 回実行したときの P50):
重要なのは、約 2 秒の固定オーバーヘッドです。文書が 1 件でも 2 秒かかります。1 件から 100 件に増やしても追加は 1.8 秒だけで、検索品質の向上はそれをはるかに上回る価値があります。
実際にレイテンシを左右するのは合計 tokens 数であって、文書数ではありません。 同じ 50 件の候補でも:
件数は同じでも、レイテンシは 4.7 倍です。これが、次のセクションのチャンク分割が recall を遅くしない理由でもあります — チャンク分割は文書数を増やしますが、合計 tokens は増やしません。
本当に大量の文書を順位付けする必要がある場合(たとえばオフラインのバッチ処理)は、同時実行数を 4 に抑えたまま、複数の 100 文書以下のリクエストに分割してください。分割しても合計 tokens は減らない点に注意してください。TPM 20,000 は依然として全体の上限なので、バッチジョブには分単位のスロットリングが必要です。そのクォータは拡張中です。大規模なバッチワークロードの場合は、まず APIYI サポートで現在使える余裕を確認してください。
3. 長い文書をチャンク化する
これは、最も効果の高い前処理ステップです。理由は2つの測定値で説明できます。 まず、無関係な内容は関連度を薄めます。 同じ一致文に、さまざまな量のダミー文を後ろへ追加した場合です。
次に、長さはノイズスコアを押し上げます。 同じ無関係な文書は、短いときは 0.029 でしたが、450 文字のダミー文を追加すると 0.121 になり、4倍高くなりました。
合わせると、答えが末尾にある長い文書は、完全に話題外の長い文書に負けます。
4. 閾値の設定(0.5 をそのまま選ばないでください)
relevance_score はシグモイドで 0–1 の範囲に写像されるため、信頼度のように見えます。しかし、そうではありません。
すべての品質テストケースで測定した分布は次のとおりです:
固定の 0.5 閾値では、正しいクロスリンガルの結果はすべて除外され、非中国語では 2 位のヒットの大半も落ちます。一方で、キーワードの重なりが大きいディストラクタは通してしまいます(「Apple Inc. FY2024 revenue」の場合、りんご栽培の価格に関する文書が 0.945 を獲得して 3 位になりました)。
最後の行に注目してください。最も高スコアの無関係な文書(0.945)が、最も低スコアの関連する文書(0.289)を上回っています。2つの分布は重なっており、まさにそれが 「安全な」絶対閾値が存在しない 理由です。
5. 否定には安全策が必要です
これはこのモデルの明らかな弱点です。「冬に訪れるのに良い観光地はどこですか?」では、明示的に該当しないと述べている 2つの文書が2位と3位になり、本当に関連性の高い結果が4位と5位に押し下げられました。nDCG@3 は 0.47 でした。 モデルは「冬 + 観光地 + 旅行」というトピックに一致しましたが、否定をまったく処理しませんでした。 対策: 再ランキングの後に、軽量な LLM の検証パスを追加します。安価な小型モデルで十分です:6. 多言語およびクロスリンガルの利用
中国語、英語、日本語、韓国語、ロシア語、フランス語、アラビア語、さらに ZH↔EN のクロスリンガル検索も、テストではすべて正しい順序で並びます。1つのモデルで多言語ナレッジベースをカバーできるため、言語ごとのデプロイは不要です。 ただし、スコアの大きさには注意してください。
クロスリンガルの正解スコアは 1〜2 桁ほど低くなりますが、それでも順序は維持されます。
7. 同時実行数、キャッシュ、冪等性
まずクォータを見積もり、それから同時実行数を考える
上流側(Huawei Cloud MaaS)は、このモデルに対して TPM 20,000 / RPM 120 を許可しています。これは最も過小評価されがちな制約です。同じプラットフォーム上の BGE-M3 embedding モデルは 1,200,000 TPM で、60倍 です。 テストでは、各ケースの前に 70 秒間何も送らずにクォータのウィンドウをリセットし、2つの独立したメカニズムを切り分けました。
発見1: 同時進行中スロットはおおむね 4〜5 個です。 R1/R2 は TPM の 3〜4% しか消費しないのに広く失敗し、同時実行数を 10 から 20 に増やしても成功数は 4〜5 に上限がかかります。一方で、R5 の 20 件のシリアルリクエストはすべて通ります。スロット上限を超えたリクエストはキューに入らず、そのまま拒否されます。
発見2: TPM 20,000 は同時実行数とは独立して適用されます。 R4 は完全シリアルであり、8 件目のリクエストが累積 16,093 token で 429 になり、ウィンドウがずれる前に 9 回連続で失敗します。
1分あたりの検索回数
計測した≈26.9 tokens/document を使うと:
候補数は品質だけでなく容量の判断でもあります: 候補数を2倍にしても品質向上は限定的ですが、スループットは半分になります。
また、1回のリクエストに候補数を載せすぎられない理由もこれで説明できます。1000 候補は 26,867 token で、1分の予算全体の 134% を1回で使うため、429 は確実です。2000 では 269% です。
クォータ拡張は進行中です。 上記の TPM 20,000 は上流側の初期割り当てであり、
APIYI はすでに引き上げ申請を行っています。ワークロードが表で許容される範囲を超える場合は、
現在の数に合わせて設計を縮小するのではなく、APIYI サポートに連絡して上流クォータの見直しを依頼してください。
キャッシュ
同一のリクエストを10回繰り返すと、bit 単位で同一です(ドリフトはゼロ)。約 3.7e-4 のドリフトが出るのは、候補の順序をシャッフルした場合だけです(bf16 バッチ処理のジッターによる)で、順序自体は影響を受けません。 そのため、結果は安全にキャッシュできます:normalised query + ordered hash of document contentsをキーにするrelevance_score自体を冪等性キーや重複排除キーとして使わない — 候補の順序を変えると末尾の数字が変わります- 繰り返しのクエリ(FAQ、人気検索)はたいていキャッシュに向いており、レイテンシと上流側への負荷の両方を減らせます
8. 既存フレームワークとの統合
パラメータ名は Cohere Rerank v1(query / documents / top_n / return_documents)と一致しますが、documents は文字列配列しか受け付けません — [{"text": "..."}] は 400 を返します — そしてレスポンスには id / meta フィールドがありません。
9. リリース前チェックリスト
正確性
正確性
-
results[].indexを使って逆参照し、テキスト一致では行わない - 長いドキュメントは 200〜500 文字でチャンク化し、最良チャンクスコアで集約する
- 単一のクエリとドキュメントの組み合わせが 8192 tokens を超えない
- 否定や除外を含むクエリには LLM の検証パスを用意する
信頼性
信頼性
- 候補セットは 100 件上限にする
- 同時実行数は 4 に制限(計測では、上流は約 4〜5 件の in-flight リクエストを許容し、それ以上はキューイングされず即座に拒否される)
- ピークスループットが TPM 20,000 に対して十分か確認し(候補 100 件で約 15 検索/分)、問題ないことを確認する
- 429 に対するバックオフ付き再試行を実装する(上流の混雑は一時的)
- タイムアウトは 60 秒以上に設定する(短いドキュメント 100 件なら P95 で約 4.3 秒だが、長いドキュメントや大きなセットでは数十秒に達する)
- リクエストパスが
/v1/rerankであることを確認する — 間違ったパスでは 404 ではなく 200 + HTML が返る - モデル名は正しく小文字で記載する — টাইポは 503 を返し、障害と見間違えやすい
品質
品質
- フィルタリングは、推測した固定値ではなく Top-N か相対しきい値を使う
- 多言語およびクロスリンガルのスコアの大きさを確認し、低いスコアが除外されないようにする
- 小さなラベル付きクエリセットで A/B テストを行い(rerank を有効/無効で比較)、メトリクスが実際に動いたことを確認する
コストとキャッシュ
コストとキャッシュ
-
usage.input_tokens/output_tokensは常に 0 であることを理解し、prompt_tokens/total_tokensを読む -
top_nもreturn_documentsも使用量を減らさないことを理解する — すべての候補がスコア付けされる - コスト計上はコンソールの請求書に基づいて行う(
prompt_tokensとtotal_tokensは候補 100 件で約 45% 異なり、今回のラウンドではどちらが課金されるか確認できなかった) - 高頻度のクエリに対する結果キャッシュを用意する