Method: 20 Chinese documents about LLM gateway integration plus 20 matching English documents,
20 Chinese and 20 English queries with hand-labelled answers, all three models run against the same
corpus in the same time window. The corpus is small, so differences under 5 percentage points are not
conclusive — reproduce on your own data before treating any of it as final.
1. Pick the right model first
Choose bge-m3 when
- Your corpus is mostly Chinese (or Japanese / Russian): retrieval quality matches 3-small, the list price is half, and the same text takes only 42% of the tokens — about 1/5 the actual spend
- You want smaller storage: 1024 dims is 33% below 1536 and 66% below 3072
- You need coverage of long-tail languages (100+ supported)
- You want to run the same open-source model locally so offline and online vectors match
Choose OpenAI when
- Your corpus is mostly English or code: quality is a tier higher. bge-m3 does burn 15%–50% more tokens on this kind of content, but half the unit price still makes it cheaper overall — so decide on quality here, not on price
- Your knowledge base mixes languages and you only want one answer back
- You need
dimensionsto shrink storage - You already have thresholds calibrated against OpenAI score ranges and do not want to redo them
2. Always chunk long documents
bge-m3 has an 8192-token window, so a long manual fits in a single call. That does not make it a good idea.
Measured: 20 sections concatenated into one long manual, with 20 short documents (each corresponding to one
section) added as strong distractors, queried by 20 questions —
For the same question, the correct section scores on average +0.10 above the whole document:
A long document’s single vector is the average of everything in it, so any precisely-worded short
passage beats it.
3. Thresholds must be recalibrated per model
This is where a migration from OpenAI tobge-m3 most often goes wrong. The two score ranges are completely different.
The same hand-labelled pairs, scored by all three models:
Best single thresholds measured for
bge-m3:
For comparison, the best Chinese-scenario threshold is 0.45 for
text-embedding-3-small and 0.33 for 3-large.
4. Similarity cannot tell you whether something is correct
This holds for every embedding model — it is not a flaw in any one of them, but you need to know it upfront:
All three fail. Cosine similarity measures whether two texts are about the same thing, not whether they agree.
Negation, prices, version numbers and entity names cannot be separated at the retrieval stage. The correct
fallback is:
1
Vector recall, Top 50–100
Use
bge-m3 to narrow the field fast. The threshold only filters out the obviously unrelated.2
Rerank down to Top 3–5
Send the candidates to
bge-reranker-v2-m3. It is a cross-encoder
that runs the query and document through the model together, which is exactly the right tool for these
fine distinctions — and it comes from the same model family as bge-m3.3
Let the LLM judge at generation time
Pass the Top 3–5 along with the original question, and state explicitly in the prompt that the model should
say it found nothing when the retrieved content does not match the question.
5. Batch size and concurrency
Batching: the knee is at 64–128
Past 128 the per-item cost barely improves (58ms → 53ms) while a single request grows 7×.
Request duration directly drives client timeout risk and how much work one failure throws away.
Concurrency: 8 online, 32–48 for bulk indexing
- Use concurrency 8 for live retrieval: 200 requests with zero failures
- Bulk indexing can go to 32–48: highest throughput, but 429s start appearing, so exponential backoff is required
- Do not exceed 64: at 96 the failure rate is 11.8% and requests start hanging for ~60 seconds
6. How cost actually works
Cost is the product of two things: unit price and how many tokens a given piece of text becomes. Both differ here.bge-m3 is $0.01 / 1M tokens against $0.02 for text-embedding-3-small — half the unit price
before anything else. On top of that comes tokenizer efficiency: bge-m3 uses XLM-R SentencePiece and gets
about 2.1 Chinese characters per token, while OpenAI’s cl100k manages about 0.9:
Chinese corpora cost roughly one fifth of
text-embedding-3-small.
English and code consume more tokens on bge-m3, but half the unit price still lands it below OpenAI on
total spend — so for those two corpora the decision rests on retrieval quality (English Recall@1 70% vs
80%), not on price.
Storage differs too. Vectors are already L2-normalized and the returned values are fp16 precision, so
storing bge-m3 vectors as float16 costs nothing in accuracy:
7. Failure modes that stay silent
7.1 LangChain’s default drops recall from 80% to 15%
Measured cost:
The fix:
7.2 An empty string is accepted as valid input
input: "" returns 200 on bge-m3 (OpenAI returns 400 here), producing a 1024-dimensional vector and
billing 2 tokens.
A chunking script that does not filter empty chunks will seed your index with meaningless vectors that
surface at random during retrieval. Filter blank text before indexing.
7.3 The dimensions parameter is rejected
Model "bge-m3" does not support matryoshka representation, changing output dimensions will lead to poor results.
bge-m3 was not trained with Matryoshka representation, so truncating the vector measurably hurts quality.
Use float16 to shrink storage instead of cutting dimensions yourself.
7.4 The model name is case-sensitive with no aliases
Onlybge-m3 works. BAAI/bge-m3 and BGE-M3 both return 503 “no available channels”.
7.5 8192 is a per-input limit
A single input above 8192 tokens returns 400 and is never silently truncated — which is the safer behaviour: you will not receive a normal-looking vector that quietly lost the second half of your text. The limit applies per item, not per request: a single call carrying 1024 items / 102560 tokens returned normally in testing. If any one item exceeds the limit the whole request fails, and the token count in the error refers to that item, not the total.8. A minimal implementation you can copy
Related documentation
Text Embedding API
Parameters, response format, quick start
Rerank
bge-reranker-v2-m3, the right tool for the precision stageRAG Tuning
Two-stage retrieval, how many candidates to recall
Model Pricing
Live pricing for every embedding model