Retrieval
Retrieval finds the chunks that are relevant to a query. You query the Mistral Search Index directly, through one of two methods:
Start with search. When you need to filter results or control how they're ranked, switch to retrieve.
Both methods rank chunks across the whole index. To read a document in order from a hit, for example the chunks around it, use document navigation.
The examples on this page share this setup:
from mistralai.search.toolkit.embedding import MistralEmbedder
from mistralai.search.toolkit.mistral_search_index import MistralSearchIndexService
index = await MistralSearchIndexService().get_search_index("my_collection")
embedder = MistralEmbedder(model_name="mistral-embed")Search
search takes a VectorSearchQuery and returns a list of SearchResult objects, best match first. Embed the query with the same model that the index uses:
from mistralai.search.toolkit.search import VectorSearchQuery
question = "How do I rotate an API key?"
embedding = await embedder.embed_query(question)
results = await index.search(
VectorSearchQuery(query=question, embedding=embedding, top_k=10)
)
for result in results:
print(f"{result.score:.3f} {result.chunk.source_id} {result.chunk.content[:80]}")The fields that you set on the query determine the search strategy:
- Vector search: set only
embedding. The index returns the chunks whose embeddings are closest to the query's. - Hybrid search: set both
queryandembedding. The index also matches the query's keywords oncontentand fuses both rankings with reciprocal rank fusion. Exact terms, such as names or error codes, then count alongside meaning.
VectorSearchQuery also takes the following fields:
| Field | Type | Default | Purpose |
|---|---|---|---|
top_k | int | 10 | Number of results, at most 100 |
exclude_ids | set[str] | empty | Chunk IDs to leave out |
exclude_source_ids | set[str] | empty | Source documents to leave out |
approximate_options | ApproximateQueryOptions | default | max_candidates for the approximate nearest-neighbor search |
Every hit includes its custom fields alongside the chunk. To filter on those fields, match keywords on a custom field, or weight the fusion, use retrieve.
Retrieve
retrieve takes a retriever: a description of the query that the index runs as is. You compose it yourself, so you can express retrieval logic that search doesn't cover. Import the retrievers from mistralai.search.toolkit.mistral_search_index.retriever:
| Retriever | Purpose |
|---|---|
NearestNeighbourRetriever | Vector search. With a Mistral embedding model, pass query and the index embeds it. |
KeywordRetriever | Keyword search on content, or on any indexed text custom field through field. |
RRFRetriever | Hybrid search: fuses the rankings of its child retrievers with reciprocal rank fusion. |
For all the options of each retriever, see Retrievers.
Filter the results
To keep only the chunks whose fields match, such as a category, a publication year, or a list of source documents, add a filter to any retriever. The index applies the filter as part of the search, so top_k only counts chunks that pass the filter. On an RRFRetriever, the filter applies to every child.
The following query matches the question against the chunk text and against a custom title field, with twice the weight on title. It fuses these rankings with vector search and keeps only financial and legal documents published since 2022:
from mistralai.search.toolkit.mistral_search_index.retriever import (
And,
In,
KeywordRetriever,
NearestNeighbourRetriever,
Range,
RRFRetriever,
)
question = "termination clauses"
results = await index.retrieve(
RRFRetriever(
top_k=10,
filter=And(matches=[
In(field="category", values=["financial", "legal"]),
Range(field="published_year", gte=2022),
]),
retrievers=[
KeywordRetriever(query=question, top_k=20),
KeywordRetriever(query=question, field="title", top_k=20),
NearestNeighbourRetriever(query=question, top_k=20),
],
weights=[1.0, 2.0, 1.0],
)
)For the available conditions, how to combine them, and the fields that you can filter on, see Filters.
Results
Both methods return SearchResult objects. Each chunk carries the chunk's content, its document-scope and chunk-scope custom fields, and its identity (id, source_id, locator). Results don't include embeddings.
A higher score means a better match. Its scale depends on the retriever: 1 - distance for cosine vector search, a keyword relevance score for KeywordRetriever, and the fused score for RRFRetriever and hybrid search. For details, see Results.