> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # Memory.cloneThread() `.cloneThread()` 方法會建立現有對話 thread 的副本,並包含其中所有訊息。它支援從對話中的指定位置建立不同的對話路徑。啟用 semantic recall 時,此方法亦會為 cloned message 建立 vector embedding。 ## 使用範例 以下範例會建立 `Memory` instance,並 clone 現有 thread。 ```typescript import { Memory } from '@mastra/memory' import { LibSQLStore } from '@mastra/libsql' const memory = new Memory({ storage: new LibSQLStore({ id: 'memory-store', url: 'file:./memory.db' }), }) const { thread, clonedMessages } = await memory.cloneThread({ sourceThreadId: 'original-thread-123', }) ``` ## 參數 **sourceThreadId** (`string`): 要 clone 的 thread ID **newThreadId** (`string`): Cloned thread 的選用自訂 ID。如未提供,系統會自動產生。 **resourceId** (`string`): Cloned thread 的選用 resource ID。預設為 source thread 的 resourceId。 **title** (`string`): Cloned thread 的選用標題。如省略,而 source thread 有標題,clone 便會使用 Clone of ${sourceThread.title};否則標題為空白。 **metadata** (`Record`): 要與 source thread metadata 合併的選用 metadata。系統會自動加入 clone metadata。 **options** (`CloneOptions`): Clone 操作的選用篩選條件。 **options.messageLimit** (`number`): 要 clone 的訊息數目上限。設定後,會 clone 最新的 N 則訊息。 **options.messageFilter** (`MessageFilter`): 用於選擇要 clone 哪些訊息的篩選條件。 **options.messageFilter.startDate** (`Date`): 只 clone 在此日期或之後建立的訊息。 **options.messageFilter.endDate** (`Date`): 只 clone 在此日期或之前建立的訊息。 **options.messageFilter.messageIds** (`string[]`): 只 clone 具有這些指定 ID 的訊息。 ## 傳回值 **thread** (`StorageThreadType`): 新建立並附有 clone metadata 的 cloned thread。 **clonedMessages** (`MastraDBMessage[]`): 已指派新 ID 並歸入新 thread 的 cloned message 陣列。 **messageIdMap** (`Record`): Source message ID 與其對應 cloned message ID 之間的映射。 ### Clone metadata Cloned thread 的 metadata 包含一個 `clone` property,其中包括: **sourceThreadId** (`string`): 被 clone 的原始 thread ID。 **clonedAt** (`Date`): 建立 clone 時的時間戳記。 **lastMessageId** (`string`): Clone 當刻 source thread 中最後一則訊息的 ID。 ## 進階使用範例 ```typescript import { mastra } from './mastra' const agent = mastra.getAgent('agent') const memory = await agent.getMemory() // Clone a thread with all messages const { thread: fullClone } = await memory.cloneThread({ sourceThreadId: 'original-thread-123', title: 'Alternative Conversation Path', }) // Clone with a custom ID const { thread: customIdClone } = await memory.cloneThread({ sourceThreadId: 'original-thread-123', newThreadId: 'my-custom-clone-id', }) // Clone only the last 5 messages const { thread: partialClone, clonedMessages } = await memory.cloneThread({ sourceThreadId: 'original-thread-123', options: { messageLimit: 5, }, }) // Clone messages from a specific date range const { thread: dateFilteredClone } = await memory.cloneThread({ sourceThreadId: 'original-thread-123', options: { messageFilter: { startDate: new Date('2024-01-01'), endDate: new Date('2024-01-31'), }, }, }) // Clone specific messages const { thread: selectedMessagesClone } = await memory.cloneThread({ sourceThreadId: 'original-thread-123', options: { messageFilter: { messageIds: ['message-1', 'message-2'], }, }, }) // Continue conversation on the cloned thread const response = await agent.generate('Try a different approach', { memory: { thread: fullClone.id, resource: fullClone.resourceId, }, }) ``` 將 cloned `thread.id` 及 `thread.resourceId` 傳給 `agent.generate()`,即可從 cloned thread 繼續對話。 ## Vector embedding 當 Memory instance 已啟用 semantic recall,並已設定 vector store 及 embedder 時,`cloneThread()` 會自動為所有 cloned message 建立 vector embedding,確保語意搜尋可在 cloned thread 上正常運作。 在此範例中,`embeddingModel` 是項目所設定的 embedding model。 ```typescript import { Memory } from '@mastra/memory' import { LibSQLStore, LibSQLVector } from '@mastra/libsql' const memory = new Memory({ storage: new LibSQLStore({ id: 'memory-store', url: 'file:./memory.db' }), vector: new LibSQLVector({ id: 'vector-store', url: 'file:./vector.db' }), embedder: embeddingModel, options: { semanticRecall: true, }, }) // Clone will also create embeddings for cloned messages const { thread } = await memory.cloneThread({ sourceThreadId: 'original-thread', }) // Semantic search works on the cloned thread const results = await memory.recall({ threadId: thread.id, vectorSearchString: 'search query', }) ``` ## Working memory 啟用 working memory 後,`cloneThread()` 會根據 working memory scope 及 clone 的 `resourceId` 複製或共用 working memory: - **Thread scope 的 working memory**:Working memory 會複製至 cloned thread。 - **Resource scope 的 working memory,且 `resourceId` 相同**:由於 source thread 與 cloned thread 屬於同一個 resource,因此會共用 working memory。 - **Resource scope 的 working memory,且 `resourceId` 不同**:Working memory 會複製至 cloned thread 的 resource。 ## Observational Memory 啟用 [Observational Memory](https://mastra.zisheng.pro/zh-HK/docs/memory/observational-memory) 後,`cloneThread()` 會自動 clone 與 source thread 相關的 OM 記錄。其行為視乎 OM scope: - **Thread scope 的 OM**:OM 記錄會 clone 至新 thread。所有內部訊息 ID 參照都會重新映射至 cloned message。 - **Resource scope 的 OM(`resourceId` 相同)**:由於 source thread 與 cloned thread 屬於同一個 resource,因此會共用 OM 記錄,不會建立副本。 - **Resource scope 的 OM(`resourceId` 不同)**:OM 記錄會 clone 至新 resource。訊息 ID 會重新映射,而 observation 中所有用於識別 thread 的 tag 都會更新為參照 cloned thread。 只會 clone 目前(最新)的 OM generation,不會複製較舊的歷史 generation。暫時性處理狀態(observation/reflection 進行中 flag)會在 cloned record 上重設。