AAI Agentic Handbook
Embeddings & Encoders

Symmetric vs asymmetric embeddings

Mid levelReviewed Oct 2026In 2 interview questions

Symmetric search matches like with like (ticket to ticket). Asymmetric search matches a short query to a long answer-bearing passage.

In plain English

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.

Analogy

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.

Common pitfall

Assuming a high similarity score means a good answer. Symmetric matches often score higher than the correct asymmetric match because they share surface wording.

How it actually works

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.

What I'd ship on day one

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.

Worked example

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.

In the interview

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.

Similar questionFAQ headingProtocol paraDosage tableBilling noteQuery (no role)
Query2 nearest neighboursOther items
Without query/passage roles, the query lands beside look-alike questions, not the passage that answers it.
Symmetric
  • Ticket vs ticket
  • Dedup, clustering
  • Same role both sides
Asymmetric
  • Short query vs passage
  • Question to answer
  • query:/passage: roles
Most RAG retrieval is the asymmetric case.

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

WhenDo 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 rolesAdd 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

Time to scale up when…
  • 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
What to monitor
  • Share of top-1 hits whose doc_type is 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

What users saw

Internal wiki search answered 'how do I rotate the staging DB password' with three Slack-exported questions asking the same thing.

How it was caught

Thumbs-down rate on the answer widget doubled; manual review of 50 sessions showed question-to-question matches.

Root cause

A migration to a new SDK dropped input_type='search_query', so queries were embedded as documents.

Fix

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.

Sources

  1. MS MARCO: A Human Generated MAchine Reading COmprehension Dataset — Nguyen et al., 2016paper
  2. Text Embeddings by Weakly-Supervised Contrastive Pre-training (E5) — Wang et al., 2022paper
  3. Embed API reference (input_type) — Cohere, 2025docs

Check yourself

Three questions. Every option is explained once you answer.

1ConceptAn asymmetric model encodes both the query and documents with the same role. Why do the top hits tend to be other users' questions instead of answers?
2ScenarioClaims ops wants to flag near-duplicate claims submitted by different brokers, using the same Cohere embed-v4 model that powers your RAG index. How should you encode them?
3CalculationAn SDK migration dropped input_type on queries, and you decide to re-embed 8M chunks of ~350 tokens each with Cohere embed-v4 at $0.12/M tokens. Roughly what does the re-embed cost?