> Discover all available pages from the documentation index: https://mastra.zisheng.pro/fr/llms.txt # 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 **MongoDB**: ```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](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-overview/?utm_campaign=devrel\&utm_source=third-party-content\&utm_medium=cta\&utm_content=mastra-docs). ### 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](https://mastra.zisheng.pro/fr/models/embeddings) et à la [référence vectorielle MongoDB](https://mastra.zisheng.pro/fr/reference/vectors/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 : ```ts 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](https://mastra.zisheng.pro/fr/reference/vectors/mongodb) pour en savoir plus sur `createSearchIndex()`, `textQuery()` et `hybridQuery()`. **PgVector**: ```ts import { PgVector } from '@mastra/pg' const store = new PgVector({ id: 'pg-vector', connectionString: process.env.POSTGRES_CONNECTION_STRING, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` ### Utiliser PostgreSQL avec pgvector PostgreSQL avec l'extension pgvector constitue une bonne solution pour les équipes qui utilisent déjà PostgreSQL et souhaitent réduire la complexité de leur infrastructure. Pour obtenir des instructions de configuration détaillées et connaître les bonnes pratiques, consultez le [dépôt officiel de pgvector](https://github.com/pgvector/pgvector). **OracleDB**: ```ts import { OracleVector } from '@mastra/oracledb' const store = new OracleVector({ id: 'oracle-vector', user: process.env.ORACLE_DATABASE_USER, password: process.env.ORACLE_DATABASE_PASSWORD, connectString: process.env.ORACLE_DATABASE_CONNECT_STRING, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, indexConfig: { type: 'none' }, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` ### Utiliser Oracle Database Vector Search OracleDB stocke les embeddings dans des colonnes `VECTOR` natives et les métadonnées au format Oracle JSON. La recherche exacte est utilisée par défaut ; des index HNSW et IVF peuvent être configurés pour optimiser les déploiements. **Pinecone**: ```ts import { PineconeVector } from '@mastra/pinecone' const store = new PineconeVector({ id: 'pinecone-vector', apiKey: process.env.PINECONE_API_KEY, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Qdrant**: ```ts import { QdrantVector } from '@mastra/qdrant' const store = new QdrantVector({ id: 'qdrant-vector', url: process.env.QDRANT_URL, apiKey: process.env.QDRANT_API_KEY, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Chroma**: ```ts import { ChromaVector } from '@mastra/chroma' // Running Chroma locally // const store = new ChromaVector() // Running on Chroma Cloud const store = new ChromaVector({ id: 'chroma-vector', apiKey: process.env.CHROMA_API_KEY, tenant: process.env.CHROMA_TENANT, database: process.env.CHROMA_DATABASE, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Astra**: ```ts import { AstraVector } from '@mastra/astra' const store = new AstraVector({ id: 'astra-vector', token: process.env.ASTRA_DB_TOKEN, endpoint: process.env.ASTRA_DB_ENDPOINT, keyspace: process.env.ASTRA_DB_KEYSPACE, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **libSQL**: ```ts import { LibSQLVector } from '@mastra/core/vector/libsql' const store = new LibSQLVector({ id: 'libsql-vector', url: process.env.DATABASE_URL, authToken: process.env.DATABASE_AUTH_TOKEN, // Optional: for Turso cloud databases }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Upstash**: ```ts import { UpstashVector } from '@mastra/upstash' // In upstash they refer to the store as an index const store = new UpstashVector({ id: 'upstash-vector', url: process.env.UPSTASH_URL, token: process.env.UPSTASH_TOKEN, }) // There is no store.createIndex call here, Upstash creates indexes (known as namespaces in Upstash) automatically // when you upsert if that namespace does not exist yet. await store.upsert({ indexName: 'myCollection', // the namespace name in Upstash vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Cloudflare**: ```ts import { CloudflareVector } from '@mastra/vectorize' const store = new CloudflareVector({ id: 'cloudflare-vector', accountId: process.env.CF_ACCOUNT_ID, apiToken: process.env.CF_API_TOKEN, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **OpenSearch**: ```ts import { OpenSearchVector } from '@mastra/opensearch' const store = new OpenSearchVector({ id: 'opensearch', node: process.env.OPENSEARCH_URL }) await store.createIndex({ indexName: 'my-collection', dimension: 1536, }) await store.upsert({ indexName: 'my-collection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Elasticsearch**: ```ts import { ElasticSearchVector } from '@mastra/elasticsearch' const store = new ElasticSearchVector({ id: 'elasticsearch-vector', url: process.env.ELASTICSEARCH_URL, auth: { apiKey: process.env.ELASTICSEARCH_API_KEY, }, }) await store.createIndex({ indexName: 'my-collection', dimension: 1536, }) await store.upsert({ indexName: 'my-collection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` ### Utiliser Elasticsearch Pour obtenir des instructions de configuration détaillées et connaître les bonnes pratiques, consultez la [documentation officielle d'Elasticsearch](https://www.elastic.co/docs/solutions/search/get-started). **Couchbase**: ```ts import { CouchbaseVector } from '@mastra/couchbase' const store = new CouchbaseVector({ id: 'couchbase-vector', connectionString: process.env.COUCHBASE_CONNECTION_STRING, username: process.env.COUCHBASE_USERNAME, password: process.env.COUCHBASE_PASSWORD, bucketName: process.env.COUCHBASE_BUCKET, scopeName: process.env.COUCHBASE_SCOPE, collectionName: process.env.COUCHBASE_COLLECTION, }) await store.createIndex({ indexName: 'myCollection', dimension: 1536, }) await store.upsert({ indexName: 'myCollection', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` **Lance**: ```ts import { LanceVectorStore } from '@mastra/lance' const store = await LanceVectorStore.create('/path/to/db') await store.createIndex({ tableName: 'myVectors', indexName: 'myCollection', dimension: 1536, }) await store.upsert({ tableName: 'myVectors', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` ### Utiliser LanceDB LanceDB est une base de données vectorielle intégrée reposant sur le format en colonnes Lance, adaptée au développement local comme au déploiement dans le cloud. Pour obtenir des instructions de configuration détaillées et connaître les bonnes pratiques, consultez la [documentation officielle de LanceDB](https://lancedb.github.io/lancedb/). **S3 Vectors**: ```ts import { S3Vectors } from '@mastra/s3vectors' const store = new S3Vectors({ id: 's3-vectors', vectorBucketName: 'my-vector-bucket', clientConfig: { region: 'us-east-1', }, nonFilterableMetadataKeys: ['content'], }) await store.createIndex({ indexName: 'my-index', dimension: 1536, }) await store.upsert({ indexName: 'my-index', vectors: embeddings, metadata: chunks.map(chunk => ({ text: chunk.text })), }) ``` ## 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 Avant de stocker des embeddings, vous devez créer un index dont le nombre de dimensions correspond à votre modèle d'embedding : ```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 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. **MongoDB**: 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 `$`) **PgVector**: Les noms d'index doivent respecter les règles suivantes : - Commencer par une lettre ou un trait de soulignement - Ne contenir que des lettres, des chiffres et des traits de soulignement - Exemple : `my_index_123` est valide - Exemple : `my-index` n'est pas valide (contient un trait d'union) **OracleDB**: Les noms d'index sont des noms logiques Mastra. En interne, OracleDB associe chaque index logique à une table Oracle physique. Les noms d'index logiques doivent respecter les règles suivantes : - Ne pas être vides - Compter au maximum 512 caractères - Rester stables pendant toute la durée de vie de l'index vectoriel - Exemple : `my_collection_123` est valide - Exemple : `customer-support/docs:v1` est valide et est associé à un nom de table Oracle sûr **Pinecone**: Les noms d'index doivent respecter les règles suivantes : - N'utiliser que des lettres minuscules, des chiffres et des traits d'union - Ne pas contenir de points (utilisés pour le routage DNS) - Ne pas utiliser de caractères non latins ni d'émojis - Avoir une longueur totale (avec l'ID du projet) inférieure à 52 caractères - Exemple : `my-index-123` est valide - Exemple : `my.index` n'est pas valide (contient un point) **Qdrant**: Les noms de collections doivent respecter les règles suivantes : - Compter entre 1 et 255 caractères - Ne contenir aucun des caractères spéciaux suivants : - `< > : " / \ | ? *` - Caractère nul (`\0`) - Séparateur d'unités (`\u{1F}`) - Exemple : `my_collection_123` est valide - Exemple : `my/collection` n'est pas valide (contient une barre oblique) **Chroma**: Les noms de collections doivent respecter les règles suivantes : - Compter entre 3 et 63 caractères - Commencer et se terminer par une lettre ou un chiffre - Ne contenir que des lettres, des chiffres, des traits de soulignement ou des traits d'union - Ne pas contenir de points consécutifs (..) - Ne pas correspondre à une adresse IPv4 valide - Exemple : `my-collection-123` est valide - Exemple : `my..collection` n'est pas valide (points consécutifs) **Astra**: Les noms de collections doivent respecter les règles suivantes : - Ne pas être vides - Compter au maximum 48 caractères - Ne contenir que des lettres, des chiffres et des traits de soulignement - Exemple : `my_collection_123` est valide - Exemple : `my-collection` n'est pas valide (contient un trait d'union) **libSQL**: Les noms d'index doivent respecter les règles suivantes : - Commencer par une lettre ou un trait de soulignement - Ne contenir que des lettres, des chiffres et des traits de soulignement - Exemple : `my_index_123` est valide - Exemple : `my-index` n'est pas valide (contient un trait d'union) **Upstash**: Les noms d'espaces de noms doivent respecter les règles suivantes : - Compter entre 2 et 100 caractères - Ne contenir que : - Des caractères alphanumériques (a-z, A-Z, 0-9) - Des traits de soulignement, des traits d'union et des points - Ne pas commencer ni se terminer par un caractère spécial (\_, -, .) - Pouvoir être sensibles à la casse - Exemple : `MyNamespace123` est valide - Exemple : `_namespace` n'est pas valide (commence par un trait de soulignement) **Cloudflare**: Les noms d'index doivent respecter les règles suivantes : - Commencer par une lettre - Compter moins de 32 caractères - Ne contenir que des lettres ASCII minuscules, des chiffres et des traits d'union - Utiliser des traits d'union à la place des espaces - Exemple : `my-index-123` est valide - Exemple : `My_Index` n'est pas valide (contient une majuscule et un trait de soulignement) **OpenSearch**: Les noms d'index doivent respecter les règles suivantes : - N'utiliser que des lettres minuscules - Ne pas commencer par un trait de soulignement ni un trait d'union - Ne contenir ni espaces ni virgules - Ne pas contenir de caractères spéciaux (par exemple `:`, `"`, `*`, `+`, `/`, `\`, `|`, `?`, `#`, `>`, `<`) - Exemple : `my-index-123` est valide - Exemple : `My_Index` n'est pas valide (contient des lettres majuscules) - Exemple : `_myindex` n'est pas valide (commence par un trait de soulignement) **Elasticsearch**: Les noms d'index doivent respecter les règles suivantes : - N'utiliser que des lettres minuscules - Ne pas dépasser 255 octets (en tenant compte des caractères multioctets) - Ne pas commencer par un trait de soulignement, un trait d'union ou un signe plus - Ne contenir ni espaces ni virgules - Ne pas contenir de caractères spéciaux (par exemple `:`, `"`, `*`, `+`, `/`, `\`, `|`, `?`, `#`, `>`, `<`) - Ne pas être égal à "." ni à ".." - Ne pas commencer par "." (déconseillé, sauf pour les index système ou masqués) - Exemple : `my-index-123` est valide - Exemple : `My_Index` n'est pas valide (contient des lettres majuscules) - Exemple : `_myindex` n'est pas valide (commence par un trait de soulignement) - Exemple : `.myindex` n'est pas valide (commence par un point, usage déconseillé) **S3 Vectors**: Les noms d'index doivent respecter les règles suivantes : - Être uniques au sein d'un même bucket vectoriel - Compter entre 3 et 63 caractères - N'utiliser que des lettres minuscules (`a–z`), des chiffres (`0–9`), des traits d'union (`-`) et des points (`.`) - Commencer et se terminer par une lettre ou un chiffre - Exemple : `my-index.123` est valide - Exemple : `my_index` n'est pas valide (contient un trait de soulignement) - Exemple : `-myindex` n'est pas valide (commence par un trait d'union) - Exemple : `myindex-` n'est pas valide (se termine par un trait d'union) - Exemple : `MyIndex` n'est pas valide (contient des lettres majuscules) ### 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 : ```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 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. ```ts // 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 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 Le cas d'utilisation le plus courant consiste à supprimer tous les vecteurs d'un document donné lorsqu'un utilisateur supprime ce document : ```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 Vous pouvez également utiliser des filtres complexes afin de supprimer les vecteurs qui répondent à plusieurs conditions : ```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 Si vous connaissez les ID des vecteurs à supprimer, vous pouvez les transmettre directement : ```ts // Delete specific vectors by their IDs await store.deleteVectors({ indexName: 'myCollection', ids: ['vec-1', 'vec-2', 'vec-3'], }) ``` ## 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`)