Retrievers
Un retriever décrit une requête : les éléments à rechercher, leur classement et le nombre de fragments à renvoyer. Transmettez-le à la méthode retrieve d'un Mistral Search Index, qui l'exécute tel quel.
Importez les retrievers depuis mistralai.search.toolkit.mistral_search_index.retriever :
| Retriever | Utilisation |
|---|---|
NearestNeighbourRetriever | Recherche vectorielle : fragments dont le sens est le plus proche de la requête, même s'ils utilisent des mots différents. |
KeywordRetriever | Recherche par mots-clés : fragments qui partagent des termes avec la requête, comme des noms, des identifiants ou des codes d'erreur. |
RRFRetriever | En environnement hybride : fusionne les classements de plusieurs retrievers en un seul. |
Utilisez des retrievers lorsque search ne permet pas d'exprimer la requête dont vous avez besoin, par exemple dans les cas suivants :
- Une recherche uniquement par mots-clés, ou une recherche uniquement vectorielle avec un pool de candidats ajusté
- Pondérer la recherche par mots-clés par rapport à la recherche vectorielle, ou modifier le
rank_constantde la fusion - Un
top_kdifférent ou un filter différent pour la recherche par mots-clés et la recherche vectorielle - Exiger tous les mots-clés (
operator="and"), ou effectuer la correspondance sur un champ autre quecontent - Combiner plusieurs recherches par mots-clés et vectorielles en un seul classement
Importez les retrievers uniquement depuis ce module, et non depuis les modules centraux de la boîte à outils, car ce sont les types que l'index accepte.
Chaque retriever prend les options suivantes :
| Option | Type | Valeur par défaut | Rôle |
|---|---|---|---|
top_k | int | 20 | Nombre de fragments à renvoyer. Plafonné à 100 sur le retriever que vous passez à retrieve. |
filter | Filter | None | None | Conserve uniquement les fragments dont les champs correspondent aux critères. Voir Filtres. |
NearestNeighbourRetriever
NearestNeighbourRetriever classe les fragments selon la distance entre leur représentation vectorielle et celle de la requête, en utilisant la métrique de distance du modèle de représentations vectorielles de l'index.
from mistralai.search.toolkit.mistral_search_index.retriever import NearestNeighbourRetriever
results = await index.retrieve(
NearestNeighbourRetriever(query="How do I rotate an API key?", top_k=10)
)| Option | Type | Valeur par défaut | Rôle |
|---|---|---|---|
query | str | None` | None | Texte de la requête. Avec un modèle de représentations vectorielles Mistral, l'index le convertit en vecteur. |
query_embedding | list[float] | None` | None | Vecteur de la requête. Obligatoire avec un modèle de représentations vectorielles personnalisé, que l'index ne peut pas appeler. |
field | str | None` | None | Champ de représentation vectorielle utilisé pour le classement. None utilise la représentation vectorielle du fragment, content_embedding. |
max_candidates | int | None | None | Taille du pool de candidats pour la recherche approximative des plus proches voisins, de 1 à 1000. Doit être au moins égale à top_k. Augmentez-la pour améliorer le rappel au détriment de la latence. |
Définissez query, query_embedding, ou les deux. Avec un modèle de représentations vectorielles personnalisé, vectorisez la requête avec le même modèle que celui qu'utilise l'index :
embedding = await embedder.embed_query("How do I rotate an API key?")
results = await index.retrieve(
NearestNeighbourRetriever(query_embedding=embedding, top_k=10)
)KeywordRetriever
KeywordRetriever classe les fragments selon la qualité de la correspondance entre leur texte et les termes de la requête. Le retriever ignore les mots courants, comme « the » ou « and ».
from mistralai.search.toolkit.mistral_search_index.retriever import KeywordRetriever
results = await index.retrieve(
KeywordRetriever(query="ERR_TOKEN_EXPIRED", top_k=10)
)| Option | Type | Valeur par défaut | Rôle |
|---|---|---|---|
query | str | (obligatoire) | Texte de la requête à rechercher. |
field | str | None | None | Champ dans lequel rechercher. None recherche dans le champ content du fragment. Définissez un champ personnalisé indexé de type text, comme title, pour rechercher dans ce champ à la place. |
operator | "or" | "and" | "or" | "or" sélectionne les fragments contenant au moins un terme de la requête. "and" conserve uniquement les fragments contenant tous les termes. |
"or" convient aux questions en langage naturel, pour lesquelles peu de fragments contiennent tous les mots. Utilisez "and" pour des requêtes courtes et précises, comme des noms de produits ou des codes d'erreur :
results = await index.retrieve(
KeywordRetriever(query="annual report 2024", field="title", operator="and", top_k=10)
)RRFRetriever
RRFRetriever exécute ses retrievers enfants et fusionne leurs classements à l'aide de la reciprocal rank fusion (RRF). Pour chaque fragment qu'un enfant renvoie, celui-ci ajoute weight / (rank_constant + rank), et le retriever classe les fragments en fonction de la somme. Les fragments bien classés par plusieurs enfants arrivent en premier. Pour obtenir une recherche hybride, combinez un retriever par mots-clés et un retriever vectoriel :
from mistralai.search.toolkit.mistral_search_index.retriever import (
KeywordRetriever,
NearestNeighbourRetriever,
RRFRetriever,
)
question = "termination clauses"
results = await index.retrieve(
RRFRetriever(
top_k=10,
retrievers=[
KeywordRetriever(query=question, top_k=20),
NearestNeighbourRetriever(query=question, top_k=20),
],
)
)| Option | Type | Valeur par défaut | Rôle |
|---|---|---|---|
retrievers | list | (obligatoire) | Un ou plusieurs retrievers enfants, chacun étant un KeywordRetriever ou un NearestNeighbourRetriever. Un RRFRetriever ne peut pas être un enfant. |
weights | list[float] | None` | None | Un poids positif par enfant, dans le même ordre. None attribue le même poids à chaque enfant. |
rank_constant | int | 60 | Constante de lissage. Des valeurs plus faibles donnent plus de poids aux premiers rangs de chaque enfant. |
filter | Filter | None | None | S'applique à chaque enfant, combiné par un AND avec tout filtre que l'enfant porte. |
Le top_k de chaque enfant doit être au moins égal au top_k du RRFRetriever, et peut aller jusqu'à 1000. Donnez aux enfants plus de candidats que ce que vous renvoyez. Ainsi, un fragment qu'un enfant classe un peu plus bas peut encore atteindre les meilleurs résultats fusionnés.
Pondérer les enfants
Seul le rapport entre les poids compte. La requête suivante compare la question au texte du fragment et à un champ title personnalisé, avec un poids double sur title. Elle fusionne les deux classements avec la recherche vectorielle :
results = await index.retrieve(
RRFRetriever(
top_k=10,
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],
)
)Chaque KeywordRetriever effectue la correspondance sur un seul champ. Pour couvrir plusieurs champs, ajoutez un enfant par champ.
Configurer chaque enfant
Chaque enfant conserve ses propres options : son propre top_k, son propre filtre et son propre operator. Dans la requête suivante, la recherche par mots-clés exige tous les mots-clés dans les titres et compte ces correspondances deux fois. La recherche vectorielle puise dans un pool de candidats plus large et ne prend en compte que les documents de facturation :
from mistralai.search.toolkit.mistral_search_index.retriever import Equal
results = await index.retrieve(
RRFRetriever(
top_k=10,
weights=[2.0, 1.0],
retrievers=[
KeywordRetriever(query="refund policy", field="title", operator="and", top_k=20),
NearestNeighbourRetriever(
query="refund policy",
top_k=100,
max_candidates=500,
filter=Equal(field="category", value="billing"),
),
],
)
)Résultats
retrieve renvoie une liste d'objets SearchResult, la meilleure correspondance en premier. Un score plus élevé signifie une meilleure correspondance, et son échelle dépend du retriever :
| Retriever | score | distance |
|---|---|---|
NearestNeighbourRetriever | 1 - distance pour le cosinus ; -distance pour l2 et inner_product | La distance vectorielle brute |
KeywordRetriever | Un score de pertinence par mots-clés : plus élevé lorsque le fragment correspond mieux aux termes de la requête | None |
RRFRetriever | Le score RRF après fusion | None |
Les scores de retrievers différents ne sont pas comparables. Chaque chunk contient le contenu du fragment, ses champs personnalisés et son identité (id, source_id, locator). Les résultats n'incluent pas de représentations vectorielles.