跳至主要內容

Convex 向量儲存

ConvexVector 類別使用 Convex 提供向量儲存及相似度搜尋。它在 Convex 內儲存嵌入向量,並在 Mastra adapter 中執行餘弦相似度搜尋。

開發規模搜尋

ConvexVector 透過 Mastra 儲存處理器讀取相符的向量、在 JavaScript 中篩選、計算餘弦相似度、排序結果,然後傳回最相符的結果。適合用於本機開發、測試及小型資料集。

如要在 Convex 上進行生產環境向量搜尋,請使用 ConvexNativeVector。它會使用 Convex 原生 vectorSearch API,而此 API 需要已部署的 Convex 向量索引及 Convex action。

安裝
安裝 的直接連結

npm install @mastra/convex@latest

Convex 設定
Convex 設定 的直接連結

使用 ConvexVector 前,你需要設定 Convex schema 及儲存處理器。設定指示請參閱 Convex 儲存設定

建構函式選項
建構函式選項 的直接連結

deploymentUrl:

string
Convex 部署 URL(例如 https://your-project.convex.cloud)

adminAuthToken:

string
Convex 管理員驗證 token

storageFunction?:

string
= mastra/storage:handle
儲存 mutation 函式的路徑

建構函式範例
建構函式範例 的直接連結

基本設定
基本設定 的直接連結

import { ConvexVector } from '@mastra/convex'

const vectorStore = new ConvexVector({
id: 'convex-vectors',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
})

生產環境的向量工作負載請使用 ConvexNativeVector。它會將向量儲存在專用的 Convex 資料表中,並查詢在 schema 中定義的 Convex 向量索引。

convex/schema.ts 中,為每個 Mastra 向量索引定義專用資料表:

convex/schema.ts
import { defineSchema } from 'convex/server'
import { defineMastraNativeVectorTable } from '@mastra/convex/schema'

export default defineSchema({
docs_vectors: defineMastraNativeVectorTable({
dimensions: 1536,
}),
})

convex/mastra/nativeVector.ts 中,匯出原生向量處理器:

convex/mastra/nativeVector.ts
import {
mastraNativeVectorAction,
mastraNativeVectorMutation,
mastraNativeVectorQuery,
} from '@mastra/convex/server'

export const query = mastraNativeVectorAction
export const read = mastraNativeVectorQuery
export const write = mastraNativeVectorMutation

在你的 Mastra 應用程式中,使用已部署的資料表及向量索引設定 ConvexNativeVector

src/mastra/index.ts
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,
})

如要支援原生篩選器,請在 Convex schema 中宣告篩選欄位。寫入向量時,原生向量處理器會將相符的中繼資料欄位複製至文件的頂層欄位。

convex/schema.ts
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'],
}),
})
src/mastra/index.ts
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 支援 Convex 原生向量篩選器格式:一個相等欄位,或由多個相等欄位組成的 $or。它不支援僅限中繼資料的查詢、基於篩選器的更新,亦不支援基於篩選器的刪除。更新及刪除時請使用向量 ID。

自訂儲存函式
自訂儲存函式 的直接連結

const vectorStore = new ConvexVector({
id: 'convex-vectors',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
storageFunction: 'custom/path:handler',
})

方法
方法 的直接連結

createIndex()
createindex 的直接連結

indexName:

string
要建立的索引名稱

dimension:

number
向量維度(必須與嵌入模型相符)

metric?:

'cosine' | 'euclidean' | 'dotproduct'
= cosine
相似度搜尋所使用的距離度量(目前只支援餘弦距離)
await vectorStore.createIndex({
indexName: 'my_vectors',
dimension: 1536,
})

upsert()
upsert 的直接連結

indexName:

string
要 upsert 向量的索引名稱

vectors:

number[][]
嵌入向量陣列

metadata?:

Record<string, any>[]
每個向量的中繼資料

ids?:

string[]
可選的向量 ID(如未提供則自動產生)
await vectorStore.upsert({
indexName: "my_vectors",
vectors: [[0.1, 0.2, 0.3, ...]],
metadata: [{ label: "example" }],
ids: ["vec-1"],
});

query()
query 的直接連結

indexName:

string
要查詢的索引名稱

queryVector:

number[]
查詢向量

topK?:

number
= 10
要傳回的結果數目

filter?:

Record<string, any>
中繼資料篩選器

includeVector?:

boolean
= false
是否在結果中包括向量
const results = await vectorStore.query({
indexName: "my_vectors",
queryVector: [0.1, 0.2, 0.3, ...],
topK: 5,
filter: { category: "documents" },
});

listIndexes()
listindexes 的直接連結

傳回由索引名稱字串組成的陣列。

const indexes = await vectorStore.listIndexes()
// ["my_vectors", "embeddings", ...]

describeIndex()
describeindex 的直接連結

indexName:

string
要描述的索引名稱

傳回:

interface IndexStats {
dimension: number
count: number
metric: 'cosine' | 'euclidean' | 'dotproduct'
}

deleteIndex()
deleteindex 的直接連結

indexName:

string
要刪除的索引名稱

刪除索引及其中所有向量。

await vectorStore.deleteIndex({ indexName: 'my_vectors' })

updateVector()
updatevector 的直接連結

按 ID 或中繼資料篩選器更新單一向量。必須提供 idfilter 其中之一,但不可同時提供。

indexName:

string
包含該向量的索引名稱

id?:

string
要更新的向量 ID(與 filter 互斥)

filter?:

Record<string, any>
用來識別要更新向量的中繼資料篩選器(與 id 互斥)

update:

{ vector?: number[]; metadata?: Record<string, any>; }
包含要更新之向量及/或中繼資料的物件
// 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()
deletevector 的直接連結

indexName:

string
包含該向量的索引名稱

id:

string
要刪除的向量 ID
await vectorStore.deleteVector({ indexName: 'my_vectors', id: 'vector123' })

deleteVectors()
deletevectors 的直接連結

按 ID 或中繼資料篩選器刪除多個向量。必須提供 idsfilter 其中之一,但不可同時提供。

indexName:

string
包含這些向量的索引名稱

ids?:

string[]
要刪除的向量 ID 陣列(與 filter 互斥)

filter?:

Record<string, any>
用來識別要刪除向量的中繼資料篩選器(與 ids 互斥)
// 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' },
})

回應類型
回應類型 的直接連結

查詢結果會以下列格式傳回:

interface QueryResult {
id: string
score: number
metadata: Record<string, any>
vector?: number[] // Only included if includeVector is true
}

中繼資料篩選
中繼資料篩選 的直接連結

ConvexVector 支援使用運算子的中繼資料篩選。從 Convex 載入向量後,adapter 會套用這些篩選器。

// 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 } }],
},
})

支援的篩選運算子
支援的篩選運算子 的直接連結

運算子說明
$eq等於
$ne不等於
$gt大於
$gte大於或等於
$lt小於
$lte小於或等於
$in在陣列中
$nin不在陣列中
$and邏輯 AND
$or邏輯 OR

架構
架構 的直接連結

ConvexVector 按以下結構將向量儲存在 mastra_vectors 資料表中:

  • id:唯一向量標識符
  • indexName:索引名稱
  • embedding:向量資料(浮點數陣列)
  • metadata:可選的 JSON 中繼資料

向量相似度搜尋會在 Mastra adapter 中使用餘弦相似度執行。這種方式可讓設定保持靈活,但並非為大型生產環境向量集合而設。

ConvexNativeVector 會將每個 Mastra 向量索引儲存在專用的 Convex 資料表中。其查詢會呼叫使用 ctx.vectorSearch 的 Convex action,然後透過 Convex query 載入相符的文件。這遵循 Convex 原生向量搜尋模型:

  • 向量索引在 convex/schema.ts 中宣告。
  • 向量搜尋從 Convex action 執行。
  • topK 必須介乎 1256
  • 篩選器必須針對 Convex 向量索引 filterFields 中列出的欄位。
  • 每個 Mastra 向量索引使用一個專用資料表,以免結果跨越不同索引。

如你需要在執行階段定義索引建立、僅限中繼資料的查詢、複雜篩選運算子、基於篩選器的批量更新或刪除,或超出 Convex 原生向量搜尋上限的結果數目,請使用外部向量資料庫。