> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # 訊息歷史 訊息歷史是最基本也最重要的 Memory 形式。它讓 LLM 能在 context window 中看到近期訊息,使 Agent 可以引用先前的交流內容並連貫地回應。 你也可以擷取訊息歷史,在 UI 中顯示過往對話。 > **資訊:** 每則訊息都屬於一個 thread(對話),以及一個 resource(與其相關聯的使用者或實體)。如需詳細資訊,請參閱 [Thread 與 resource](#threads-and-resources)。 > **警告:** 在用戶端應用程式中使用 Memory 時,用戶端**只應傳送新訊息**,不要傳送完整的對話歷史。 > > 傳送完整歷史是多餘的,因為 Mastra 會從儲存空間載入訊息;而且當用戶端時間戳記與已儲存的時間戳記衝突時,可能導致訊息順序錯誤。 > > 如需 AI SDK 範例,請參閱[使用 Mastra Memory](https://mastra.zisheng.pro/zh-TW/guides/build-your-ui/ai-sdk-ui)。 ## Thread 與 resource Mastra 使用兩個識別碼整理對話: - **Thread**:包含一系列訊息的對話工作階段。 - **Resource**:擁有該 thread 的實體,例如應用程式中的使用者、組織、專案或其他領域實體。 Studio 會自動為你產生 thread 與 resource ID。自行呼叫 `stream()` 或 `generate()` 時,請明確提供這些識別碼。 ## 開始使用 安裝 Mastra Memory 模組,以及資料庫所需的[儲存 adapter](https://mastra.zisheng.pro/zh-TW/docs/storage/overview)。以下範例使用 `@mastra/libsql`,它會將資料儲存在本機的 `mastra.db` 檔案中。 **npm**: ```bash npm install @mastra/memory@latest @mastra/libsql@latest ``` **pnpm**: ```bash pnpm add @mastra/memory@latest @mastra/libsql@latest ``` **Yarn**: ```bash yarn add @mastra/memory@latest @mastra/libsql@latest ``` **Bun**: ```bash bun add @mastra/memory@latest @mastra/libsql@latest ``` 訊息歷史需要儲存 adapter 才能保存對話。若尚未設定,請在 Mastra 執行個體上設定儲存空間: ```typescript import { Mastra } from '@mastra/core' import { LibSQLStore } from '@mastra/libsql' export const mastra = new Mastra({ storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db', }), }) ``` 在 Agent 中建立 [`Memory`](https://mastra.zisheng.pro/zh-TW/reference/memory/memory-class) 執行個體: ```typescript import { Memory } from '@mastra/memory' import { Agent } from '@mastra/core/agent' export const agent = new Agent({ id: 'test-agent', memory: new Memory({ options: { lastMessages: 10, }, }), }) ``` 呼叫 Agent 時,訊息會自動儲存至資料庫。你可以指定 `threadId`、`resourceId` 及選用的 `metadata`: **.generate()**: ```typescript await agent.generate('Hello', { memory: { thread: { id: 'thread-123', title: 'Support conversation', metadata: { category: 'billing' }, }, resource: 'user-456', }, }) ``` **.stream()**: ```typescript await agent.stream('Hello', { memory: { thread: { id: 'thread-123', title: 'Support conversation', metadata: { category: 'billing' }, }, resource: 'user-456', }, }) ``` > **資訊:** 呼叫 `agent.generate()` 或 `agent.stream()` 時,系統會自動建立 thread 與訊息;你也可以使用 [`createThread()`](https://mastra.zisheng.pro/zh-TW/reference/memory/createThread) 與 [`saveMessages()`](https://mastra.zisheng.pro/zh-TW/reference/memory/memory-class) 手動建立。 你可以透過兩種方式使用這份歷史: - **自動納入**:Mastra 會自動擷取近期訊息,並將其納入 context window。預設會納入最近 10 則訊息,讓 Agent 以對話內容為依據。你可以使用 `lastMessages` 調整數量,但多數情況下不需要特別處理。 - [**手動查詢**](#querying):若需要更多控制,請使用 `recall()` 函式直接查詢 thread 與訊息。如此便能精確選擇 context window 中要納入哪些記憶,或擷取訊息以在 UI 中呈現對話歷史。 > **提示:** 啟用 Memory 後,[Studio](https://mastra.zisheng.pro/zh-TW/docs/studio/overview) 會使用訊息歷史,在聊天側邊欄顯示過往對話。 ## 產生 thread 標題 啟用 `generateTitle` 後,Mastra 可以根據對話逐字稿自動產生描述性的 thread 標題。若你建立的聊天介面會在 thread 清單或側邊欄呈現對話標題,請使用此選項。 ```typescript import { Agent } from '@mastra/core/agent' import { Memory } from '@mastra/memory' export const supportAgent = new Agent({ id: 'support-agent', name: 'Support agent', instructions: 'Answer customer support questions.', model: 'openai/gpt-5.6-sol', memory: new Memory({ options: { generateTitle: true, }, }), }) ``` 標題會在 Agent 回應後以非同步方式產生,不會影響回應時間。 若要最佳化成本或行為,請提供較小的 [`model`](https://mastra.zisheng.pro/zh-TW/models) 與自訂 `instructions`: ```typescript import { Agent } from '@mastra/core/agent' import { Memory } from '@mastra/memory' export const supportAgent = new Agent({ id: 'support-agent', name: 'Support agent', instructions: 'Answer customer support questions.', model: 'openai/gpt-5.6-sol', memory: new Memory({ options: { generateTitle: { model: 'openai/gpt-5-mini', instructions: 'Generate a one-word title.', }, }, }), }) ``` ## 存取 Memory 若要存取 Memory 函式以查詢、複製或刪除 thread 與訊息,請對 Agent 呼叫 `getMemory()`: ```typescript const agent = mastra.getAgentById('test-agent') const memory = await agent.getMemory() ``` `Memory` 執行個體可讓你使用列出 thread、回想訊息、複製對話等函式。 ## 查詢 使用以下方法擷取 thread 與訊息,以便在 UI 中顯示對話歷史,或用於自訂 Memory 擷取邏輯。 > **警告:** Memory 系統不會強制執行存取控制。執行任何查詢前,請在應用程式邏輯中確認目前使用者有權存取要查詢的 `resourceId`。 ### Thread 使用 [`listThreads()`](https://mastra.zisheng.pro/zh-TW/reference/memory/listThreads) 擷取 resource 的 thread: ```typescript const result = await memory.listThreads({ filter: { resourceId: 'user-123' }, perPage: false, }) ``` 以分頁方式瀏覽 thread: ```typescript const result = await memory.listThreads({ filter: { resourceId: 'user-123' }, page: 0, perPage: 10, }) console.log(result.threads) // thread objects console.log(result.hasMore) // more pages available? ``` 你也可以依 metadata 篩選並控制排序順序: ```typescript const result = await memory.listThreads({ filter: { resourceId: 'user-123', metadata: { status: 'active' }, }, orderBy: { field: 'createdAt', direction: 'DESC' }, }) ``` 若要依 ID 擷取單一 thread,請使用 [`getThreadById()`](https://mastra.zisheng.pro/zh-TW/reference/memory/getThreadById): ```typescript const thread = await memory.getThreadById({ threadId: 'thread-123' }) ``` ### 訊息 取得 thread 後,請使用 [`recall()`](https://mastra.zisheng.pro/zh-TW/reference/memory/recall) 擷取其訊息。它支援分頁、日期篩選與[語意搜尋](https://mastra.zisheng.pro/zh-TW/docs/memory/semantic-recall)。 基本回想會傳回 thread 中的所有訊息: ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', perPage: false, }) ``` 以分頁方式瀏覽訊息: ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', page: 0, perPage: 50, }) ``` 依日期範圍篩選: ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', filter: { dateRange: { start: new Date('2025-01-01'), end: new Date('2025-06-01'), }, }, }) ``` 依淺層訊息 metadata 篩選: ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', filter: { metadata: { category: 'billing', escalated: true, priority: 2, archivedAt: null, }, }, }) ``` Metadata 篩選條件只會比對淺層純量值:`string`、有限的 `number`、`boolean` 與 `null`。 所有指定的 metadata key 都使用 AND 語意。`null` 篩選條件只會比對明確的 `null` 值;缺少 metadata key 時不會相符。 Metadata key 必須以字母或底線開頭,且只能包含英數字元。長度不得超過 128 個字元,也不能使用 `__proto__`、`constructor` 或 `prototype` 等保留的 prototype key。 效能取決於儲存後端。部分後端可將部分篩選條件下推至資料庫;其他後端則會先套用 thread、resource 與日期限制,再掃描候選訊息,最後才進行分頁。 依 ID 擷取單一訊息: ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', include: [{ id: 'msg-123' }], }) ``` 依 ID 擷取多則訊息及其周邊脈絡: ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', include: [ { id: 'msg-123' }, { id: 'msg-456', withPreviousMessages: 3, withNextMessages: 1, }, ], }) ``` 依語意搜尋(設定方式請參閱[語意回憶](https://mastra.zisheng.pro/zh-TW/docs/memory/semantic-recall)): ```typescript const { messages } = await memory.recall({ threadId: 'thread-123', vectorSearchString: 'project deadline discussion', threadConfig: { semanticRecall: true, }, }) ``` ### UI 格式 訊息查詢會傳回 `MastraDBMessage[]` 格式。若要在前端顯示訊息,你可能需要轉換成 UI 程式庫預期的格式。例如,[`toAISdkV5Messages`](https://mastra.zisheng.pro/zh-TW/reference/ai-sdk/to-ai-sdk-v5-messages) 可將訊息轉換為 AI SDK UI 格式。 ## 複製 thread 複製 thread 會建立現有 thread 及其訊息的副本。這適合用來建立對話分支、在可能造成破壞的操作前建立檢查點,或測試不同的對話變化。 ```typescript const { thread, clonedMessages } = await memory.cloneThread({ sourceThreadId: 'thread-123', title: 'Branched conversation', }) ``` 你可以依數量或日期範圍篩選要複製的訊息、指定自訂 thread ID,並使用公用方法檢查複製關係。 如需完整 API,請參閱 [`cloneThread()`](https://mastra.zisheng.pro/zh-TW/reference/memory/cloneThread) 與[複製公用方法](https://mastra.zisheng.pro/zh-TW/reference/memory/clone-utilities)。 ## 刪除訊息 若要從 thread 移除訊息,請使用 [`deleteMessages()`](https://mastra.zisheng.pro/zh-TW/reference/memory/deleteMessages)。你可以依訊息 ID 刪除,或清除 thread 中的所有訊息。