方法: LLM ゲートウェイ統合に関する中国語文書 20 件と、それに対応する英語文書 20 件、
人手でラベル付けした回答を持つ中国語クエリ 20 件と英語クエリ 20 件、3 つのモデルすべてを同じコーパスに対して同じ時間帯に実行しました。コーパスは小さいため、5 ポイント未満の差は決定的ではありません — いずれも最終的な結論として扱う前に、ご自身のデータで再現してください。
1. まず適切なモデルを選びます
bge-m3 を選ぶのは次の場合です
- コーパスの大半が中国語(または日本語 / ロシア語)である場合: 検索品質は 3-small と同等で、定価は半額、同じテキストに必要な token は 42% だけです。実際の支出は約 1/5 になります
- より小さいストレージを求めている場合: 1024 次元は 1536 より 33%、3072 より 66% 小さいです
- 長尾言語(100 以上対応)をカバーする必要がある場合
- 同じオープンソースモデルをローカルで実行して、オフラインとオンラインのベクトルを一致させたい場合
OpenAI を選ぶのは次の場合です
- コーパスの大半が英語またはコードである場合: 品質は 1 段上です。bge-m3 はこの種の内容で token を 15%〜50% 多く消費しますが、単価が半額なので総額ではなお安くなります。ここでは価格ではなく品質で判断してください
- ナレッジベースが複数言語を混在しており、1 つの回答だけ返したい場合
dimensionsストレージを縮小したい場合- すでに OpenAI のスコア範囲に合わせてしきい値を調整済みで、やり直したくない場合
2. 長いドキュメントは常にチャンクに分割する
bge-m3 は 8192-token のコンテキストウィンドウを持っているため、長いマニュアルでも1回の呼び出しに収まります。しかし、それが良い考えだという意味ではありません。
測定結果: 20のセクションを1つの長いマニュアルに連結し、各セクションに対応する20の短いドキュメントを強力な撹乱要因として追加し、20の質問で照会すると —
同じ質問では、正しいセクションのスコアはドキュメント全体より平均で +0.10 高くなります。
長いドキュメントの単一ベクトルは、その中身すべての 平均 なので、正確に書かれた短い
一節ならどれでもそれを上回ります。
3. 閾値はモデルごとに再調整する必要があります
OpenAI からbge-m3 への移行で最も失敗しやすいのが、ここです。この2つのスコア範囲はまったく異なります。
同じ手作業でラベル付けしたペアを、3つのモデルすべてで採点した結果です:
bge-m3で測定された最適な単一閾値:
参考までに、中国語シナリオでの最適閾値は、
text-embedding-3-smallで 0.45、3-largeで 0.33 です。
4. 類似性だけでは、何かが 正しい かどうかは分かりません
これは すべての エンベディングモデルに当てはまります — どれか1つの欠陥ではありませんが、事前に知っておく必要があります:
3つとも失敗します。コサイン類似度は、2つのテキストが同じ内容についているかどうかを測るものであり、互いに一致しているかどうかを測るものではありません。
否定、価格、バージョン番号、エンティティ名は、検索段階では切り分けられません。正しい
フォールバックは次のとおりです:
1
ベクトル検索、上位 50–100
bge-m3 を使って素早く候補を絞り込みます。しきい値は、明らかに無関係なものを除外するだけです。2
再ランク付けして上位 3–5 に絞る
候補を
bge-reranker-v2-m3 に送ります。これは、クエリとドキュメントをモデルに一緒に通すクロスエンコーダーで、こうした細かな違いを見分けるのにまさに最適なツールです — しかも、bge-m3 と同じモデルファミリーです。3
生成時に LLM に判定させる
上位 3–5 件を元の質問と一緒に渡し、検索した内容が質問と一致しない場合は、何も見つからなかったと prompt に明示的に書いてください。
5. バッチサイズと同時実行数
バッチ処理: 変曲点は64–128です
128を超えると、1件あたりのコストはほとんど改善せず(58ms → 53ms)、一方で1回のリクエストは7倍に増えます。
リクエストの所要時間は、クライアントのタイムアウトリスクと、1つの失敗で失われる作業量に直接影響します。
同時実行数: オンラインでは8、バルクのインデックス作成では32–48
- ライブ取得では同時実行数8を使ってください: 200リクエストで失敗はゼロです
- バルクのインデックス作成は32–48まで上げられます: スループットは最大になりますが、429が出始めるため、指数バックオフが必要です
- 64を超えないでください: 96では失敗率が11.8%になり、リクエストが約60秒ハングし始めます
6. コストが実際にどう決まるか
コストは、2つの要素の積です。単価と、あるテキストが何 token になるかです。 この2つがここでは異なります。bge-m3 は $0.01 / 1M tokens で、text-embedding-3-small の $0.02 と比べて、まず単価が半分です。
さらに、トークナイザ効率もあります。bge-m3 は XLM-R SentencePiece を使用し、1 tokenあたり約2.1中国語文字 になりますが、OpenAI の cl100k は約 0.9 です:
中国語コーパスのコストは、
text-embedding-3-small のおよそ5分の1です。
英語とコードでは bge-m3 でより多くの token を消費しますが、単価が半分であるため、総支出でも OpenAI を下回ります。したがって、この2つのコーパスでは判断基準は 検索品質(English Recall@1 70% vs 80%)であり、価格ではありません。
ストレージも異なります。ベクトルはすでに L2 正規化されており、返される値は fp16 精度なので、bge-m3 ベクトルを float16 で保存しても精度への影響はありません:
7. ひそかに失敗するモード
7.1 LangChain のデフォルトは再現率を 80% から 15% に落とします
計測結果:
修正方法:
7.2 空文字列が有効な入力として受け入れられる
input: "" は bge-m3 に対して 200 を返し(ここで OpenAI は 400 を返します)、1024 次元のベクトルを生成し、2 tokens 課金されます。
空のチャンクを除外しないチャンク分割スクリプトは、検索時にランダムに現れる意味のないベクトルでインデックスを埋めてしまいます。インデックス作成前に空白のテキストを除外してください。
7.3 dimensions パラメータは拒否されます
Model "bge-m3" does not support matryoshka representation, changing output dimensions will lead to poor results.
bge-m3 は Matryoshka representation で学習されていないため、ベクトルを切り詰めると品質が測定可能なほど低下します。次元を自分で削るのではなく、ストレージを小さくするには float16 を使ってください。
7.4 モデル名は大文字小文字を区別し、別名はありません
bge-m3 だけが機能します。BAAI/bge-m3 と BGE-M3 はどちらも 503 「利用可能なチャネルがありません」を返します。
7.5 8192 は入力ごとの上限です
8192 tokens を超える単一入力は 400 を返し、決して黙って切り詰められることはありません。こちらのほうが安全な挙動です。見た目は正常なベクトルなのに、テキストの後半をひそかに失ったものを受け取ることはありません。 この上限は リクエストごとではなく、アイテムごと に適用されます。テストでは、1024 items / 102560 tokens を含む 1 回の呼び出しが正常に返りました。いずれか 1 つのアイテムが上限を超えるとリクエスト全体が失敗し、エラー内の token 数は合計ではなく、そのアイテムを指します。8. そのままコピーできる最小実装
関連ドキュメント
テキスト埋め込み API
パラメータ、レスポンス形式、クイックスタート
リランク
bge-reranker-v2-m3、精度段階に適したツールRAG チューニング
2段階検索、どれだけの候補をリコールするか
モデル料金
各埋め込みモデルの最新料金