RAG retrieve¶
Retrieval takes a query (or query vector) and asks the vector store for
the most relevant chunks. It sits between embed (which produced the
query vector) and postprocess / generate (which refines and uses the
results). All implementations satisfy:
type Retriever interface {
Retrieve(ctx, queryVector []float32, topK int) ([]*rag.SearchResult, error)
}
Beyond plain vector search, the package ships keyword (BM25), hybrid, fusion / ensemble, MMR, auto-merging / parent (small-to-big), routing, SQL (NL2SQL), summary-then-chunk, LLM rerank, memx-native dual-mode, and a family of query transformers (HyDE, multi-query, step-back, sub-question).
Implementations¶
simple — pass-through to the store¶
The baseline: invokes store.Search directly. Source:
pkg/rag/retrieve/retrieve.go (SimpleRetriever).
mmr — Maximal Marginal Relevance over the store¶
| Field | Type | Default | Description |
|---|---|---|---|
lambda |
float | 0.5 | 1.0 = pure relevance, 0.0 = pure diversity. |
Fetches topK*3 candidates, then iteratively selects the next result
maximising lambda*relevance - (1-lambda)*max_similarity_to_already_picked.
Use when result diversity matters more than raw top-1 quality. Source:
pkg/rag/retrieve/retrieve.go (MMRRetriever).
embedder-mmr — MMR on top of another retriever¶
Same algorithm as mmr but operates on the output of any
base retriever; uses embed.Embedder to embed chunks that lack a
pre-computed vector. Source: pkg/rag/retrieve/mmr.go.
hybrid — vector + keyword in one pass¶
| Field | Type | Default | Description |
|---|---|---|---|
alpha |
float | 0.7 | Weight on vector score; 1-alpha on keyword score. |
Annotates store.Search results with a keyword-overlap score and
blends. Source: pkg/rag/retrieve/retrieve.go (HybridRetriever).
dual-hybrid — two retrievers (vector + keyword) blended¶
rag:
retrieve:
type: dual-hybrid
vector: simple
keyword: bm25
vector_weight: 0.7
keyword_weight: 0.3
top_k: 10
Runs the two retrievers in parallel, normalises each side's scores to
[0,1], and combines by weight. Cleaner than hybrid when the keyword
side is BM25 over its own index. Source:
pkg/rag/retrieve/hybrid.go.
bm25 — pure in-memory BM25¶
| Field | Type | Default | Description |
|---|---|---|---|
k1 |
float | 1.2 | Term-saturation parameter. |
b |
float | 0.75 | Length normalisation. |
synonyms |
map | — | Term → synonym list (optional RAGFlow-style expansion). |
synonym_weight |
float | 0.5 | Weight applied to synonym matches. |
field_boosts |
map | — | Per-metadata-field score multiplier (e.g. {title: 10}). |
BM25Index.Add(results) indexes documents; NewBM25Retriever(index)
queries them. Supports synonym expansion and per-field boosts
(RAGFlow title^10 / important_kwd^30 style). Source:
pkg/rag/retrieve/bm25.go.
fusion — Reciprocal Rank Fusion across N retrievers¶
| Field | Type | Default | Description |
|---|---|---|---|
k |
int | 60 | RRF constant; larger = less weight on top ranks. |
For each retriever, each chunk gets 1/(K+rank+1); scores are summed
across retrievers. The canonical multi-retriever combiner. Source:
pkg/rag/retrieve/fusion.go (FusionRetriever).
ensemble — weighted RRF across N retrievers¶
Identical to fusion but with per-retriever weights. Runs retrievers
in parallel. Source: pkg/rag/retrieve/ensemble.go.
auto_merging — promote children to parent when enough match¶
rag:
retrieve:
type: auto_merging
child_store: kb_children
parent_store: kb_parents
merge_threshold: 0.5
top_k: 10
| Field | Type | Default | Description |
|---|---|---|---|
child_store |
ref | — | Vector store containing fine-grained child chunks. |
parent_store |
ref | — | Vector store containing coarser parent chunks. |
merge_threshold |
float | 0.5 | Fraction of a parent's children that must match before promoting. |
Pairs with chunk: hierarchical or chunk: parent-child. There's also
a single-store variant (RetrieverAutoMerging in auto_merging.go) that
infers parents from parent_id / parent_content in a single
retriever's output. Source: pkg/rag/retrieve/fusion.go
(AutoMergingRetriever), pkg/rag/retrieve/auto_merging.go
(RetrieverAutoMerging).
parent — search children, return parents¶
Small-to-big retrieval: matches small children, then looks up their
parents for fuller context. Unlike auto_merging, parents are always
returned (no threshold). Source: pkg/rag/retrieve/retrieve.go
(ParentRetriever).
rerank — bigram cross-encoder heuristic¶
Fetches fetch_k candidates, reranks using a bigram-overlap proxy for a
cross-encoder (no external model). Cheap and dependency-free. For real
cross-encoders, use the postprocess page's cross-encoder-rerank or
cohere-rerank. Source: pkg/rag/retrieve/retrieve.go
(RerankRetriever).
llm-rerank — LLM-judged relevance rerank¶
Sends batches of (query, document) to a ChatModel asking for a 0-10
relevance score, then sorts. Slow but very high quality. Falls back to
the original order on parse failure. Source:
pkg/rag/retrieve/llm_rerank.go.
multi-query — N hand-picked query vectors¶
For each precomputed query vector, fetches topK and unions the
deduplicated results. Use when the caller has the queries in hand.
Source: pkg/rag/retrieve/retrieve.go (MultiQueryRetriever).
multi-query-llm — LLM-generated query expansion¶
rag:
retrieve:
type: multi-query-llm
inner: simple
model: ${LLM_REF}
embedder: ${EMBEDDER_REF}
num_queries: 3
LLM generates num_queries alternative phrasings of the user's query;
each is embedded and retrieved; results are deduplicated. Source:
pkg/rag/retrieve/query_transform.go (MultiQueryLLMRetriever,
MultiQueryTransformer).
hyde — Hypothetical Document Embeddings¶
LLM hallucinates a hypothetical answer to the query, embeds it, and
retrieves against that vector. Often beats query-only retrieval for
detailed technical questions. Source:
pkg/rag/retrieve/query_transform.go (HyDETransformer,
HyDERetriever).
step-back — abstract-then-retrieve¶
LLM produces a more abstract / general version of the query (e.g.
"What is the population of Paris?" → "What is the population of
European capitals?"). Retrieves with the abstract query — useful when
the user query is too specific to find context. Source:
pkg/rag/retrieve/query_transform.go (StepBackTransformer,
StepBackRetriever).
sub-question — decompose then retrieve¶
rag:
retrieve:
type: sub-question
inner: simple
model: ${LLM_REF}
embedder: ${EMBEDDER_REF}
max_questions: 3
LLM splits the query into up to max_questions sub-questions; each
sub-question is retrieved separately and results are merged. Source:
pkg/rag/retrieve/query_transform.go (SubQuestionTransformer,
SubQuestionRetriever).
router (vector-keyed) — route by vector selector¶
RouterRetriever picks the named retriever using a
Selector func(vec) string. Source: pkg/rag/retrieve/fusion.go
(RouterRetriever).
query-router — route by text-based selector¶
rag:
retrieve:
type: query-router
retrievers:
tech: vector_tech
hr: bm25_hr
selector:
type: keywords
routes:
tech: [api, sdk, helix]
hr: [salary, leave, hiring]
default: tech
QueryRouterRetriever uses a RouteSelector interface; the built-in
KeywordRouteSelector matches case-insensitive keyword patterns. Source:
pkg/rag/retrieve/router.go.
sql — NL2SQL retrieval¶
rag:
retrieve:
type: sql
model: ${LLM_REF}
dsn: postgres://user:pass@host:5432/db
driver: postgres
table_schemas:
users: |
CREATE TABLE users (id INT, name TEXT, email TEXT)
LLM generates SQL from a natural-language query, given the table
schemas as context; rows are returned as SearchResult. Use for
structured-data sub-questions inside a RAG pipeline (e.g. analytics
queries mixed with document retrieval). Source:
pkg/rag/retrieve/sql.go.
summary — summary-then-chunk¶
rag:
retrieve:
type: summary
summary_store: kb_summaries
chunk_store: kb_chunks
model: ${LLM_REF}
embedder: ${EMBEDDER_REF}
DocumentSummaryRetriever first searches LLM-generated document
summaries to identify relevant documents, then retrieves chunks only
from those documents. Drastically reduces the search space on large
corpora. Source: pkg/rag/retrieve/summary.go.
memx — memx-native dual-mode retriever¶
rag:
retrieve:
type: memx
conn_string: http://localhost:9000
database: default
table_name: memx_documents
strategy: hybrid
metric: cosine
text_query: ...
| Field | Type | Default | Description |
|---|---|---|---|
strategy |
string | dense |
dense / simple (vector), text / bm25, hybrid / fusion (RRF). |
metric |
string | cosine |
cosine, l2, ip. |
text_query |
string | — | BM25/hybrid query text. |
Selects ES-API fast path for http(s):// and SQL mode for
postgres://. Lets one retriever pick between dense, BM25, or hybrid
without composing multiple Helix retrievers. Source:
pkg/rag/retrieve/memx.go.
Choosing between them¶
| If you need… | Pick |
|---|---|
| Default top-K vector search | simple |
| Diverse top-K | mmr (or embedder-mmr over another retriever) |
| Keyword + vector | dual-hybrid (with bm25 + simple) |
| Multi-retriever combine | fusion (equal weights) or ensemble (weighted) |
| Small chunks for ranking, big chunks for context | parent or auto_merging |
| Rerank with a real model | llm-rerank (in pipeline) or postprocess cohere-rerank |
| Query is too narrow | hyde (or step-back) |
| Query is multi-part | sub-question |
| Choose retriever per query | query-router with keywords selector |
| Structured-data sub-queries | sql |
| Massive corpus, coarse-then-fine | summary |
| memx backend, mixed dense+BM25 | memx (single retriever) |
See also¶
- embed — produces the
queryVectorconsumed here. - store — the backend(s) retrievers read from.
- postprocess — filter / rerank the results.
- generate — consumes
[]*rag.SearchResultto build the answer. - chunk —
hierarchical/parent-childare prerequisites forauto_merging/parent.