> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # MongoDB 向量儲存 `MongoDBVector` 類別使用 [MongoDB Atlas Vector Search](https://www.mongodb.com/docs/atlas/atlas-vector-search/) 提供向量搜尋。它可在 MongoDB 集合中進行高效率的相似度搜尋與中繼資料篩選。 ## 安裝 **npm**: ```bash npm install @mastra/mongodb@latest ``` **pnpm**: ```bash pnpm add @mastra/mongodb@latest ``` **Yarn**: ```bash yarn add @mastra/mongodb@latest ``` **Bun**: ```bash bun add @mastra/mongodb@latest ``` ## 使用範例 ```typescript import { MongoDBVector } from '@mastra/mongodb' const store = new MongoDBVector({ id: 'mongodb-vector', uri: process.env.MONGODB_URI, dbName: process.env.MONGODB_DB_NAME, }) ``` ### 自訂嵌入欄位路徑 如果需要將嵌入儲存在巢狀欄位結構中(例如整合現有的 MongoDB 集合),請使用 `embeddingFieldPath` 選項: ```typescript import { MongoDBVector } from '@mastra/mongodb' const store = new MongoDBVector({ id: 'mongodb-vector', uri: process.env.MONGODB_URI, dbName: process.env.MONGODB_DB_NAME, embeddingFieldPath: 'text.contentEmbedding', // Store embeddings at text.contentEmbedding }) ``` ## 建構函式選項 **id** (`string`): 此向量儲存執行個體的不重複識別碼 **uri** (`string`): MongoDB 連線字串 **dbName** (`string`): 要使用的 MongoDB 資料庫名稱 **options** (`MongoClientOptions`): 選用的 MongoDB 使用者端選項 **embeddingFieldPath** (`string`): 儲存向量嵌入的欄位路徑。支援使用點號標記法的巢狀路徑(例如 'text.contentEmbedding')。 (Default: `embedding`) ## 方法 ### `connect()` 建立與 MongoDB 伺服器的連線。首次使用時會自動呼叫此方法,但也可視需要明確呼叫。 ```typescript await store.connect() ``` ### `createIndex()` 在 MongoDB 中建立新的向量索引(集合)。 **indexName** (`string`): 要建立的集合名稱 **dimension** (`number`): 向量維度(必須與嵌入模型相符) **metric** (`'cosine' | 'euclidean' | 'dotproduct'`): 相似度搜尋使用的距離度量 (Default: `cosine`) **filterFields** (`string[]`): 要在 Atlas vectorSearch 索引中宣告為篩選欄位的中繼資料欄位名稱(註冊為 metadata.\)。只篩選已宣告欄位的查詢會直接下推至 $vectorSearch,而不會預先篩選候選 \_id,藉此避免大型結果集的 16 MB BSON 限制。若篩選條件參照未宣告的欄位,或使用 $vectorSearch 不支援的運算子,則會自動改用預先篩選。 **collectionName** (`string`): 將向量儲存在現有的作業集合中,而非使用以索引命名的受管理集合。設定此選項後,此儲存絕不會建立或移除該集合。預設為 indexName。 **searchIndexName** (`string`): 在集合上建立的 Atlas vectorSearch 索引名稱。預設為 ${indexName}\_vector\_index。 **allowWrites** (`boolean`): 選擇允許對自備集合執行寫入操作(upsert、updateVector、deleteVector、deleteVectors)。BYO 索引預設為唯讀:此儲存絕不會修改或刪除呼叫端擁有的作業文件。受管理集合一律可寫入,因此會忽略此選項。此原則會隨索引註冊持久保存,重新啟動後仍然有效。 (Default: `false`) ### `waitForIndexReady()` 等待建立後的索引進入就緒狀態。需要在執行操作前確保索引已就緒時很實用。 **indexName** (`string`): 要等待的索引名稱 **timeoutMs** (`number`): 最長等待時間,單位為毫秒 (Default: `60000`) **checkIntervalMs** (`number`): 狀態檢查間隔,單位為毫秒 (Default: `2000`) ### `upsert()` 在集合中新增或更新向量及其中繼資料。BYO 集合預設為唯讀,因此若使用自備索引,必須在呼叫 `createIndex()` 時設定 `allowWrites: true`。 **indexName** (`string`): 要插入資料的集合名稱 **vectors** (`number[][]`): 嵌入向量陣列 **metadata** (`Record[]`): 每個向量的中繼資料 **ids** (`string[]`): 選用的向量 ID(未提供時會自動產生) **documents** (`string[]`): 選用的文件文字內容,與向量一併儲存 ### `query()` 搜尋相似向量,並可選擇套用中繼資料篩選。 **indexName** (`string`): 要搜尋的集合名稱 **queryVector** (`number[]`): 用於尋找相似向量的查詢向量 **topK** (`number`): 要傳回的結果數量 (Default: `10`) **filter** (`Record`): 中繼資料篩選條件(套用至 metadata 欄位) **documentFilter** (`Record`): 針對原始文件欄位的篩選條件(不限於中繼資料) **includeVector** (`boolean`): 結果是否包含向量資料 (Default: `false`) **numCandidates** (`number`): HNSW 圖形在選出 top-K 結果前納入考量的候選項目數量。較高的值可提高召回率,但會增加延遲。請參閱:https\://www\.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/ (Default: `20 * topK (capped at 10000)`) **metadataMode** (`'field' | 'document'`): 'field'(預設)會投影受管理的 metadata/document 欄位,並將 filter 欄位與 metadata 子文件比對。'document' 會以 metadata 傳回完整來源文件,適用於文件具有自有結構的自備作業集合;此時 filter 欄位會與\*\*根層級\*\*文件比對(不加 metadata. 前綴)。預設會從 metadata 省略嵌入欄位,以免承載資料過大;設定 includeVector: true 可將它保留在 metadata 中,並同時公開為頂層 vector。 (Default: `field`) ### `createSearchIndex()` 在索引背後的集合上佈建 Atlas Search(BM25/全文)索引,並將其記錄為 `textQuery()` 與 `hybridQuery()` 的目標文字搜尋索引。 **受管理集合與自備集合:** - 對於**受管理**索引(建立時未提供 `collectionName`),`createIndex()` 已會佈建名為 `${collectionName}_search_index` 的\_動態\_全文索引(涵蓋所有字串欄位)。因此,只有需要**限制欄位**的對應或**自訂索引名稱**時,才需要使用 `createSearchIndex()`。 - 對於**自備**索引(建立時提供 `collectionName`),`createIndex()` 不會自動建立任何全文索引。在呼叫端擁有的作業集合上啟用 `textQuery()`/`hybridQuery()` 是選擇性功能。請明確呼叫 `createSearchIndex()` 來佈建(需付費的)文字索引。在此之前,`textQuery()`/`hybridQuery()` 會擲回明確錯誤,而不會查詢不存在的索引。 命名: - 提供 `fields` 但**未**明確提供 `searchIndexName` 時,欄位對應索引會使用**不同的**預設名稱(`${collectionName}_${indexName}_search_fields_index`,每個邏輯索引都不重複),以免與受管理集合自動建立的動態索引衝突而遭到默默忽略。這個獨立索引會持久保存為文字搜尋索引,因此 `textQuery()`/`hybridQuery()` 會自動使用受限的對應。 - 提供 `searchIndexName` 時,會使用並持久保存該確切名稱。`textQuery()`/`hybridQuery()` 會自動解析已保存的名稱。你也可以透過各方法的 `searchIndexName`/`textSearchIndexName` 參數,在每次呼叫時覆寫名稱。 **indexName** (`string`): 其集合要建立搜尋索引的 Mastra 索引名稱 **fields** (`string[]`): 全文搜尋要建立索引的欄位名稱。省略時使用動態對應(所有字串欄位)。 **searchIndexName** (`string`): Atlas Search 索引名稱。提供 fields 且省略此值時,會使用每個邏輯索引都不重複的獨立預設名稱,因此欄位對應不會被自動建立的動態索引遮蔽,同一集合上的兩個邏輯索引也不會衝突。 (Default: ``${collectionName}_search_index(提供 `fields` 時則為 ${collectionName}_${indexName}_search_fields_index)``) **waitUntilReady** (`boolean`): 設為 true 時,會阻塞到已佈建的全文索引回報 READY 後才完成。預設為 false,以避免非預期延遲;若偏好分開等待,請明確呼叫 waitForSearchIndexReady()。 (Default: `false`) ```typescript await store.createSearchIndex({ indexName: 'precedents', fields: ['note', 'description'], }) ``` 欄位對應索引名稱包含邏輯 `indexName`,因此同一集合上的兩個邏輯索引會有不同的文字索引。若要使用不同 `fields` 重新建立\_同一個\_邏輯索引,仍須先移除現有索引(`IndexAlreadyExists`)。 ### `waitForSearchIndexReady()` 等待索引的全文(BM25)搜尋索引進入 READY 狀態。`waitForIndexReady()` 只會輪詢 vectorSearch 索引;`createSearchIndex()` 會在 Atlas Search 全文索引仍在建置時傳回,因此立即呼叫 `textQuery()`/`hybridQuery()` 可能偶爾失敗。請呼叫此方法(或將 `waitUntilReady: true` 傳給 `createSearchIndex()`),阻塞到解析出的文字索引回報 READY。 **indexName** (`string`): 其文字索引要等待的索引邏輯名稱 **searchIndexName** (`string`): 覆寫解析出的文字搜尋索引名稱 **timeoutMs** (`number`): 最長等待時間,單位為毫秒 (Default: `60000`) **checkIntervalMs** (`number`): 狀態檢查間隔,單位為毫秒 (Default: `2000`) ```typescript await store.createSearchIndex({ indexName: 'precedents', fields: ['note'] }) await store.waitForSearchIndexReady({ indexName: 'precedents' }) ``` ### `textQuery()` 對 Atlas Search 索引執行全文(BM25)搜尋。預設會以此索引所記錄的文字搜尋索引為目標(由 `createSearchIndex()` 設定,或由 `createIndex()` 自動建立的動態 `${collectionName}_search_index`)。傳入 `searchIndexName` 可讓本次呼叫以特定索引為目標。 此處的中繼資料篩選條件(如同 `hybridQuery()`)會透過 `$match` 階段套用。對於 `hybridQuery()` 的向量分支,在建立索引時未透過 `filterFields` 宣告的欄位篩選條件,會透明地具體化為候選 `_id`(與 `query()` 使用相同的後援機制),因此未宣告欄位的篩選條件不會發生錯誤。 **indexName** (`string`): 要搜尋的 Mastra 索引名稱 **query** (`string`): 全文搜尋查詢字串 **paths** (`string[]`): 要搜尋的欄位路徑(例如 \["note", "description"]) **topK** (`number`): 要傳回的結果數量 (Default: `10`) **filter** (`Record`): 中繼資料篩選條件(套用至 metadata 欄位) **metadataMode** (`'field' | 'document'`): 'field'(預設)會投影受管理的 metadata/document 欄位。'document' 會以 metadata 傳回完整來源文件。 (Default: `field`) **searchIndexName** (`string`): 覆寫本次呼叫所解析出的全文搜尋索引名稱。預設為 createSearchIndex()/createIndex() 持久保存的索引。 ```typescript const results = await store.textQuery({ indexName: 'precedents', query: 'shell company offshore', paths: ['note'], topK: 10, }) ``` ### `hybridQuery()` 使用 MongoDB 伺服器端的 `$rankFusion` 融合向量相似度與全文搜尋結果,執行混合搜尋。此功能需要 MongoDB 8.0 以上版本,並自 8.1 起正式提供。在 8.0.x 上可能需要向 MongoDB 支援團隊提出申請才能啟用,並可在已啟用的環境中執行,例如 Atlas 8.0.x。全文搜尋索引必須存在:受管理索引會自動建立;自備集合則必須先呼叫 `createSearchIndex()`(選擇啟用)。 **indexName** (`string`): 要搜尋的 Mastra 索引名稱 **queryVector** (`number[]`): 相似度搜尋使用的查詢向量 **query** (`string`): 全文搜尋查詢字串 **paths** (`string[]`): 全文搜尋使用的欄位路徑(例如 \["note", "description"]) **topK** (`number`): 要傳回的結果數量 (Default: `10`) **filter** (`Record`): 中繼資料篩選條件(同時套用至向量與文字分支) **weights** (`{ vector?: number; text?: number }`): 融合時向量結果與文字結果的相對權重(預設:1:1) **numCandidates** (`number`): 向量搜尋分支的候選項目數量 (Default: `20 * topK (capped at 10000)`) **metadataMode** (`'field' | 'document'`): 'field'(預設)會投影受管理的 metadata/document 欄位。'document' 會以 metadata 傳回完整來源文件。 (Default: `field`) **textSearchIndexName** (`string`): 覆寫本次呼叫所解析出的全文搜尋索引名稱。預設為 createSearchIndex()/createIndex() 持久保存的索引。 ```typescript const results = await store.hybridQuery({ indexName: 'precedents', queryVector: embedding, query: 'shell company offshore', paths: ['note'], topK: 10, weights: { vector: 1, text: 1.5 }, // Favor text matches }) ``` `hybridQuery()` 的 `$rankFusion` 階段需要 MongoDB 8.0 以上版本。此階段自 8.1 起正式提供。在 8.0.x 上可能需要向 MongoDB 支援團隊提出申請才能啟用,並可在 Atlas 8.0.x 等已啟用的環境中執行。如果使用較舊版本,或 8.0.x 部署未啟用 `$rankFusion`,請分別使用 `query()` 和 `textQuery()`,再於使用者端合併結果。 ### `describeIndex()` 傳回索引(集合)的相關資訊。 **indexName** (`string`): 要描述的集合名稱 傳回: ```typescript interface IndexStats { dimension: number count: number metric: 'cosine' | 'euclidean' | 'dotproduct' } ``` ### `deleteIndex()` 刪除向量索引。行為取決於索引的建立方式: - **受管理索引**(建立時未提供 `collectionName`):移除整個集合及其中所有資料。 - **自備索引**(建立時提供 `collectionName`):移除 Atlas vectorSearch 索引,以及透過 `createSearchIndex()` 佈建的配套全文搜尋索引(若有)。呼叫端的作業集合及其中的文件會保留。此儲存絕不會移除非由它建立的集合。 建立索引時會持久記錄 BYO 分類,因此即使由不同處理程序操作,也能正確套用(例如由設定工作建立索引,之後再由長期執行的服務刪除)。請一律傳入**邏輯索引名稱**(呼叫 `createIndex` 時使用的 `indexName`),而不是實體集合名稱。 **indexName** (`string`): 要刪除的索引邏輯名稱 ### `listIndexes()` 列出 Mastra 的**邏輯**索引名稱(傳給 `createIndex` 的 `indexName` 值),而不是實體集合名稱。對於資料位於作業集合中的自備索引,會傳回邏輯索引名稱,而非實體集合名稱。此值可直接傳給 `deleteIndex()`/`describeIndex()`。在引入持久中繼資料前建立的受管理索引,仍可透過其 `${name}_vector_index` 搜尋索引找到。內部登錄集合絕不會列出。 傳回:`Promise` ### `updateVector()` 依 ID 或中繼資料篩選條件更新單一向量。必須提供 `id` 或 `filter` 其中一項,但不能同時提供兩者。 > \*\*自備集合預設為唯讀。\*\*除非 BYO 索引建立時設定了 `allowWrites: true`,否則 `upsert()`、`updateVector()`、`deleteVector()` 和 `deleteVectors()` 會擲回 USER 類別錯誤。請參閱[為現有集合建立索引](#indexing-an-existing-collection)。 **indexName** (`string`): 包含該向量的集合名稱 **id** (`string`): 要更新的向量項目 ID(不可與 filter 同時使用) **filter** (`Record`): 用於識別待更新向量的中繼資料篩選條件(不可與 id 同時使用) **update** (`object`): 包含向量及/或中繼資料的更新資料 **update.vector** (`number[]`): 要更新的新向量資料 **update.metadata** (`Record`): 要更新的新中繼資料 ### `deleteVector()` 依 ID 從索引中刪除指定的向量項目。 **indexName** (`string`): 包含該向量的集合名稱 **id** (`string`): 要刪除的向量項目 ID ### `deleteVectors()` 依 ID 或中繼資料篩選條件刪除多個向量。必須提供 `ids` 或 `filter` 其中一項,但不能同時提供兩者。 **indexName** (`string`): 包含待刪除向量的集合名稱 **ids** (`string[]`): 要刪除的向量 ID 陣列(不可與 filter 同時使用) **filter** (`Record`): 用於識別待刪除向量的中繼資料篩選條件(不可與 ids 同時使用) ### `disconnect()` 關閉 MongoDB 使用者端連線。向量儲存使用完畢後應呼叫此方法。 ## 回應型別 查詢結果會以下列格式傳回: ```typescript interface QueryResult { id: string score: number metadata: Record vector?: number[] // Only included if includeVector is true } ``` ## 錯誤處理 此儲存會擲回可攔截的具型別錯誤: ```typescript try { await store.query({ indexName: 'my_collection', queryVector: queryVector, }) } catch (error) { // Handle specific error cases if (error.message.includes('Invalid collection name')) { console.error( 'Collection name must start with a letter or underscore and contain only valid characters.', ) } else if (error.message.includes('Collection not found')) { console.error('The specified collection does not exist') } else { console.error('Vector store error:', error.message) } } ``` ## 為現有集合建立索引 你可以在現有作業集合上建立向量索引,而不使用受管理集合。若要為 MongoDB 資料庫中的現有文件新增向量搜尋功能,此方式很實用。 ```typescript import { MongoDBVector } from '@mastra/mongodb' const store = new MongoDBVector({ id: 'mongodb-vector', uri: process.env.MONGODB_URI, dbName: process.env.MONGODB_DB_NAME, }) // Create a vector index on an existing 'transactions' collection await store.createIndex({ indexName: 'precedents', dimension: 1024, collectionName: 'transactions', // Use existing collection searchIndexName: 'txn_vec_idx', // Custom search index name }) // Wait for the index to be ready await store.waitForIndexReady({ indexName: 'precedents' }) // Query using document mode to get full source documents const hits = await store.query({ indexName: 'precedents', queryVector: embeddings, topK: 5, metadataMode: 'document', // Returns full document as metadata }) // hits[0].metadata now contains all fields from the source document console.log(hits[0].metadata.amount, hits[0].metadata.customField) // Full-text / hybrid search on a BYO collection is opt-in: provision the text index first. await store.createSearchIndex({ indexName: 'precedents', fields: ['note'] }) ``` **重要注意事項:** - 集合必須已存在,且包含具 `embedding` 欄位(或你設定的自訂 `embeddingFieldPath`)的文件 - 使用 `collectionName` 時,絕不會建立或移除集合 - **BYO 索引預設為唯讀。**`upsert()`、`updateVector()`、`deleteVector()` 和 `deleteVectors()` 會擲回明確錯誤,而不會變更呼叫端擁有的作業文件。若要允許此儲存將嵌入寫入集合(或從集合刪除文件),請透過 `createIndex({ ..., allowWrites: true })` 明確選擇啟用。此原則會持久保存,重新啟動後仍然有效。舊版在沒有此旗標時寫入的項目會視為唯讀(預設拒絕)。 - 查詢時使用 `metadataMode: 'document'`,以 `metadata` 取得完整來源文件 - 在 `'document'` 模式下,預設會從 `metadata` 省略嵌入;傳入 `includeVector: true` 可保留嵌入(並同時公開為頂層 `vector`) - **`'document'` 模式的篩選會對根層級文件欄位操作**,而非巢狀 `metadata.` 子文件。`filter: { lane: 'fraud' }` 會比對作業文件的頂層 `lane` 欄位(在預設 `'field'` 模式中,受管理集合的裸欄位會重寫為 `metadata.`)。下推與 `$match` 後援路徑都會遵守此行為。 - \*\*支援原生 `ObjectId` `_id`。\*\*作業集合通常以 `ObjectId` 作為鍵;查詢結果會將 `_id` 強制轉換為字串(符合 `QueryResult.id` 契約),而 `deleteVector()`/`updateVector()`/`deleteVectors()` 接受該字串,並比對底層的 `ObjectId` 文件。受管理集合(字串 `_id`)不受影響。 - BYO 集合上的全文與混合搜尋是**選擇啟用**的功能:不會自動建立全文索引,因此請在 `textQuery()`/`hybridQuery()` 前呼叫 `createSearchIndex()`。全文索引會以非同步方式建置。若要立即進行文字/混合查詢,請先呼叫 `waitForSearchIndexReady()`(或傳入 `waitUntilReady: true`)。 - BYO 索引上的 `deleteIndex()` 會移除向量索引(以及已建立的文字索引),但會**保留**集合及其中的文件 ## 最佳實務 - 為篩選條件使用的中繼資料欄位建立索引,以取得最佳查詢效能。 - 在中繼資料中使用一致的欄位命名,以避免非預期的查詢結果。 - 定期監控索引與集合的統計資料,以確保搜尋效率。 - 為現有集合建立索引時,請確保所有文件都有必要的 `embedding` 欄位。 ## 使用範例 ### 使用 `MongoDB` 的向量嵌入 嵌入是記憶體的 `semanticRecall` 用來依語意(而非關鍵字)擷取相關訊息的數值向量。 > **備註:** 正式環境建議使用 MongoDB Atlas Vector Search。自行託管的部署可透過 [Atlas CLI 的本機 Atlas 部署](https://www.mongodb.com/docs/atlas/cli/current/atlas-cli-deploy-local/)使用 Vector Search。 此設定使用本機嵌入模型 FastEmbed 產生向量嵌入。 若要使用,請安裝 `@mastra/fastembed`: **npm**: ```bash npm install @mastra/fastembed@latest ``` **pnpm**: ```bash pnpm add @mastra/fastembed@latest ``` **Yarn**: ```bash yarn add @mastra/fastembed@latest ``` **Bun**: ```bash bun add @mastra/fastembed@latest ``` 將下列內容新增至你的 Agent: ```typescript import { Memory } from '@mastra/memory' import { Agent } from '@mastra/core/agent' import { MongoDBStore, MongoDBVector } from '@mastra/mongodb' import { fastembed } from '@mastra/fastembed' export const mongodbAgent = new Agent({ id: 'mongodb-agent', name: 'mongodb-agent', instructions: 'You are an AI agent with the ability to automatically recall memories from previous interactions.', model: 'openai/gpt-5.6-sol', memory: new Memory({ storage: new MongoDBStore({ id: 'mongodb-storage', uri: process.env.MONGODB_URI!, dbName: process.env.MONGODB_DB_NAME!, }), vector: new MongoDBVector({ id: 'mongodb-vector', uri: process.env.MONGODB_URI!, dbName: process.env.MONGODB_DB_NAME!, }), embedder: fastembed, options: { lastMessages: 10, semanticRecall: { topK: 3, messageRange: 2, }, generateTitle: true, // generates descriptive thread titles automatically }, }), }) ``` ### 使用 VoyageAI 的向量嵌入 VoyageAI 提供針對擷取工作最佳化的專用嵌入模型。VoyageAI 也與 MongoDB Atlas 整合,可提供多模態嵌入。 **npm**: ```bash npm install @mastra/voyageai@latest ``` **pnpm**: ```bash pnpm add @mastra/voyageai@latest ``` **Yarn**: ```bash yarn add @mastra/voyageai@latest ``` **Bun**: ```bash bun add @mastra/voyageai@latest ``` 基本使用範例: ```typescript import { Memory } from '@mastra/memory' import { Agent } from '@mastra/core/agent' import { MongoDBStore, MongoDBVector } from '@mastra/mongodb' import { voyage } from '@mastra/voyageai' export const mongodbVoyageAgent = new Agent({ id: 'mongodb-voyage-agent', name: 'MongoDB VoyageAI Agent', instructions: 'You are an AI agent with semantic recall powered by VoyageAI and MongoDB.', model: 'openai/gpt-5.6-sol', memory: new Memory({ storage: new MongoDBStore({ id: 'mongodb-storage', uri: process.env.MONGODB_URI!, dbName: process.env.MONGODB_DB_NAME!, }), vector: new MongoDBVector({ id: 'mongodb-vector', uri: process.env.MONGODB_URI!, dbName: process.env.MONGODB_DB_NAME!, }), embedder: voyage, // VoyageAI's default model (voyage-3.5, 1024 dimensions) options: { lastMessages: 10, semanticRecall: { topK: 5, messageRange: 2, }, }, }), }) ``` 如需包含專用模型、多模態嵌入與擷取最佳化的詳細 VoyageAI 嵌入範例,請參閱 [VoyageAI 嵌入文件](https://mastra.zisheng.pro/zh-TW/models/embeddings)。 ## 相關內容 - [中繼資料篩選條件](https://mastra.zisheng.pro/zh-TW/reference/rag/metadata-filters) - [VoyageAI 嵌入文件](https://mastra.zisheng.pro/zh-TW/models/embeddings)