Stockage vectoriel Convex
La classe ConvexVector fournit un stockage vectoriel et une recherche par similarité au moyen de Convex. Elle stocke les embeddings dans Convex et effectue la recherche par similarité cosinus dans l'adaptateur Mastra.
ConvexVector lit les vecteurs correspondants via le gestionnaire de stockage Mastra, les filtre en JavaScript, calcule leur similarité cosinus, trie les résultats et renvoie les meilleures correspondances. Utilisez-le pour le développement local, les tests et les petits jeux de données.
Pour la recherche vectorielle en production sur Convex, utilisez ConvexNativeVector. Il utilise l'API native vectorSearch de Convex, qui nécessite un index vectoriel Convex déployé et une action Convex.
InstallationLien direct vers Installation
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/convex@latest
pnpm add @mastra/convex@latest
yarn add @mastra/convex@latest
bun add @mastra/convex@latest
Configuration de ConvexLien direct vers Configuration de Convex
Avant d'utiliser ConvexVector, vous devez configurer le schéma et le gestionnaire de stockage Convex. Consultez la configuration du stockage Convex pour obtenir les instructions.
Options du constructeurLien direct vers Options du constructeur
deploymentUrl:
adminAuthToken:
storageFunction?:
Exemples de constructeurLien direct vers Exemples de constructeur
Configuration de baseLien direct vers Configuration de base
import { ConvexVector } from '@mastra/convex'
const vectorStore = new ConvexVector({
id: 'convex-vectors',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
})
Recherche vectorielle native de ConvexLien direct vers Recherche vectorielle native de Convex
Utilisez ConvexNativeVector pour les charges vectorielles de production. Il stocke les vecteurs dans une table Convex dédiée et interroge un index vectoriel Convex défini dans le schéma.
Dans convex/schema.ts, définissez une table dédiée pour chaque index vectoriel Mastra :
import { defineSchema } from 'convex/server'
import { defineMastraNativeVectorTable } from '@mastra/convex/schema'
export default defineSchema({
docs_vectors: defineMastraNativeVectorTable({
dimensions: 1536,
}),
})
Dans convex/mastra/nativeVector.ts, exportez les gestionnaires vectoriels natifs :
import {
mastraNativeVectorAction,
mastraNativeVectorMutation,
mastraNativeVectorQuery,
} from '@mastra/convex/server'
export const query = mastraNativeVectorAction
export const read = mastraNativeVectorQuery
export const write = mastraNativeVectorMutation
Dans votre application Mastra, configurez ConvexNativeVector avec la table et l'index vectoriel déployés :
import { ConvexNativeVector } from '@mastra/convex'
const vectorStore = new ConvexNativeVector({
id: 'convex-native-vectors',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
indexes: {
docs: {
tableName: 'docs_vectors',
vectorIndexName: 'by_embedding',
dimension: 1536,
},
},
})
const results = await vectorStore.query({
indexName: 'docs',
queryVector: embedding,
topK: 10,
})
Pour prendre en charge les filtres natifs, déclarez leurs champs dans votre schéma Convex. Lors de l'écriture des vecteurs, les gestionnaires vectoriels natifs copient les champs de métadonnées correspondants dans les champs de premier niveau du document.
import { defineSchema, defineTable } from 'convex/server'
import { v } from 'convex/values'
export default defineSchema({
docs_vectors: defineTable({
id: v.string(),
embedding: v.array(v.float64()),
metadata: v.optional(v.any()),
tenantId: v.string(),
})
.index('by_record_id', ['id'])
.vectorIndex('by_embedding', {
vectorField: 'embedding',
dimensions: 1536,
filterFields: ['tenantId'],
}),
})
const vectorStore = new ConvexNativeVector({
id: 'convex-native-vectors',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
indexes: {
docs: {
tableName: 'docs_vectors',
dimension: 1536,
filterFields: ['tenantId'],
},
},
})
await vectorStore.upsert({
indexName: 'docs',
ids: ['chunk-1'],
vectors: [embedding],
metadata: [{ tenantId: 'acme', text: 'Account setup guide' }],
})
const results = await vectorStore.query({
indexName: 'docs',
queryVector: embedding,
filter: { tenantId: 'acme' },
})
ConvexNativeVector prend en charge les formes de filtres vectoriels natifs de Convex : un champ d'égalité, ou un $or de champs d'égalité. Il ne prend pas en charge les requêtes reposant uniquement sur les métadonnées, ni les mises à jour ou suppressions fondées sur des filtres. Utilisez les identifiants des vecteurs pour les mises à jour et les suppressions.
Fonction de stockage personnaliséeLien direct vers Fonction de stockage personnalisée
const vectorStore = new ConvexVector({
id: 'convex-vectors',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
storageFunction: 'custom/path:handler',
})
MéthodesLien direct vers Méthodes
createIndex()Lien direct vers createindex
indexName:
dimension:
metric?:
await vectorStore.createIndex({
indexName: 'my_vectors',
dimension: 1536,
})
upsert()Lien direct vers upsert
indexName:
vectors:
metadata?:
ids?:
await vectorStore.upsert({
indexName: "my_vectors",
vectors: [[0.1, 0.2, 0.3, ...]],
metadata: [{ label: "example" }],
ids: ["vec-1"],
});
query()Lien direct vers query
indexName:
queryVector:
topK?:
filter?:
includeVector?:
const results = await vectorStore.query({
indexName: "my_vectors",
queryVector: [0.1, 0.2, 0.3, ...],
topK: 5,
filter: { category: "documents" },
});
listIndexes()Lien direct vers listindexes
Renvoie un tableau de noms d'index sous forme de chaînes.
const indexes = await vectorStore.listIndexes()
// ["my_vectors", "embeddings", ...]
describeIndex()Lien direct vers describeindex
indexName:
Renvoie :
interface IndexStats {
dimension: number
count: number
metric: 'cosine' | 'euclidean' | 'dotproduct'
}
deleteIndex()Lien direct vers deleteindex
indexName:
Supprime l'index et tous ses vecteurs.
await vectorStore.deleteIndex({ indexName: 'my_vectors' })
updateVector()Lien direct vers updatevector
Met à jour un seul vecteur à partir de son identifiant ou d'un filtre de métadonnées. Vous devez fournir soit id, soit filter, mais pas les deux.
indexName:
id?:
filter?:
update:
// Update by ID
await vectorStore.updateVector({
indexName: 'my_vectors',
id: 'vector123',
update: {
vector: [0.1, 0.2, 0.3],
metadata: { label: 'updated' },
},
})
// Update by filter
await vectorStore.updateVector({
indexName: 'my_vectors',
filter: { category: 'product' },
update: {
metadata: { status: 'reviewed' },
},
})
deleteVector()Lien direct vers deletevector
indexName:
id:
await vectorStore.deleteVector({ indexName: 'my_vectors', id: 'vector123' })
deleteVectors()Lien direct vers deletevectors
Supprime plusieurs vecteurs à partir de leurs identifiants ou d'un filtre de métadonnées. Vous devez fournir soit ids, soit filter, mais pas les deux.
indexName:
ids?:
filter?:
// Delete by IDs
await vectorStore.deleteVectors({
indexName: 'my_vectors',
ids: ['vec1', 'vec2', 'vec3'],
})
// Delete by filter
await vectorStore.deleteVectors({
indexName: 'my_vectors',
filter: { status: 'archived' },
})
Types de réponseLien direct vers Types de réponse
Les résultats de la requête sont renvoyés au format suivant :
interface QueryResult {
id: string
score: number
metadata: Record<string, any>
vector?: number[] // Only included if includeVector is true
}
Filtrage des métadonnéesLien direct vers Filtrage des métadonnées
ConvexVector prend en charge le filtrage des métadonnées au moyen d'opérateurs. L'adaptateur applique ces filtres après avoir chargé les vecteurs depuis Convex.
// Simple equality
const results = await vectorStore.query({
indexName: 'my_vectors',
queryVector: embedding,
filter: { category: 'documents' },
})
// Comparison operators
const results = await vectorStore.query({
indexName: 'my_vectors',
queryVector: embedding,
filter: {
price: { $gt: 100 },
status: { $in: ['active', 'pending'] },
},
})
// Logical operators
const results = await vectorStore.query({
indexName: 'my_vectors',
queryVector: embedding,
filter: {
$and: [{ category: 'electronics' }, { price: { $lte: 500 } }],
},
})
Opérateurs de filtre pris en chargeLien direct vers Opérateurs de filtre pris en charge
| Opérateur | Description |
|---|---|
$eq | Égal à |
$ne | Différent de |
$gt | Supérieur à |
$gte | Supérieur ou égal à |
$lt | Inférieur à |
$lte | Inférieur ou égal à |
$in | Dans le tableau |
$nin | Absent du tableau |
$and | ET logique |
$or | OU logique |
ArchitectureLien direct vers Architecture
ConvexVector stocke les vecteurs dans la table mastra_vectors avec la structure suivante :
id: identifiant unique du vecteurindexName: nom de l'indexembedding: données du vecteur (tableau de nombres à virgule flottante)metadata: métadonnées JSON facultatives
La recherche par similarité vectorielle est effectuée au moyen de la similarité cosinus dans l'adaptateur Mastra. Cette approche garantit une configuration flexible, mais n'est pas conçue pour de grandes collections vectorielles de production.
ConvexNativeVector stocke chaque index vectoriel Mastra dans une table Convex dédiée. Ses requêtes appellent une action Convex qui utilise ctx.vectorSearch, puis chargent les documents correspondants au moyen d'une requête Convex. Cette approche suit le modèle de recherche vectorielle natif de Convex :
- Les index vectoriels sont déclarés dans
convex/schema.ts. - La recherche vectorielle est exécutée depuis une action Convex.
topKdoit être compris entre1et256.- Les filtres doivent cibler les champs répertoriés dans
filterFieldsde l'index vectoriel Convex. - Utilisez une table dédiée par index vectoriel Mastra afin d'éviter les résultats provenant de plusieurs index.
Utilisez une base de données vectorielle externe lorsque vous avez besoin de créer des index définis à l'exécution, d'effectuer des requêtes reposant uniquement sur les métadonnées, d'utiliser des opérateurs de filtre complexes, de réaliser des mises à jour ou suppressions groupées fondées sur des filtres, ou de dépasser la limite de résultats de la recherche vectorielle native de Convex.