Aller au contenu principal

Stocker des embeddings dans une base de données vectorielle

Après avoir généré des embeddings, vous devez les stocker dans une base de données prenant en charge la recherche vectorielle par similarité. Mastra fournit une interface cohérente pour stocker et interroger des embeddings dans différentes bases de données vectorielles.

Bases de données prises en charge
Lien direct vers Bases de données prises en charge

vector-store.ts
import { MongoDBVector } from '@mastra/mongodb'

const store = new MongoDBVector({
id: 'mongodb-vector',
uri: process.env.MONGODB_URI,
dbName: process.env.MONGODB_DB_NAME,
})
await store.createIndex({
indexName: 'myCollection',
dimension: 1536,
})
await store.upsert({
indexName: 'myCollection',
vectors: embeddings,
metadata: chunks.map(chunk => ({ text: chunk.text })),
})

Utiliser MongoDB Atlas Vector Search

Pour obtenir des instructions de configuration détaillées et connaître les bonnes pratiques, consultez la documentation officielle de MongoDB Atlas Vector Search.

Utiliser VoyageAI avec MongoDB

MongoDB fonctionne parfaitement avec les modèles d'embedding de VoyageAI, optimisés pour les tâches de recherche d'informations. Pour consulter des exemples complets et des modèles spécialisés, reportez-vous à la documentation sur les embeddings VoyageAI et à la référence vectorielle MongoDB.

Recherche hybride (vectorielle + texte intégral)

MongoDB prend en charge la recherche hybride, qui associe la similarité vectorielle à la recherche en texte intégral BM25 à l'aide de $rankFusion côté serveur (nécessite MongoDB >= 8.0 ; disponible de manière générale à partir de la version 8.1 et activée sur Atlas 8.0.x). Cette approche est utile pour combiner une recherche sémantique et une recherche par mots-clés :

await store.createSearchIndex({ indexName: 'myCollection', fields: ['text'] })
const results = await store.hybridQuery({
indexName: 'myCollection',
queryVector: embedding,
query: 'search terms',
paths: ['text'],
topK: 10,
})

Consultez la référence vectorielle MongoDB pour en savoir plus sur createSearchIndex(), textQuery() et hybridQuery().

Utiliser le stockage vectoriel
Lien direct vers Utiliser le stockage vectoriel

Une fois initialisés, tous les stockages vectoriels partagent la même interface pour créer des index, insérer ou mettre à jour des embeddings et effectuer des requêtes.

Créer des index
Lien direct vers Créer des index

Avant de stocker des embeddings, vous devez créer un index dont le nombre de dimensions correspond à votre modèle d'embedding :

store-embeddings.ts
// Create an index with dimension 1536 (for text-embedding-3-small)
await store.createIndex({
indexName: 'myCollection',
dimension: 1536,
})

Le nombre de dimensions doit correspondre à celui produit par le modèle d'embedding choisi. Les dimensions courantes sont les suivantes :

  • OpenAI text-embedding-3-small : 1 536 dimensions (ou une valeur personnalisée, par exemple 256)
  • Cohere embed-multilingual-v3 : 1 024 dimensions
  • VoyageAI voyage-3.5 : 1 024 dimensions (ou une valeur personnalisée : 256, 512, 1 024, 2 048)
  • Google gemini-embedding-001 : 768 dimensions (ou une valeur personnalisée)
attention

Les dimensions d'un index ne peuvent plus être modifiées après sa création. Pour utiliser un autre modèle, supprimez l'index, puis recréez-le avec le nouveau nombre de dimensions.

Règles de nommage des bases de données
Lien direct vers Règles de nommage des bases de données

Chaque base de données vectorielle impose des conventions de nommage propres aux index et aux collections afin de garantir la compatibilité et d'éviter les conflits.

Les noms de collections (index) doivent respecter les règles suivantes :

  • Commencer par une lettre ou un trait de soulignement
  • Ne pas dépasser 120 octets
  • Ne contenir que des lettres, des chiffres, des traits de soulignement ou des points
  • Ne pas contenir $ ni le caractère nul
  • Exemple : my_collection.123 est valide
  • Exemple : my-index n'est pas valide (contient un trait d'union)
  • Exemple : My$Collection n'est pas valide (contient $)

Insérer ou mettre à jour des embeddings
Lien direct vers Insérer ou mettre à jour des embeddings

Après avoir créé un index, vous pouvez stocker des embeddings avec leurs métadonnées de base :

store-embeddings.ts
// Store embeddings with their corresponding metadata
await store.upsert({
indexName: 'myCollection', // index name
vectors: embeddings, // array of embedding vectors
metadata: chunks.map(chunk => ({
text: chunk.text, // The original text content
id: chunk.id, // Optional unique identifier
})),
})

L'opération d'upsert :

  • Reçoit un tableau de vecteurs d'embedding et les métadonnées correspondantes
  • Met à jour les vecteurs existants s'ils partagent le même ID
  • Crée de nouveaux vecteurs s'ils n'existent pas
  • Gère automatiquement le traitement par lots pour les jeux de données volumineux

Ajouter des métadonnées
Lien direct vers Ajouter des métadonnées

Les stockages vectoriels prennent en charge des métadonnées riches (tout champ sérialisable en JSON) à des fins de filtrage et d'organisation. Comme les métadonnées sont stockées sans schéma fixe, utilisez des noms de champs cohérents afin d'éviter des résultats de requête inattendus.

attention

Les métadonnées sont essentielles au stockage vectoriel. Sans elles, vous ne disposeriez que d'embeddings numériques, sans aucun moyen de renvoyer le texte d'origine ni de filtrer les résultats. Stockez toujours au moins le texte source dans les métadonnées.

// Store embeddings with rich metadata for better organization and filtering
await store.upsert({
indexName: 'myCollection',
vectors: embeddings,
metadata: chunks.map(chunk => ({
// Basic content
text: chunk.text,
id: chunk.id,

// Document organization
source: chunk.source,
category: chunk.category,

// Temporal metadata
createdAt: new Date().toISOString(),
version: '1.0',

// Custom fields
language: chunk.language,
author: chunk.author,
confidenceScore: chunk.score,
})),
})

Points essentiels concernant les métadonnées :

  • Appliquez une convention stricte aux noms de champs : des incohérences telles que 'category' et 'Category' auront une incidence sur les requêtes
  • N'incluez que les champs que vous prévoyez d'utiliser pour filtrer ou trier : les champs supplémentaires entraînent un surcoût
  • Ajoutez des horodatages (par exemple 'createdAt', 'lastUpdated') pour suivre l'actualité du contenu

Supprimer des vecteurs
Lien direct vers Supprimer des vecteurs

Lors de la création d'applications RAG, vous devez souvent nettoyer les vecteurs obsolètes quand des documents sont supprimés ou mis à jour. Mastra fournit la méthode deleteVectors, qui permet de supprimer des vecteurs à l'aide de filtres de métadonnées. Vous pouvez ainsi retirer facilement tous les embeddings associés à un document donné.

Supprimer à l'aide d'un filtre de métadonnées
Lien direct vers Supprimer à l'aide d'un filtre de métadonnées

Le cas d'utilisation le plus courant consiste à supprimer tous les vecteurs d'un document donné lorsqu'un utilisateur supprime ce document :

delete-vectors.ts
// Delete all vectors for a specific document
await store.deleteVectors({
indexName: 'myCollection',
filter: { docId: 'document-123' },
})

Cette fonctionnalité est particulièrement utile dans les cas suivants :

  • Un utilisateur supprime un document et vous devez retirer tous ses segments
  • Vous réindexez un document et souhaitez d'abord supprimer les anciens vecteurs
  • Vous devez nettoyer les vecteurs associés à un utilisateur ou à un tenant donné

Supprimer plusieurs documents
Lien direct vers Supprimer plusieurs documents

Vous pouvez également utiliser des filtres complexes afin de supprimer les vecteurs qui répondent à plusieurs conditions :

delete-vectors-advanced.ts
// Delete all vectors for multiple documents
await store.deleteVectors({
indexName: 'myCollection',
filter: {
docId: { $in: ['doc-1', 'doc-2', 'doc-3'] },
},
})

// Delete vectors for a specific user's documents
await store.deleteVectors({
indexName: 'myCollection',
filter: {
$and: [{ userId: 'user-123' }, { status: 'archived' }],
},
})

Supprimer par ID de vecteur
Lien direct vers Supprimer par ID de vecteur

Si vous connaissez les ID des vecteurs à supprimer, vous pouvez les transmettre directement :

delete-by-ids.ts
// Delete specific vectors by their IDs
await store.deleteVectors({
indexName: 'myCollection',
ids: ['vec-1', 'vec-2', 'vec-3'],
})

Bonnes pratiques
Lien direct vers Bonnes pratiques

  • Créez les index avant les insertions en masse
  • Utilisez des opérations par lots pour les insertions volumineuses (la méthode d'upsert gère automatiquement le traitement par lots)
  • Ne stockez que les métadonnées que vous utiliserez dans vos requêtes
  • Faites correspondre les dimensions des embeddings à votre modèle (par exemple, 1 536 pour text-embedding-3-small)