Aller au contenu principal

Récupération dans les systèmes RAG

Après avoir stocké les embeddings, vous devez récupérer les segments pertinents pour répondre aux requêtes des utilisateurs.

Mastra offre des options de récupération flexibles qui prennent en charge la recherche sémantique, le filtrage et le reranking.

Fonctionnement de la récupération
Lien direct vers Fonctionnement de la récupération

  1. La requête de l’utilisateur est convertie en embedding avec le même modèle que celui utilisé pour les embeddings de documents
  2. Cet embedding est comparé aux embeddings stockés au moyen de la similarité vectorielle
  3. Les segments les plus similaires sont récupérés et peuvent, au besoin, être :
  • Filtrés par métadonnées
  • Réordonnés pour une meilleure pertinence
  • Traités par un graphe de connaissances

Récupération de base
Lien direct vers Récupération de base

L’approche la plus simple consiste en une recherche sémantique directe. Cette méthode utilise la similarité vectorielle pour trouver les segments sémantiquement similaires à la requête :

import { embed } from 'ai'
import { PgVector } from '@mastra/pg'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'

// Convert query to embedding
const { embedding } = await embed({
value: 'What are the main points in the article?',
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
})

// Query vector store
const pgVector = new PgVector({
id: 'pg-vector',
connectionString: process.env.POSTGRES_CONNECTION_STRING,
})
const results = await pgVector.query({
indexName: 'embeddings',
queryVector: embedding,
topK: 10,
})

// Display results
console.log(results)

Le paramètre topK indique le nombre maximal de résultats les plus similaires à renvoyer par la recherche vectorielle.

Les résultats contiennent à la fois le contenu texte et un score de similarité :

[
{
text: 'Climate change poses significant challenges...',
score: 0.89,
metadata: { source: 'article1.txt' },
},
{
text: 'Rising temperatures affect crop yields...',
score: 0.82,
metadata: { source: 'article1.txt' },
},
]

Options de récupération avancées
Lien direct vers Options de récupération avancées

Filtrage par métadonnées
Lien direct vers Filtrage par métadonnées

Filtrez les résultats selon les champs de métadonnées afin de réduire l’espace de recherche. Cette approche, qui combine recherche par similarité vectorielle et filtres de métadonnées, est parfois appelée recherche vectorielle hybride, car elle associe la recherche sémantique à des critères de filtrage structurés.

Cette approche est utile lorsque vous disposez de documents provenant de sources ou périodes différentes, ou ayant des attributs spécifiques. Mastra fournit une syntaxe de requête unifiée de style MongoDB qui fonctionne avec tous les stockages vectoriels pris en charge.

Pour obtenir des informations détaillées sur les opérateurs disponibles et leur syntaxe, consultez la référence des filtres de métadonnées.

Exemples de filtrage de base :

// Simple equality filter
const results = await pgVector.query({
indexName: 'embeddings',
queryVector: embedding,
topK: 10,
filter: {
source: 'article1.txt',
},
})

// Numeric comparison
const results = await pgVector.query({
indexName: 'embeddings',
queryVector: embedding,
topK: 10,
filter: {
price: { $gt: 100 },
},
})

// Multiple conditions
const results = await pgVector.query({
indexName: 'embeddings',
queryVector: embedding,
topK: 10,
filter: {
category: 'electronics',
price: { $lt: 1000 },
inStock: true,
},
})

// Array operations
const results = await pgVector.query({
indexName: 'embeddings',
queryVector: embedding,
topK: 10,
filter: {
tags: { $in: ['sale', 'new'] },
},
})

// Logical operators
const results = await pgVector.query({
indexName: 'embeddings',
queryVector: embedding,
topK: 10,
filter: {
$or: [{ category: 'electronics' }, { category: 'accessories' }],
$and: [{ price: { $gt: 50 } }, { price: { $lt: 200 } }],
},
})

Cas d’utilisation courants du filtrage par métadonnées :

  • Filtrer par source ou type de document
  • Filtrer par plages de dates
  • Filtrer par catégories ou tags spécifiques
  • Filtrer par plages numériques, par exemple le prix ou la note
  • Combiner plusieurs conditions pour des requêtes précises
  • Filtrer par attributs de document, par exemple la langue ou l’auteur

Tool de requête vectorielle
Lien direct vers Tool de requête vectorielle

Vous souhaitez parfois permettre à votre Agent d’interroger directement une base de données vectorielle. Le Tool de requête vectorielle confie à votre Agent les décisions de récupération, en associant recherche sémantique, filtrage facultatif et reranking selon sa compréhension des besoins de l’utilisateur.

import { createVectorQueryTool } from '@mastra/rag'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'

const vectorQueryTool = createVectorQueryTool({
vectorStoreName: 'pgVector',
indexName: 'embeddings',
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
})

Lors de la création du Tool, prêtez une attention particulière à son nom et à sa description : ils aident l’Agent à comprendre quand et comment utiliser les capacités de récupération. Vous pourriez, par exemple, le nommer « SearchKnowledgeBase » et le décrire ainsi : « Recherchez dans notre documentation des informations pertinentes sur le sujet X. »

Cela est particulièrement utile lorsque :

  • Votre Agent doit décider à l’exécution quelles informations récupérer
  • Le processus de récupération exige une prise de décision complexe
  • Vous voulez que l’Agent combine plusieurs stratégies de récupération selon le contexte

Configurations propres aux bases de données
Lien direct vers Configurations propres aux bases de données

Le Tool de requête vectorielle prend en charge des configurations propres aux bases de données qui permettent d’utiliser les fonctionnalités et optimisations spécifiques des différents stockages vectoriels.

remarque

Ces configurations concernent les options à l’exécution de la requête, telles que les espaces de noms, le réglage des performances et le filtrage, et non la configuration de connexion à la base de données.

Les identifiants de connexion, URL et jetons d’authentification, sont configurés lors de l’instanciation de la classe de stockage vectoriel, par exemple new LibSQLVector({ url: '...' }).

import { createVectorQueryTool } from '@mastra/rag'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'

// Pinecone with namespace
const pineconeQueryTool = createVectorQueryTool({
vectorStoreName: 'pinecone',
indexName: 'docs',
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
databaseConfig: {
pinecone: {
namespace: 'production', // Isolate data by environment
},
},
})

// pgVector with performance tuning
const pgVectorQueryTool = createVectorQueryTool({
vectorStoreName: 'postgres',
indexName: 'embeddings',
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
databaseConfig: {
pgvector: {
minScore: 0.7, // Filter low-quality results
ef: 200, // HNSW search parameter
probes: 10, // IVFFlat probe parameter
},
},
})

// Chroma with advanced filtering
const chromaQueryTool = createVectorQueryTool({
vectorStoreName: 'chroma',
indexName: 'documents',
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
databaseConfig: {
chroma: {
where: { category: 'technical' },
whereDocument: { $contains: 'API' },
},
},
})

// LanceDB with table specificity
const lanceQueryTool = createVectorQueryTool({
vectorStoreName: 'lance',
indexName: 'documents',
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
databaseConfig: {
lance: {
tableName: 'myVectors', // Specify which table to query
includeAllColumns: true, // Include all metadata columns in results
},
},
})

Avantages principaux :

  • Espaces de noms Pinecone : organisez les vecteurs par locataire, environnement ou type de données
  • Optimisation pgVector : contrôlez la précision et la vitesse de recherche avec les paramètres ef/probes
  • Filtrage de qualité : définissez des seuils minimaux de similarité pour améliorer la pertinence des résultats
  • Tables LanceDB : séparez les données en tables pour une meilleure organisation et de meilleures performances
  • Flexibilité à l’exécution : remplacez les configurations à l’exécution selon le contexte

Cas d’utilisation courants :

  • Applications multi-locataires utilisant les espaces de noms Pinecone
  • Optimisation des performances dans les scénarios à forte charge
  • Configurations propres aux environnements, dev/staging/prod
  • Résultats de recherche contrôlés par la qualité
  • Stockage vectoriel embarqué fondé sur des fichiers avec LanceDB pour les scénarios de déploiement à la périphérie

Vous pouvez aussi remplacer ces configurations à l’exécution au moyen du contexte de requête :

import { RequestContext } from '@mastra/core/request-context'

const requestContext = new RequestContext()
requestContext.set('databaseConfig', {
pinecone: {
namespace: 'runtime-namespace',
},
})

await pineconeQueryTool.execute({ queryText: 'search query' }, { mastra, requestContext })

Pour les options de configuration détaillées et les usages avancés, consultez la référence du Tool de requête vectorielle.

Prompts de stockage vectoriel
Lien direct vers Prompts de stockage vectoriel

Les prompts de stockage vectoriel définissent les modèles de requêtes et les capacités de filtrage de chaque implémentation de base de données vectorielle. Lors de l’implémentation du filtrage, ces prompts sont nécessaires dans les instructions de l’Agent afin de spécifier les opérateurs et la syntaxe valides pour chaque implémentation de stockage vectoriel.

import { PGVECTOR_PROMPT } from '@mastra/pg'

export const ragAgent = new Agent({
id: 'rag-agent',
name: 'RAG Agent',
model: 'openai/gpt-5.6-sol',
instructions: `
Process queries using the provided context. Structure responses to be concise and relevant.
${PGVECTOR_PROMPT}
`,
tools: { vectorQueryTool },
})

Reranking
Lien direct vers Reranking

La recherche initiale par similarité vectorielle peut parfois manquer de précision dans la pertinence. Le reranking est un processus plus coûteux en calcul, mais plus précis, qui améliore les résultats en :

  • Prenant en compte l’ordre des mots et les correspondances exactes
  • Appliquant un score de pertinence plus avancé
  • Utilisant une méthode appelée attention croisée entre la requête et les documents

Voici comment utiliser le reranking :

import { rerankWithScorer as rerank, MastraAgentRelevanceScorer } from '@mastra/rag'

// Get initial results from vector search
const initialResults = await pgVector.query({
indexName: 'embeddings',
queryVector: queryEmbedding,
topK: 10,
})

// Create a relevance scorer
const relevanceProvider = new MastraAgentRelevanceScorer(
'relevance-scorer',
'openai/gpt-5.6-sol',
)

// Re-rank the results
const rerankedResults = await rerank({
results: initialResults,
query,
scorer: relevanceProvider,
options: {
weights: {
semantic: 0.5, // How well the content matches the query semantically
vector: 0.3, // Original vector similarity score
position: 0.2, // Preserves original result ordering
},
topK: 10,
},
})

Les pondérations contrôlent l’influence des différents facteurs sur le classement final :

  • semantic : des valeurs plus élevées privilégient la compréhension sémantique et la pertinence par rapport à la requête
  • vector : des valeurs plus élevées favorisent les scores de similarité vectorielle d’origine
  • position : des valeurs plus élevées aident à préserver l’ordre initial des résultats
remarque

Pour que le score sémantique fonctionne correctement durant le reranking, chaque résultat doit inclure le contenu texte dans son champ metadata.text.

Vous pouvez aussi utiliser d’autres fournisseurs de score de pertinence, tels que Cohere ou ZeroEntropy :

const relevanceProvider = new CohereRelevanceScorer('rerank-v3.5')
const relevanceProvider = new ZeroEntropyRelevanceScorer('zerank-1')

Les résultats réordonnés combinent la similarité vectorielle et la compréhension sémantique afin d’améliorer la qualité de récupération.

Pour plus de détails sur le reranking, consultez la méthode rerank().

Pour une récupération fondée sur les graphes qui suit les connexions entre segments, consultez la documentation GraphRAG.