Aller au contenu principal

Créer un assistant de recherche documentaire avec RAG

Dans ce guide, vous créerez un assistant de recherche IA capable d’analyser des articles universitaires et de répondre à des questions précises sur leur contenu avec la génération augmentée par récupération, ou RAG.

Vous utiliserez comme exemple l’article Transformer original « Attention Is All You Need ». Vous utiliserez une base de données libSQL locale.

Prérequis
Lien direct vers Prérequis

Fonctionnement de RAG
Lien direct vers Fonctionnement de RAG

Voyons comment fonctionne RAG et comment implémenter chaque composant.

Stockage/index de connaissances
Lien direct vers Stockage/index de connaissances

  • Conversion du texte en représentations vectorielles
  • Création de représentations numériques du contenu
  • Implémentation : vous utiliserez text-embedding-3-small d’OpenAI pour créer des embeddings et les stocker dans LibSQLVector

Récupérateur
Lien direct vers Récupérateur

  • Recherche de contenu pertinent avec la recherche par similarité
  • Mise en correspondance des embeddings de requête avec les vecteurs stockés
  • Implémentation : vous utiliserez LibSQLVector pour effectuer des recherches de similarité sur les embeddings stockés

Générateur
Lien direct vers Générateur

  • Traitement du contenu récupéré avec un LLM
  • Création de réponses informées par le contexte
  • Implémentation : vous utiliserez un modèle OpenAI pour générer des réponses basées sur le contenu récupéré

Votre implémentation :

  1. Traite l’article Transformer pour en créer des embeddings
  2. Les stocke dans LibSQLVector pour une récupération rapide
  3. Utilise une recherche par similarité pour trouver les sections pertinentes
  4. Génère des réponses précises avec le contexte récupéré

Créer l’Agent
Lien direct vers Créer l’Agent

Définissez le comportement de l’Agent, connectez-le à votre projet Mastra et créez le stockage vectoriel.

  1. Installez les dépendances supplémentaires.

    Après avoir suivi le guide d’installation, vous devrez installer des dépendances supplémentaires :

    npm install @mastra/rag@latest ai
  2. Vous allez maintenant créer votre assistant de recherche compatible RAG. L’Agent utilise :

    • Un Tool de requête vectorielle pour effectuer une recherche sémantique dans le stockage vectoriel et trouver du contenu pertinent dans les articles
    • Un modèle OpenAI pour comprendre les requêtes et générer des réponses
    • Des instructions personnalisées qui guident l’Agent dans l’analyse des articles, l’utilisation efficace du contenu récupéré et la reconnaissance de ses limites

    Créez un fichier src/mastra/agents/researchAgent.ts et définissez votre Agent :

    src/mastra/agents/researchAgent.ts
    import { Agent } from '@mastra/core/agent'
    import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
    import { createVectorQueryTool } from '@mastra/rag'

    // Create a tool for semantic search over the paper embeddings
    const vectorQueryTool = createVectorQueryTool({
    vectorStoreName: 'libSqlVector',
    indexName: 'papers',
    model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
    })

    export const researchAgent = new Agent({
    id: 'research-agent',
    name: 'Research Assistant',
    instructions: `You are a helpful research assistant that analyzes academic papers and technical documents.
    Use the provided vector query tool to find relevant information from your knowledge base,
    and provide accurate, well-supported answers based on the retrieved content.
    Focus on the specific content available in the tool and acknowledge if you cannot find sufficient information to answer a question.
    Base your responses only on the content provided, not on general knowledge.`,
    model: 'openai/gpt-5.6-sol',
    tools: {
    vectorQueryTool,
    },
    })
  3. À la racine du projet, récupérez le chemin absolu avec la commande pwd. Il peut ressembler à ceci :

    > pwd
    /Users/your-name/guides/research-assistant

    Dans votre fichier src/mastra/index.ts, ajoutez ce qui suit au fichier et à la configuration existants :

    src/mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { LibSQLVector } from '@mastra/libsql'

    const libSqlVector = new LibSQLVector({
    id: 'research-vectors',
    url: 'file:/Users/your-name/guides/research-assistant/vector.db',
    })

    export const mastra = new Mastra({
    vectors: { libSqlVector },
    })

    Pour url, utilisez le chemin absolu obtenu avec la commande pwd. Le fichier vector.db est ainsi créé à la racine du projet.

    remarque

    Dans ce guide, vous utilisez un chemin absolu codé en dur vers votre fichier libSQL local. Cela ne fonctionnera toutefois pas en production : utilisez alors une base de données persistante distante.

  4. Dans le fichier src/mastra/index.ts, ajoutez l’Agent à Mastra :

    src/mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { LibSQLVector } from '@mastra/libsql'
    import { researchAgent } from './agents/researchAgent'

    const libSqlVector = new LibSQLVector({
    id: 'research-vectors',
    url: 'file:/Users/your-name/guides/research-assistant/vector.db',
    })

    export const mastra = new Mastra({
    agents: { researchAgent },
    vectors: { libSqlVector },
    })

Traiter les documents
Lien direct vers Traiter les documents

Dans les étapes suivantes, vous récupérerez l’article de recherche et le découperez en segments plus petits. Vous générerez ensuite les embeddings et stockerez les segments dans la base de données vectorielle.

  1. À cette étape, l’article de recherche est récupéré à partir d’une URL, converti en objet document, puis découpé en segments plus petits et gérables. Ce découpage rend le traitement plus rapide et efficace.

    Créez un fichier src/store.ts et ajoutez ce qui suit :

    src/store.ts
    import { MDocument } from '@mastra/rag'

    // Load the paper
    const paperUrl = 'https://arxiv.org/html/1706.03762'
    const response = await fetch(paperUrl)
    const paperText = await response.text()

    // Create document and chunk it
    const doc = MDocument.fromText(paperText)
    const chunks = await doc.chunk({
    strategy: 'recursive',
    maxSize: 512,
    overlap: 50,
    separators: ['\n\n', '\n', ' '],
    })

    console.log('Number of chunks:', chunks.length)

    Exécutez le fichier dans votre terminal :

    npx bun src/store.ts

    Vous devriez obtenir cette réponse :

    Number of chunks: 892
  2. Enfin, préparez le contenu pour RAG en :

    1. Générant les embeddings de chaque segment de texte
    2. Créant un index de stockage vectoriel pour conserver les embeddings
    3. Stockant les embeddings et les métadonnées, texte original et informations de source, dans la base vectorielle
    remarque

    Ces métadonnées sont cruciales, car elles permettent de retourner le contenu réel lorsque le stockage vectoriel trouve des correspondances pertinentes.

    L’Agent utilise l’index vectoriel pour rechercher et récupérer des informations pertinentes.

    Ouvrez le fichier src/store.ts et ajoutez ce qui suit :

    src/store.ts
    import { MDocument } from '@mastra/rag'
    import { embedMany } from 'ai'
    import { mastra } from './mastra'

    // Load the paper
    const paperUrl = 'https://arxiv.org/html/1706.03762'
    const response = await fetch(paperUrl)
    const paperText = await response.text()

    // Create document and chunk it
    const doc = MDocument.fromText(paperText)
    const chunks = await doc.chunk({
    strategy: 'recursive',
    maxSize: 512,
    overlap: 50,
    separators: ['\n\n', '\n', ' '],
    })

    // Generate embeddings
    const { embeddings } = await embedMany({
    model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
    values: chunks.map(chunk => chunk.text),
    })

    // Get the vector store instance from Mastra
    const vectorStore = mastra.getVector('libSqlVector')

    // Create an index for paper chunks
    await vectorStore.createIndex({
    indexName: 'papers',
    dimension: 1536,
    })

    // Store embeddings
    await vectorStore.upsert({
    indexName: 'papers',
    vectors: embeddings,
    metadata: chunks.map(chunk => ({
    text: chunk.text,
    source: 'transformer-paper',
    })),
    })

    Enfin, stockez les embeddings en exécutant à nouveau le script :

    npx bun src/store.ts

    Si l’opération réussit, votre terminal ne doit afficher aucune sortie ni erreur.

Tester l’assistant
Lien direct vers Tester l’assistant

Maintenant que la base de données vectorielle contient tous les embeddings, vous pouvez tester l’assistant de recherche avec différents types de requêtes.

Créez un fichier src/ask-agent.ts et ajoutez différents types de requêtes :

src/ask-agent.ts
import { mastra } from './mastra'
const agent = mastra.getAgent('researchAgent')

// Basic query about concepts
const query1 = 'What problems does sequence modeling face with neural networks?'
const response1 = await agent.generate(query1)
console.log('\nQuery:', query1)
console.log('Response:', response1.text)

Exécutez le script :

npx bun src/ask-agent.ts

Vous devriez voir une sortie semblable à :

Query: What problems does sequence modeling face with neural networks?
Response: Sequence modeling with neural networks faces several key challenges:
1. Vanishing and exploding gradients during training, especially with long sequences
2. Difficulty handling long-term dependencies in the input
3. Limited computational efficiency due to sequential processing
4. Challenges in parallelizing computations, resulting in longer training times

Essayez une autre question :

src/ask-agent.ts
import { mastra } from './mastra'
const agent = mastra.getAgent('researchAgent')

// Query about specific findings
const query2 = 'What improvements were achieved in translation quality?'
const response2 = await agent.generate(query2)
console.log('\nQuery:', query2)
console.log('Response:', response2.text)

Sortie :

Query: What improvements were achieved in translation quality?
Response: The model showed significant improvements in translation quality, achieving more than 2.0
BLEU points improvement over previously reported models on the WMT 2014 English-to-German translation
task, while also reducing training costs.

Servir l’application
Lien direct vers Servir l’application

Démarrez le serveur Mastra afin d’exposer votre assistant de recherche via l’API :

mastra dev

Votre assistant de recherche sera disponible à l’adresse :

http://localhost:4111/api/agents/researchAgent/generate

Testez avec curl :

curl -X POST http://localhost:4111/api/agents/researchAgent/generate \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": "What were the main findings about model parallelization?" }
]
}'

Exemples RAG avancés
Lien direct vers Exemples RAG avancés

Explorez ces exemples pour découvrir des techniques RAG plus avancées :

  • Filter RAG pour filtrer les résultats avec des métadonnées
  • Cleanup RAG pour optimiser la densité d’information
  • Chain of Thought RAG pour les requêtes de raisonnement complexe avec des Workflows
  • Rerank RAG pour améliorer la pertinence des résultats