Skip to main content
テキスト埋め込みでは、API の呼び出し方法を説明します。このページでは、正しく使う方法を説明します。 埋め込みの問題は、失敗した呼び出しとして現れることがほとんどありません。エンドポイントは 200 を返し、次元も正しいのに、 検索品質が静かに低下します。以下の推奨事項はすべて、2026-08-25 (UTC+8) に APIYI ゲートウェイで取得した測定値に基づいています — 一般的な助言ではありません。
方法: 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 のスコア範囲に合わせてしきい値を調整済みで、やり直したくない場合
多言語混在コーパスは bge-m3 の弱点です(Recall@1 65%)。クロスリンガル検索が弱いからではなく、むしろ逆です。同じ事実の中国語版と英語版をほぼ同じ評価(0.75〜0.87、OpenAI では 0.56〜0.69)にするため、中国語クエリでは英語版が中国語版より上位に来ることがよくあります。RAG が 1 つの回答しか返さない場合は、インデックスを言語ごとに分けるか、クエリ時に言語フィルターを追加してください。言語をまたいで資料を集める必要がある場合は、これは欠点ではなく機能です。

2. 長いドキュメントは常にチャンクに分割する

bge-m3 は 8192-token のコンテキストウィンドウを持っているため、長いマニュアルでも1回の呼び出しに収まります。しかし、それが良い考えだという意味ではありません。 測定結果: 20のセクションを1つの長いマニュアルに連結し、各セクションに対応する20の短いドキュメントを強力な撹乱要因として追加し、20の質問で照会すると — 同じ質問では、正しいセクションのスコアはドキュメント全体より平均で +0.10 高くなります。 長いドキュメントの単一ベクトルは、その中身すべての 平均 なので、正確に書かれた短い 一節ならどれでもそれを上回ります。
チャンク化の指針
  • 意味的な境界で 200〜500 tokens ごとに分割し、10%〜15% のオーバーラップを持たせる
  • 中国語は1 tokenあたり約2.1文字なので、200〜500 tokens はおおよそ 420〜1050中国語文字
  • 細かく切り刻みすぎないでください: すべての入力には2個の固定特別 token が含まれるため、500-token のチャンクでは 0.4% のオーバーヘッドですが、16-token のチャンクでは 12.5% が純粋な無駄になります
  • 各チャンクの先頭にセクション見出しを付けると、チャンクの識別しやすさが目に見えて向上します

3. 閾値はモデルごとに再調整する必要があります

OpenAI から bge-m3 への移行で最も失敗しやすいのが、ここです。この2つのスコア範囲はまったく異なります。 同じ手作業でラベル付けしたペアを、3つのモデルすべてで採点した結果です:
bge-m3下限は0.42で、OpenAI の下限は0.09です。 「0.3未満はすべて除外する」といったルールをそのまま流用すると、bge-m3ではまったくフィルタリングされません; 「0.8以上だけを関連ありと見なす」と流用すると、正しい結果のほとんどが捨てられてしまいます。
bge-m3で測定された最適な単一閾値: 参考までに、中国語シナリオでの最適閾値は、text-embedding-3-small0.453-large0.33 です。
実際には: 0.50 から始め、0.45–0.60 を確認が必要なグレーゾーンとして扱い、本番稼働する前に自分のコーパスから 50–100 件のラベル付きサンプルを使って再調整してください。

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秒ハングし始めます
クライアントは必ず再試行できるようにしてください。 低い同時実行数でも、約0.8%のリクエストが切断された接続に当たります (Connection aborted / Remote end closed connection)。 1回の再試行で解消します。再試行しないと、インデックスに抜けが生じます。バルクのインデックス作成では、クライアントのタイムアウトを数百秒ではなく60〜90秒に設定してください。ハングしたリクエストは、失敗したリクエストより対処が難しいです。

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 で保存しても精度への影響はありません:
ベクトルは正規化された状態で返ってきます(測定された L2 ノルムは 0.99992–1.00029)ので、内積がそのまま cosine similarity ですIPCOSINE のインデックスタイプは、ベクトルデータベース内で同一の結果を返し、IP は 1 回分の正規化処理を省けます。

7. ひそかに失敗するモード

7.1 LangChain のデフォルトは再現率を 80% から 15% に落とします

langchain_openai.OpenAIEmbeddings のデフォルトは check_embedding_ctx_length=True で、これが 最初にテキストを tiktoken の token id にエンコードし、整数配列を /v1/embeddings に送ります。これは、トークナイザーが tiktoken そのもの である OpenAI のモデルに対しては問題ありません。bge-m3 は XLM-R のトークナイザーを使っており、両者の id 空間には共通点がありません。呼び出しは引き続き 200 を返し、ベクトルも 1024 次元のまま、usage も正常に見えます。— ただし検索品質だけが静かに崩壊します。
計測結果: 修正方法:
同じリスクは、送信前にクライアント側で token 化するあらゆるラッパーにも当てはまります。サードパーティの埋め込みモデルを組み込むときは、SDK が生のテキストを送るのか、それとも token id を送るのかを確認してください。

7.2 空文字列が有効な入力として受け入れられる

input: ""bge-m3 に対して 200 を返し(ここで OpenAI は 400 を返します)、1024 次元のベクトルを生成し、2 tokens 課金されます。 空のチャンクを除外しないチャンク分割スクリプトは、検索時にランダムに現れる意味のないベクトルでインデックスを埋めてしまいます。インデックス作成前に空白のテキストを除外してください。

7.3 dimensions パラメータは拒否されます

400 を返します: 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-m3BGE-M3 はどちらも 503 「利用可能なチャネルがありません」を返します。

7.5 8192 は入力ごとの上限です

8192 tokens を超える単一入力は 400 を返し、決して黙って切り詰められることはありません。こちらのほうが安全な挙動です。見た目は正常なベクトルなのに、テキストの後半をひそかに失ったものを受け取ることはありません。 この上限は リクエストごとではなく、アイテムごと に適用されます。テストでは、1024 items / 102560 tokens を含む 1 回の呼び出しが正常に返りました。いずれか 1 つのアイテムが上限を超えるとリクエスト全体が失敗し、エラー内の token 数は合計ではなく、そのアイテムを指します。

8. そのままコピーできる最小実装

関連ドキュメント

テキスト埋め込み API

パラメータ、レスポンス形式、クイックスタート

リランク

bge-reranker-v2-m3、精度段階に適したツール

RAG チューニング

2段階検索、どれだけの候補をリコールするか

モデル料金

各埋め込みモデルの最新料金