MultiQueryEmbeddingRetriever
Retrieves documents using multiple queries in parallel with an embedding-based Retriever.
| Most common position in a pipeline | After a QueryExpander component, before a ChatPromptBuilder in RAG pipelines |
| Mandatory init variables | retriever: An embedding-based Retriever (such as InMemoryEmbeddingRetriever)query_embedder: A Text Embedder component |
| Mandatory run variables | queries: A list of query strings |
| Output variables | documents: A list of retrieved documents sorted by relevance score |
| API reference | Retrievers |
| GitHub link | https://github.com/deepset-ai/haystack/blob/main/haystack/components/retrievers/multi_query_embedding_retriever.py |
Overview
MultiQueryEmbeddingRetriever improves retrieval recall by searching for documents using multiple queries in parallel. Each query is converted to an embedding using a Text Embedder, and an embedding-based Retriever fetches relevant documents.
The component:
- Processes queries in parallel using a thread pool for better performance
- Automatically deduplicates results based on document content
- Sorts the final results by relevance score
This Retriever is particularly effective when combined with QueryExpander, which generates multiple query variations from a single user query. By searching with these variations, you can find documents that might not match the original query phrasing but are still relevant.
Use MultiQueryEmbeddingRetriever when your documents use different words than your users' queries, or when you want to find more diverse results in RAG pipelines. Running multiple queries takes more time, but you can speed it up by increasing max_workers to run queries in parallel.
MultiQueryTextRetriever insteadIf you need exact keyword matching and don't want to use embeddings, use MultiQueryTextRetriever instead. It works with text-based Retrievers like InMemoryBM25Retriever and is better when synonyms can be generated through query expansion.
Passing Additional Retriever Parameters
You can pass additional parameters to the underlying Retriever using retriever_kwargs:
result = multi_query_retriever.run(
queries=["renewable energy", "sustainable power"],
retriever_kwargs={"top_k": 5}
)
Usage
This pipeline takes a single query "sustainable power generation" and expands it into multiple variations using an LLM (for example: "renewable energy sources", "green electricity", "clean power"). The Retriever then converts each variation to an embedding and searches for similar documents. This way, documents about "solar energy" or "wind energy" can be found even though they don't contain the words "sustainable power generation".
Before running the pipeline, documents must be embedded using a Document Embedder and stored in the Document Store.
- Python
- YAML
from haystack import Document, Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder
from haystack.components.retrievers import InMemoryEmbeddingRetriever, MultiQueryEmbeddingRetriever
from haystack.components.query import QueryExpander
documents = [
Document(content="Renewable energy is energy that is collected from renewable resources."),
Document(content="Solar energy is a type of green energy that is harnessed from the sun."),
Document(content="Wind energy is another type of green energy that is generated by wind turbines."),
Document(content="Geothermal energy is heat that comes from the sub-surface of the earth."),
]
doc_store = InMemoryDocumentStore()
doc_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
doc_embedder.warm_up()
documents_with_embeddings = doc_embedder.run(documents)["documents"]
doc_store.write_documents(documents_with_embeddings)
pipeline = Pipeline()
pipeline.add_component("query_expander", QueryExpander(n_expansions=3))
pipeline.add_component(
"retriever",
MultiQueryEmbeddingRetriever(
retriever=InMemoryEmbeddingRetriever(document_store=doc_store, top_k=2),
query_embedder=SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"),
)
)
pipeline.connect("query_expander.queries", "retriever.queries")
result = pipeline.run({"query_expander": {"query": "sustainable power generation"}})
for doc in result["retriever"]["documents"]:
print(f"Score: {doc.score:.3f} | {doc.content}")
components:
query_expander:
type: haystack.components.query.query_expander.QueryExpander
init_parameters:
n_expansions: 3
retriever:
type: haystack.components.retrievers.multi_query_embedding_retriever.MultiQueryEmbeddingRetriever
init_parameters:
retriever:
type: haystack.components.retrievers.in_memory.embedding_retriever.InMemoryEmbeddingRetriever
init_parameters:
document_store:
type: haystack.document_stores.in_memory.document_store.InMemoryDocumentStore
init_parameters: {}
top_k: 2
query_embedder:
type: haystack.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder
init_parameters:
model: sentence-transformers/all-MiniLM-L6-v2
connections:
- sender: query_expander.queries
receiver: retriever.queries