Start with two representations of user intent
A retrieval request often contains both semantic intent and lexical constraints. For example, “why does checkout return ERR_42 after a timeout?” expresses a troubleshooting concept, but ERR_42 is also an exact token that should not be diluted or paraphrased away.
Model the request accordingly. Keep a natural-language text field for embedding and dense retrieval, while also retaining the original query text and any extracted terms for sparse retrieval. This preserves the information each retrieval method needs.
Talqora’s architecture separates these retrieval modes: regional S3 Vectors is used for dense search, while Quickwit BM25 is used for sparse search. An application-level query contract can keep the inputs to both paths clear and auditable.
- semantic_text: the text to embed for meaning-based retrieval
- lexical_text: the original text for BM25 matching
- required_terms: identifiers, quoted phrases, or extracted entities
- filters: structured constraints such as tenant, document type, or time range
Route by query shape, not by a permanent default
Not every query needs the same retrieval path. A broad question such as “how do I rotate credentials safely?” may benefit most from dense retrieval because relevant documents can use varied language. A query such as “E_CONN_RESET” or a specific API field name is usually dominated by lexical precision.
A simple router does not need to predict relevance perfectly. It only needs to recognize useful signals: the presence of code-like tokens, long quoted phrases, uncommon identifiers, or a high proportion of punctuation and digits. These signals can trigger a sparse-first path or require sparse results to participate in the final candidate set.
For ambiguous natural-language queries, run both paths. Treat the two result lists as candidate generators rather than competing truth sources.
- Use sparse-first handling for exact identifiers and error messages.
- Use dense-first handling for conceptual questions and paraphrases.
- Use both paths when the request mixes a task description with exact terms.
- Log the selected route and its detected signals for later evaluation.
Fuse candidates with transparent, testable rules
Dense similarity scores and BM25 scores are not naturally comparable. Instead of adding raw scores together, begin with rank-based fusion. Reciprocal rank fusion, for example, combines documents according to their position in each ranked list and avoids assuming that the score scales mean the same thing.
Keep the first version intentionally simple: retrieve a fixed candidate set from S3 Vectors and a fixed candidate set from Quickwit BM25, deduplicate by document identifier, then combine their ranks. If a required term is present, apply it as a filter or a clear ranking rule rather than hoping semantic similarity will preserve it.
Evaluation should include query sets that expose each method’s weaknesses: paraphrases for dense retrieval, rare terms for BM25, and mixed queries containing both. Review not only whether a relevant document appears, but whether it appears early enough for the downstream experience.
- Deduplicate candidates using a stable document or chunk identifier.
- Prefer rank-based fusion before introducing score normalization.
- Apply tenant and access-control filters consistently to both paths.
- Maintain separate test cases for semantic, lexical, and mixed-intent queries.
