Symmetric vs asymmetric embeddings
Symmetric search matches like with like (ticket to ticket). Asymmetric search matches a short query to a long answer-bearing passage.
In symmetric search both sides look alike: you compare one sentence with another, for example to find duplicate bug reports. In asymmetric search the sides look different: a short question such as 'is prior authorization needed for an MRI' has to find a long policy paragraph that answers it.
Most RAG retrieval is asymmetric, and many Embedding models are trained for one style or ask you to mark which side is the question and which is the document.
Symmetric is pairing socks from a laundry pile: two items of the same kind. Asymmetric is finding the key for a lock: two different shapes that fit together.
Assuming a high similarity score means a good answer. Symmetric matches often score higher than the correct asymmetric match because they share surface wording.
Symmetric models are trained on interchangeable pairs (paraphrases, duplicate questions, NLI entailments), so sim(a,b) = sim(b,a) is the objective. Asymmetric models are trained on (query, relevant passage) pairs such as MS MARCO, where the query is 5–10 words and underspecified and the passage is 50–300 words and answer-bearing.
Modern bi-encoders serve both by marking roles: E5 uses query: vs passage: prefixes, Nomic uses search_query: vs search_document: , Cohere embed-v4 takes input_type='search_query' vs 'search_document', Voyage takes input_type='query' vs 'document'. Encode both sides the same way on an asymmetric task and the top hits become passages that look like the question (FAQ headers, other users' questions) rather than ones that answer it. HyDE (hypothetical document embeddings) converts the asymmetric problem into a symmetric one by generating a hypothetical answer and searching with that. For duplicate detection, clustering or 'more like this', use the symmetric mode on both sides.
For RAG, use an asymmetric model and always pass the role: Cohere input_type, Voyage input_type, E5/Nomic prefixes, or the query instruction for bge and Qwen3-Embedding. Use the same model in symmetric mode (document role on both sides) for dedup and clustering jobs.
Clinical intake triage. Query: 'chest tightness after starting new BP meds'.
Symmetric encoding (no roles): top hit is another patient's intake note, 'tightness in chest since new blood pressure pills?', cosine 0.91. Similar wording, no guidance.
Asymmetric encoding (query: / passage:): top hit is the protocol paragraph 'ACE-inhibitor-associated cough and chest discomfort: assess for angioedema; escalate if…', cosine 0.74. Lower score, right document.
If someone says recall dropped after a model swap, check the role contract first: "RAG is asymmetric, so I confirm the model was trained on query-passage pairs and that we pass input_type or prefixes the same way it was trained. For dedup I flip to the symmetric mode." The expected follow-up is how to prove it: run the golden set with and without roles; a 3–10 point recall gap is a normal result.
Symmetric
- Ticket vs ticket
- Dedup, clustering
- Same role both sides
Asymmetric
- Short query vs passage
- Question to answer
- query:/passage: roles
Numbers worth knowing
- Typical MS MARCO query vs passage length
- ~6 words vs ~55 wordsMS MARCO passage ranking
- Recall loss from dropping roles on an asymmetric model
- 3–10 points recall@10common on E5/Nomic-style models; measure on your golden set
How to decide
| When | Do this |
|---|---|
| Questions retrieve answers (RAG, support, search) | Asymmetric model with query/document roles. |
| Finding duplicates or near-duplicates (tickets, claims, code clones) | Symmetric mode: same role on both sides. |
| Queries are 1–3 words and recall is poor even with roles | Add HyDE (hypothetical document embeddings) or Query rewriting before changing the model. |
Cost maths
No direct cost: roles are free tokens (2–4 tokens per input). The cost of getting it wrong is a re-embed: 8M chunks × 350 tokens = 2.8B tokens × $0.12/M (Cohere embed-v4 list price, illustrative, Oct 2026) = $336, plus a backfill window.
Operating it
- Golden-set recall gap between question-style and keyword-style queries above 10 points: add query rewriting
- Top-1 hits are other questions in >20% of a sampled week: roles are missing somewhere
- Share of top-1 hits whose
doc_typeis a question: alert above 15% - Golden-set recall@10 split by query style (question vs keyword): alert if the gap exceeds 10 points
When it goes wrong
Internal wiki search answered 'how do I rotate the staging DB password' with three Slack-exported questions asking the same thing.
Thumbs-down rate on the answer widget doubled; manual review of 50 sessions showed question-to-question matches.
A migration to a new SDK dropped input_type='search_query', so queries were embedded as documents.
Restored the role, added a unit test that asserts the role on both the query and ingest code paths, and filtered Slack-question chunks out of the answer index.
Related terms
Sources
- MS MARCO: A Human Generated MAchine Reading COmprehension Dataset — Nguyen et al., 2016paper
- Text Embeddings by Weakly-Supervised Contrastive Pre-training (E5) — Wang et al., 2022paper
- Embed API reference (input_type) — Cohere, 2025docs
Check yourself
Three questions. Every option is explained once you answer.