> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # 觀察記憶 **新增於:** `@mastra/memory@1.1.0` 觀察記憶(Observational Memory,OM)是 Mastra 的長上下文 Agent 記憶系統。背景 Agent(即 **Observer** 和 **Reflector**)會監察 Agent 的對話,並維護一份密集的觀察日誌;隨着日誌增長,它會取代原始訊息歷史記錄。 ## 快速開始 請確保項目已安裝 `@mastra/memory`。在 Memory 配置中設定 `observationalMemory: true`,即可啟用觀察記憶。 ```typescript import { Memory } from '@mastra/memory' import { Agent } from '@mastra/core/agent' export const agent = new Agent({ id: 'my-agent', name: 'my-agent', instructions: 'You are a helpful assistant.', model: 'openai/gpt-5-mini', memory: new Memory({ options: { observationalMemory: true, }, }), }) ``` **供 AI Agent 參考:** 使用觀察記憶需要儲存 Provider!你需要在 `src/mastra/index.ts` 的 Mastra 實例上設定,或將其傳入 Agent 建構函數。 以下指令碼會建立本機 LibSQL 資料庫、啟用觀察記憶,並在兩次 Agent 呼叫中使用同一個資源和對話串: ```typescript import { Agent } from '@mastra/core/agent' import { LibSQLStore } from '@mastra/libsql' import { Memory } from '@mastra/memory' const memory = new Memory({ storage: new LibSQLStore({ id: 'memory-storage', url: 'file:./memory.db', }), options: { observationalMemory: { model: 'openai/gpt-5-mini', }, }, }) const agent = new Agent({ id: 'memory-agent', name: 'Memory Agent', instructions: 'You are a helpful assistant.', model: 'openai/gpt-5-mini', memory, }) const memoryOptions = { resource: 'user-123', thread: 'conversation-123', } const firstResponse = await agent.generate('Remember that my favorite color is blue.', { memory: memoryOptions, }) console.log(firstResponse.text) const secondResponse = await agent.generate('What is my favorite color?', { memory: memoryOptions, }) console.log(secondResponse.text) ``` `resource` 用來識別使用者或實體,而 `thread` 則識別對話。重用這兩個值即可繼續同一段對話。觀察記憶會隨着已儲存的歷史記錄增長而進行處理,並在符合啟用條件時以觀察記錄取代較舊的訊息。 Agent 現在具備可跨對話保留、類似人類的長期記憶。設定 `observationalMemory: true` 時,預設會使用 `google/gemini-2.5-flash`。如要使用其他模型,請在配置物件中傳入模型: ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'deepseek/deepseek-reasoner', }, }, }) ``` 完整 API 詳情請參閱[配置選項](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 > **注意:** 在客戶端應用程式中使用 OM 時,請從客戶端**只傳送新訊息**,而非完整的對話歷史記錄。 > > 觀察記憶仍依賴已儲存的對話歷史記錄。傳送完整歷史記錄既多餘,也可能在客戶端時間戳與已儲存的時間戳發生衝突時,引致訊息排序錯誤。 > > AI SDK 範例請參閱[使用 Mastra Memory](https://mastra.zisheng.pro/zh-HK/guides/build-your-ui/ai-sdk-ui)。 > **備註:** OM 目前只支援 `@mastra/pg`、`@mastra/libsql`、`@mastra/mysql`、`@mastra/mongodb`、`@mastra/convex` 及 `@mastra/oracledb` 儲存配接器。 它使用背景 Agent 管理記憶。未設定模型時,預設模型為 `google/gemini-2.5-flash`。 ## 時間間隔標記 如果對話串中上一則訊息發出後已經過足夠時間,時間間隔標記會在新的使用者訊息前插入簡短提示,讓 Agent 和 UI 知道對話是在一段值得留意的停頓後恢復。 時間間隔標記預設為停用。請在 `observationalMemory` 配置中設定 `temporalMarkers: true` 以啟用: ```typescript import { Memory } from '@mastra/memory' import { Agent } from '@mastra/core/agent' export const agent = new Agent({ id: 'my-agent', name: 'my-agent', instructions: 'You are a helpful assistant.', model: 'openai/gpt-5-mini', memory: new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', temporalMarkers: true, }, }, }), }) ``` 當時間間隔至少為 10 分鐘時,Mastra 會插入時間間隔標記。此標記會儲存在記憶中,同時以暫時提示事件的形式發出,讓客戶端可以將其呈現為輕量的時間軸提示。 Observer 處理對話串時也會看到這些標記,因此它寫入的觀察記錄可將記憶與事件發生的時間連繫起來(例如「使用者在相隔 2 天後詢問部署事宜」)。 完整配置結構請參閱 [API 參考](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 ## 提早啟用 OM 可在達到 token 閾值前啟用已緩衝的觀察記錄。當提示快取可能即將到期,或 Agent 更換模型 Provider 時,這項功能十分實用。 頂層提早啟用設定預設套用於觀察記錄: ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', activateAfterIdle: 'auto', activateOnProviderChange: true, }, }, }) ``` 使用巢狀 `observation` 和 `reflection` 設定,分別控制各個階段。反思的提早啟用須主動選用,因此頂層設定只會影響觀察記錄。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', activateAfterIdle: '5m', observation: { activateAfterIdle: false, }, reflection: { activateAfterIdle: '10m', activateOnProviderChange: true, }, }, }, }) ``` 在此範例中,頂層閒置設定對觀察記錄停用,而反思則選擇啟用閒置及 Provider 變更時啟用的機制。 ### 閒置時緩衝 將 `observation.bufferOnIdle` 設為 `true`,即可在 Agent 的一輪互動結束並進入閒置狀態時,在背景執行觀察緩衝。對於希望短輪次也能被觀察,而無需等待下一輪或達到 `messageTokens` 閾值的應用程式,這項功能十分實用。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'openai/gpt-5-mini', observation: { bufferOnIdle: true, }, }, }, }) ``` `bufferOnIdle` 預設為停用。它與 `bufferTokens` 分開運作:`bufferTokens` 控制步驟執行期間的非同步緩衝,而 `bufferOnIdle` 則控制閒置輪次在互動結束時的緩衝。 完整配置結構請參閱 [API 參考](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 ## 優點 - **提示快取**:OM 的上下文保持穩定,觀察記錄會隨時間附加,而非在每輪執行時擷取。這可讓提示前綴保持可快取,從而降低成本。 - **壓縮**:原始訊息歷史記錄和 Tool 結果會壓縮成密集的觀察日誌。上下文越小,回應便越快,連貫的對話也能維持更久。 - **零上下文劣化**:Agent 看到的是相關資訊,而非嘈雜的 Tool 呼叫和無關 token,因此能在長時間工作階段中持續專注於任務。 ## 運作方式 你不會記得自己曾經歷的每次對話中的每一句話。你會在潛意識中觀察所發生的事,然後大腦作出反思,將內容重新整理、合併和濃縮成長期記憶。OM 的運作方式亦一樣。 每次 Agent 回應時,都會看到一個包含其系統提示、近期訊息記錄,以及任何注入內容的上下文視窗。上下文視窗的容量有限,即使 token 上限很高的模型,在視窗載滿時表現也會變差。這會導致兩個問題: - **上下文劣化**:Agent 攜帶的原始訊息記錄越多,表現便越差。 - **上下文浪費**:這些記錄大部分都包含已不再需要、無助於 Agent 繼續執行當前任務的 token。 OM 將舊有上下文壓縮成密集的觀察記錄,從而解決這兩個問題。 ### 觀察 當訊息記錄的 token 超過閾值(預設:30,000)時,Observer 會建立觀察記錄,以簡潔筆記記下所發生的事: OM 使用快速的本機 token 估算來判斷是否達到閾值。文字使用 `tokenx` 估算,而圖像部分則使用考慮 Provider 的啟發式方法,讓多模態對話仍能在適當時機觸發觀察。當傳輸層把已上載的圖像正規化為檔案而非圖像部分時,同樣的方式也適用於類似圖像的 `file` 部分。例如,OpenAI 的圖像細節設定可能會實質影響 OM 決定執行觀察的時機。 Observer 也可以看到其檢視記錄中的附件。為方便閱讀,OM 會在文字記錄中保留 `[Image #1: reference-board.png]` 或 `[File #1: floorplan.pdf]` 等易讀的佔位符,並將實際附件部分連同文字一併轉交。OM 會盡可能把類似圖像的 `file` 部分升級為 Observer 的圖像輸入,而非圖像附件則會以檔案部分轉交,並使用正規化的 token 計算方式。這同時適用於一般 thread 觀察和批次 resource scope 觀察。 ### Extractor 如要 OM 在觀察記錄旁持久保存特定值,請使用 Extractor。**目前任務**、**建議回應**和 **thread 標題**等內置值,與自訂值使用相同的擷取流程。 以下範例從觀察記錄擷取精簡的用戶資料: ```typescript import { Agent } from '@mastra/core/agent' import { Extractor, Memory } from '@mastra/memory' import { z } from 'zod' const memory = new Memory({ options: { observationalMemory: { model: 'openai/gpt-5-mini', observation: { extract: [ new Extractor({ name: 'User profile', instructions: 'Extract stable user profile facts that should be remembered.', schema: z.object({ preferredName: z.string().optional(), timezone: z.string().optional(), tools: z.array(z.string()).optional(), }), }), ], }, }, }, }) export const agent = new Agent({ id: 'assistant', name: 'assistant', instructions: 'You are a helpful assistant.', model: 'openai/gpt-5-mini', memory, }) ``` 加入 `schema` 後,Extractor 會以後續結構化輸出請求的形式執行。沒有 schema 的 Extractor 是內嵌字串 Extractor,會直接在 Observer 或 Reflector 的回應中輸出。 ```typescript new Extractor({ name: 'Mood', instructions: 'Extract the user mood as a short phrase.', }) ``` 預設情況下,OM 會在後續執行時向 Extractor 顯示上一次擷取的值。如果不應讓 Observer 看到上一個值,請設定 `includePreviousExtraction: false`。 ```typescript new Extractor({ name: 'Latest blocker', instructions: 'Extract any blockers the agent is running into.', includePreviousExtraction: false, }) ``` 當 Extractor 需要執行階段上下文(例如目前使用中的 memory 執行個體或請求上下文)時,請使用執行階段 `instructions` 或 `schema` 函數: ```typescript new Extractor({ name: 'Workspace summary', instructions: ({ memory }) => memory ? 'Extract workspace facts for this memory instance.' : 'Extract workspace facts.', }) ``` #### 從串流讀取擷取值 OM 完成觀察或反思時,便會輸出 Extractor 結果。從串流讀取兩種完成資料部分: ```typescript const stream = await agent.stream('Remember that I prefer dark mode.') for await (const chunk of stream.fullStream) { if (chunk.type === 'data-om-observation-end' || chunk.type === 'data-om-buffering-end') { const { operationType, extractedValues = {}, extractionFailures = [] } = chunk.data for (const [slug, value] of Object.entries(extractedValues)) { console.log(`${operationType} extractor ${slug}:`, value) } for (const failure of extractionFailures) { console.error(`Extractor ${failure.slug} failed:`, failure.error) } } } ``` `extractedValues` 以每個 Extractor 的 slug 作為 key。兩個結果欄位皆為選填,而某個 Extractor 失敗亦不會移除成功 Extractor 的值。 `data-om-observation-end` 表示同步完成。`data-om-buffering-end` 表示背景工作完成。其 Extractor metadata 會立即持久保存,但緩衝內容在啟用前仍維持非使用中狀態。檢查 `operationType`,即可判斷已完成的工作屬於觀察還是反思。 如需完整 payload,請參閱 [`data-om-observation-end`](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory) 和 [`data-om-buffering-end`](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory) 參考表格。 ### 更新 working memory 使用 `observationalMemory.observation.manageWorkingMemory`,讓 Observer 自動管理 working memory。主要 Agent 處理用戶請求時,不再需要呼叫 working memory Tool,因此更新 working memory 不再取決於 Agent 是否記得執行相關操作。 這也讓 working memory 配合提示快取使用。Working memory 一般位於系統提示中,因此更新可能令提示快取失效。由 OM 管理的 working memory 會將 `workingMemory.useStateSignals` 預設為 `true`,把 working memory 移至狀態訊號中。 ```typescript import { Memory } from '@mastra/memory' const memory = new Memory({ options: { workingMemory: { enabled: true, }, observationalMemory: { enabled: true, observation: { manageWorkingMemory: true, }, }, }, }) ``` 此設定會加入 `WorkingMemoryExtractor`、將 `workingMemory.agentManaged` 預設為 `false`,並將 `workingMemory.useStateSignals` 預設為 `true`。如主要 Agent 仍應接收 working memory Tool 和指示注入,請設定 `workingMemory.agentManaged: true`。 在自訂擷取值持久保存之前,使用 `onExtracted` 將值正規化或回應這些值: ```typescript new Extractor({ name: 'Project status', instructions: 'Extract the current project status.', schema: z.string(), async onExtracted({ current, sendSignal }) { await sendSignal?.({ type: 'user-message', contents: `Project status extracted: ${current}`, }) return current.trim().toLowerCase() }, }) ``` Extractor 失敗會在 OM 標記中報告,且不會阻礙其他 Extractor 成功輸出值。如需完整的 `Extractor` 結構,請參閱 [API 參考](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 如果你的 Observer 模型只支援文字,或其 API 拒絕多模態輸入,請將 `observation.observeAttachments` 設定為 `false`,在附件送達 Observer 前移除附件。易讀的佔位符(`[Image #1: ...]`、`[File #1: ...]`)仍會保留在文字記錄中,讓 Observer 即使沒有收到二進制 payload,仍可根據已分享的內容進行推理。相同的篩選器亦適用於包含圖像或檔案部分的 Tool 結果: ```typescript new Agent({ id: 'assistant', name: 'assistant', instructions: 'You are a helpful assistant.', model: 'openai/gpt-5-mini', memory: new Memory({ options: { observationalMemory: { observation: { model: 'deepseek/deepseek-reasoner', observeAttachments: false, }, }, }, }), }) ``` 你也可以傳入 mimeType glob 的允許清單(例如 `['image/*']`),只轉交 Observer 能夠處理的類型。另一種做法是設定 `observeAttachments: 'auto'`,讓 Mastra 根據 Provider 功能註冊表決定:當 Observer 模型支援多模態輸入時轉交附件,否則移除附件;如果該模型沒有可用的功能資料,則回退至 `true`。 ```md Date: 2026-01-15 - 🔴 12:10 User is building a Next.js app with Supabase auth, due in 1 week (meaning January 22nd 2026) - 🔴 12:10 App uses server components with client-side hydration - 🟡 12:12 User asked about middleware configuration for protected routes - 🔴 12:15 User stated the app name is "Acme Dashboard" ``` 壓縮率通常介乎 5 倍至 40 倍。Observer 亦會追蹤**目前任務**和**建議回應**,讓 Agent 從上次中斷之處繼續。 如啟用 `observation.threadTitle`,當對話主題出現重大變化時,Observer 也可以建議簡短的 thread 標題。產生 thread 標題屬於選用功能,並會更新 thread metadata,讓 Mastra Code 等應用程式可在 thread 清單和狀態 UI 中顯示最新標題。 範例:使用 Playwright MCP 的 Agent,每個頁面快照可能有超過 50,000 個 token。有了 OM,Observer 會監察互動,並建立數百個 token 的觀察記錄,記下頁面上的內容和已執行的操作。Agent 無需攜帶每個原始快照,仍可專注於目前任務。 ### 反思 當觀察記錄超過閾值(預設:40,000 個 token)時,Reflector 會將其濃縮、合併相關項目,並反思當中的模式。 反思不會累積成獨立且不斷增長的層。每次反思都會重寫整份觀察記錄。Reflector 的輸出會成為新記錄,新觀察則附加在其後。下次記錄達到閾值時,Reflector 會重新處理所有內容,包括先前的反思。它會更大幅度地濃縮較舊的資訊,同時保留近期細節。無論對話持續多久,記憶大小都會維持在反思閾值附近。 最終形成一個三層系統: 1. **近期訊息**:目前任務的完整對話記錄 2. **觀察**:Observer 所見內容的記錄 3. **反思**:記憶過長時經濃縮的觀察記錄 ### 上下文如何隨時間改變 使用預設設定時,上下文視窗不會無限增長,而會反覆經歷觀察並縮減的週期: ![Chart of context tokens over the course of a conversation with Observational Memory enabled: message history repeatedly grows toward the 30,000 token observation threshold, then shrinks back to around 6,000 tokens as observations activate, while the observation log steps up with each cycle until it reaches the 40,000 token reflection threshold and the Reflector condenses it into reflections](/img/memory/om-context-over-time-light.svg) 1. **0 → 30k 個 token**:訊息記錄正常增長。在背景中,Observer 每累積約 \~6k 個 token 便緩衝觀察記錄(`bufferTokens: 0.2`)。 2. **達到 30k**:緩衝的觀察記錄會立即啟用。已觀察的訊息會從上下文視窗移除,僅保留約 \~6k 個 token 的近期記錄(`bufferActivation: 0.8` 會保留閾值的 20%)。移除的約 \~24k 個訊息 token,在一般 5 至 40 倍壓縮率下,會變成約 1 至 5k 個觀察 token。 3. **重複**:記錄從約 \~6k 再次增長至接近 30k,然後再次縮減。每個週期都會附加至觀察記錄,而觀察記錄的增長速度遠低於原始記錄。 4. **觀察記錄達到 40k**:Reflector 根據目前觀察記錄和任何先前反思建立較小的記錄。 在一般緩衝週期中,原始記錄會在約 6k 至 30k 個 token 之間變動。無論對話持續多久,觀察記錄都維持在約 40k 個 token。這些是啟用閾值,而非硬性上限。如果背景緩衝未能跟上,記錄可以超出閾值,直至 `blockAfter`(預設為 `1.2`)在約 \~36k 個 token(反思則為 \~48k)時強制執行同步觀察,作為安全上限。 啟用 [`shareTokenBudget`](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory) 後,兩個預算會合併共用。當觀察記錄較小時,訊息記錄可以佔用尚未使用的觀察空間(使用預設值時最高約為 \~70k 個 token),之後才觸發觀察。隨着觀察記錄累積,訊息記錄便會縮減。 ### 檢索模式 一般 OM 會將訊息壓縮成觀察記錄,這非常有助於專注執行任務,但會失去原文措辭。檢索模式會把每組觀察記錄與產生該記錄的原始訊息連結起來,從而解決此問題。當 Agent 需要摘要壓縮時所捨棄的確切措辭、Tool 輸出或時間次序,便可呼叫 `recall` Tool,逐頁瀏覽來源訊息。 #### 僅瀏覽 設定 `retrieval: true`,啟用 recall Tool 來瀏覽原始訊息,無需使用向量儲存。預設情況下,recall Tool 可以瀏覽目前 resource 的所有 thread。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', retrieval: true, }, }, }) ``` #### 配合語意搜尋 設定 `retrieval: { vector: true }`,同時啟用語意搜尋。這會重用已在 Memory 執行個體上設定的向量儲存和 embedder: ```typescript const memory = new Memory({ storage, vector: myVectorStore, embedder: myEmbedder, options: { observationalMemory: { model: 'google/gemini-2.5-flash', retrieval: { vector: true }, }, }, }) ``` 設定向量搜尋後,系統會在緩衝時和同步觀察期間,自動為新的觀察群組建立索引(即發即棄、非阻塞)。語意搜尋會傳回相符的觀察群組及其原始來源訊息 ID 範圍,讓 recall Tool 在顯示摘要記憶時,也能一併顯示其來源位置。 #### 限制為目前 thread recall Tool 的預設 scope 是 `'resource'`,Agent 可以列出 thread、瀏覽其他 thread,以及搜尋所有對話。設定 `scope: 'thread'`,將 Agent 限制為只能存取目前 thread: ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', retrieval: { vector: true, scope: 'thread' }, }, }, }) ``` #### 自訂 recall 指引 Mastra 會注入考慮 scope 的指示,教導 Agent 何時搜尋、列出 thread,或讀取特定 thread。使用 `instructions`,在這些內置指示後附加應用程式專用指引。內置指示絕不會被取代: ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', retrieval: { vector: true, instructions: ` Prefer the current conversation when it already contains the answer. For an initial scan, use a small limit with detail="low". `, }, }, }, }) ``` 這會讓 recall 專用指引附加至 recall Tool,而非 Agent 的全域指示,因此不會影響無關的任務。 #### 檢索所啟用的功能 啟用檢索模式後,OM 會: - 在每個觀察群組上儲存一個 `range`(例如 `startId:endId`),指向產生該觀察群組的訊息 - 在 Agent 的上下文中顯示範圍 metadata,讓 Agent 知道哪些觀察記錄對應哪些訊息 - 註冊一個 Agent 可以呼叫的 `recall` Tool,以便: - 逐頁瀏覽任何觀察群組範圍背後的原始訊息 - 按語意相似度搜尋(`mode: "search"` 並提供 `query` 字串);需要 `vector: true` - 列出所有 thread(`mode: "threads"`)、瀏覽其他 thread(`threadId`),以及搜尋所有 thread(預設 `scope: 'resource'`) - 當 `scope: 'thread'` 時:將瀏覽和搜尋限制為目前 thread 如需完整 API(詳細程度、部分索引、分頁、跨 thread 瀏覽和 token 限制),請參閱 [recall Tool 參考](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 ## Studio 如要實際查看運作方式,請開啟 [Studio](https://mastra.zisheng.pro/zh-HK/docs/studio/overview),然後前往已啟用 OM 的 Agent。**Memory**分頁會顯示: - **Token 進度列**:顯示訊息和觀察記錄目前的 token 數量,以及距離各自閾值還有多遠。將游標停留在資訊圖示上,即可查看 Observer 和 Reflector 的模型與閾值。 - **使用中的觀察記錄**:目前的觀察記錄會直接顯示。如有更早的觀察或反思記錄,請展開「Previous observations」瀏覽。 - **背景處理**:對話期間,Agent 在背景處理時,會顯示已緩衝的觀察區塊和反思狀態。 Agent 正在觀察或反思時,進度列會即時更新,並顯示經過時間和狀態徽章。 ## 模型 Observer 和 Reflector 會在背景執行。任何支援 Mastra [模型路由](https://mastra.zisheng.pro/zh-HK/models)(`provider/model`)的模型皆可使用。如果沒有設定模型,預設模型為 `google/gemini-2.5-flash`。 Mastra 建議使用具備大型上下文視窗(128K+ 個 token),並且速度足以在背景執行而不會拖慢操作的模型。 如果不確定應使用哪個模型,請先使用預設的 `google/gemini-2.5-flash`。我們亦已成功測試 `openai/gpt-5-mini`、`anthropic/claude-haiku-4-5`、`deepseek/deepseek-reasoner`、`deepseek/deepseek-v4-pro`、`deepseek/deepseek-v4-flash`、`xai/grok-4-1-fast`、`qwen3` 和 `glm-4.7`。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'deepseek/deepseek-reasoner', }, }, }) ``` 如要為每個 Agent 使用不同模型,請參閱[模型設定](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 > **備註:** `google/gemini-2.5-flash` 特別擅長在長輸出中保留細節。因此,即使達到壓縮重試次數上限,Reflector 所產生的反思仍可能高於設定的 `reflection.observationTokens` 閾值。發生這種情況時,Reflector 會傳回重試期間產生的最小非退化候選結果,讓循環終止,而非無限執行。 > > 如想讓 Reflector 更大幅度地壓縮,可改用更容易濃縮內容的模型,例如 `xai/grok-4-1-fast`、`deepseek/deepseek-v4-pro` 或 `deepseek/deepseek-v4-flash`。你可以繼續為 Observer 使用 `google/gemini-2.5-flash`,並為 Reflector 使用另一個模型。請參閱[為每個 Agent 使用不同模型](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 ### 按 token 分級選擇模型 **新增於:** `@mastra/memory@1.10.0` 你可以使用 `ModelByInputTokens`,根據輸入 token 數量為 Observer 或 Reflector 指定不同模型。OM 會在執行階段根據設定的 `upTo` 閾值,選擇相符的模型級別。 ```typescript import { Memory, ModelByInputTokens } from '@mastra/memory' const memory = new Memory({ options: { observationalMemory: { observation: { model: new ModelByInputTokens({ upTo: { // Faster, cheaper models for smaller inputs; stronger models for larger contexts 5_000: 'openrouter/mistralai/ministral-8b-2512', 20_000: 'openrouter/mistralai/mistral-small-2603', 40_000: 'openai/gpt-5-mini', 1_000_000: 'google/gemini-3.1-flash-lite-preview', }, }), }, reflection: { model: new ModelByInputTokens({ upTo: { 20_000: 'openai/gpt-5-mini', 100_000: 'google/gemini-2.5-flash', }, }), }, }, }, }) ``` `upTo` key 是包含端點的上限。OM 會計算 Observer 或 Reflector 呼叫的實際輸入 token 數量,直接解析相符級別,並在該次執行中使用對應的具體模型。 如果輸入超過已設定的最大閾值,系統便會拋出錯誤。請確保閾值涵蓋所有可能的輸入大小,或在最高級別使用上下文視窗足夠大的模型。 ## 作用域 ### Thread 作用域(預設) 每個 thread 都有各自的觀察記錄。此作用域已經過充分測試,作為通用記憶系統時表現良好,尤其適合長期運作的 Agent 使用情境。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', scope: 'thread', }, }, }) ``` Thread 作用域要求呼叫 Agent 時提供有效的 `threadId`。如果缺少 `threadId`,Observational Memory 會拋出錯誤。這可防止多個 thread 在不知情下共用同一筆觀察記錄,否則可能會造成資料庫死鎖。 ### Resource 作用域(實驗性) 觀察記錄會在同一 resource(通常是使用者)的所有 thread 之間共用,從而實現跨對話記憶。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', scope: 'resource', }, }, }) ``` Resource 作用域可以運作,但目前仍標示為實驗性,直至我們證實它能在多個同時持續進行的 thread 之間維持任務遵循能力和連貫性。 目前,你可能需要調整 system prompt,避免某個 thread 接續另一個 thread 已開始(但尚未完成)的工作。 這是因為在 resource 作用域中,每個 thread 都是檢視該 resource _所有_ thread 的一個視角。 這對你的使用情境而言未必是問題,因此實際效果可能因情況而異。 > **注意:** 在 resource 作用域中,_所有_ thread 內尚未觀察的訊息會一併處理。對於已有大量 thread 的使用者,這個過程可能很慢。現有應用程式應使用 thread 作用域。 ## Token 預算 OM 使用 token 閾值來決定何時進行觀察和反思。詳情請參閱 [token 預算設定](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', observation: { // when to run the Observer (default: 30,000) messageTokens: 30_000, }, reflection: { // when to run the Reflector (default: 40,000) observationTokens: 40_000, }, // let message history borrow from observation budget // requires bufferTokens: false (temporary limitation) shareTokenBudget: false, }, }, }) ``` ### Token 計數快取 OM 會在訊息 metadata 中快取 token 估算值,以減少執行閾值檢查和作出緩衝決定時的重複計數工作。 - 每個 part 的估算值會儲存在 `part.providerMetadata.mastra`,並在後續處理中於快取版本/tokenizer 來源相符時重用。 - 對於只有字串的訊息內容(不含 part),OM 會使用訊息層級的 metadata 後備快取。 - 每次處理仍會重新計算訊息和對話的額外開銷。快取只儲存 payload 估算值,因此計數語意維持不變。 - `data-*` 和 `reasoning` part 仍會略過,不會快取。 ### 呼叫方為檔案 part 提供的 token 估算值 你可以使用 `providerMetadata.mastra.tokenEstimate`,直接將 token 估算值附加至 `image` 或 `file` part。Token Counter 會原樣採用這個值,並略過本身的估算器: ```typescript const filePart = { type: 'file', data: 'storage://bucket/large-report.pdf', mimeType: 'application/pdf', filename: 'large-report.pdf', providerMetadata: { mastra: { tokenEstimate: { v: 0, source: 'client', key: 'client', tokens: 100_000, }, }, }, } ``` `tokenEstimate` 物件的結構與 Token Counter 內部快取估算值所用的結構相同: - `v`:快取 schema 版本。請設為 `0`。呼叫方提供的項目不受 framework 的版本檢查約束,因此不會讀取此值。 - `source`:快取來源標記。必須是 `'client'`。它會告知 Token Counter 此項目具權威性,應原樣採用,而不是重新計算或覆寫。 - `key`:內容 fingerprint 欄位。請設為 `'client'`。Framework 項目會在此處使用內容 hash,讓項目在 payload 變更時失效。`'client'` sentinel 可讓呼叫方估算值在多次寫入之間保持穩定。 - `tokens`:要使用的 token 數量。必須是有限的非負數。 其他注意事項: - 估算值只會在 `image` 和 `file` part 上獲採用。`text` 和 `tool-invocation` part 一律會正常計數,即使它們包含 `tokenEstimate` 亦然。 ## 非同步緩衝 如果不使用非同步緩衝,當訊息達到閾值時,Observer 會同步執行;Agent 會在對話途中暫停,直至 Observer LLM 呼叫完成。使用非同步緩衝(預設啟用)後,系統會隨對話增長,在背景預先計算觀察記錄。達到閾值時,已緩衝的觀察記錄會即時啟用,過程毋須暫停。 ### 運作方式 隨着 Agent 進行對話,訊息 token 會不斷累積。系統會按固定間隔(`bufferTokens`)在背景呼叫 Observer,而不會阻塞 Agent。每次呼叫都會產生一個觀察記錄「區塊」,並儲存在緩衝區中。 當訊息 token 達到 `messageTokens` 閾值時,已緩衝的區塊便會啟用:其中的觀察記錄會移至作用中的觀察日誌,而相應的原始訊息會從上下文視窗中移除。Agent 全程都不會暫停。 已緩衝的觀察記錄亦包括接續提示、建議的下一個回覆及目前任務,因此啟用緩衝內容並縮減上下文視窗後,主要 Agent 仍可維持對話連貫性。 如果 Agent 產生訊息的速度快過 Observer 的處理速度,`blockAfter` 安全閾值會作為最後手段,強制執行同步觀察。啟用已緩衝內容時,仍會保留最低限度的剩餘上下文(約 1k token 或已設定保留下限,取兩者中較小者)。 反思的運作方式相近:當觀察記錄達到反思閾值的某個比例時,Reflector 便會在背景執行。 ### 設定 | 設定 | 預設值 | 控制內容 | | ------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `observation.bufferTokens` | `0.2` | 執行緩衝的頻率。`0.2` 表示每達到 `messageTokens` 的 20% 便執行一次。若使用預設的 30k 閾值,即大約每 6k token 執行一次。亦可使用絕對 token 數量(例如 `5000`)。 | | `observation.bufferActivation` | `0.8` | 啟用時清除訊息視窗的積極程度。`0.8` 表示移除足夠的訊息,讓剩餘內容只佔 `messageTokens` 的 20%。較低的值會保留更多訊息歷史。 | | `observation.blockAfter` | `1.2` | 緩衝速度不足時的安全機制。從 1 至 100 以內(不包括 100)的值會乘以 `messageTokens`:設為 `1.2` 時,系統會在 36k token(1.2 × 30k)強制執行同步觀察。100 或以上的值則代表絕對 token 數量(例如 `50_000`)。 | | `activateAfterIdle` | 無 | 即使尚未達到 `observation.messageTokens`,亦會在閒置一段時間後強制啟用已緩衝的觀察記錄。接受以毫秒表示的數值(例如 `300_000`)、`"5m"` 或 `"1hr"` 等持續時間字串,亦可設為 `"auto"`,以使用配合 Provider 的 prompt 快取 TTL。 | | `activateOnProviderChange` | `false` | 如果下一個步驟使用的 `provider/model` 與產生最新 assistant 步驟的 provider/model 不同,便會強制啟用已緩衝的觀察記錄。切換 Provider 或模型會令 prompt 快取無法重用時,請使用此設定。 | | `reflection.bufferActivation` | `0.5` | 開始背景反思的時機。`0.5` 表示當觀察記錄達到 `observationTokens` 閾值的 50% 時,便開始反思。 | | `reflection.activateAfterIdle` | 無 | 讓已緩衝的反思選擇加入閒置啟用機制。反思不會繼承最上層的 `activateAfterIdle`。 | | `reflection.activateOnProviderChange` | `false` | 讓已緩衝的反思選擇加入 Provider 變更啟用機制。反思不會繼承最上層的 `activateOnProviderChange`。 | | `reflection.blockAfter` | `1.2` | 反思的安全閾值,邏輯與觀察相同。 | 如果你依賴 prompt 快取,請將 `activateAfterIdle` 設為 `"auto"` 或特定的快取 TTL。這樣,當 thread 閒置時間足以令快取過期後,下一個請求可先啟用已緩衝的觀察記錄,再傳送較小且已壓縮的上下文視窗。 使用 `"auto"` 時,Mastra 會根據作用中模型的 Provider 選擇閒置啟用 TTL: | Provider | 自動 TTL | | --------------------------------------------------------------------------- | ------ | | Anthropic、OpenRouter、未知 Provider、xAI | 5 分鐘 | | DeepSeek | 1 小時 | | Google Gemini | 24 小時 | | Groq | 2 小時 | | 使用 `providerOptions.openai.promptCacheRetention: "24h"` 的 OpenAI | 1 小時 | | 使用 `providerOptions.openai.promptCacheRetention: "in_memory"` 的 OpenAI | 5 分鐘 | | OpenAI `gpt-4*`、`gpt-5`、`gpt-5-*`,以及由 `gpt-5.1` 至 `gpt-5.4`(包括帶有 `-` 後綴的變體) | 5 分鐘 | | 其他 OpenAI 模型 | 1 小時 | ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', activateAfterIdle: 'auto', activateOnProviderChange: true, }, }, }) ``` 使用 `"auto"` 時,此功能會根據作用中 Provider 的 prompt 快取行為啟用已緩衝的觀察記錄,讓下一個未快取的 prompt 使用已壓縮的觀察記錄,而非較大的原始訊息視窗。如果你偏好固定的 5 分鐘 TTL,請使用 `"5m"` 或 `300_000`。 在 thread 進行期間變更模型或 Provider,會令 prompt 快取失效。如果你的 Agent 可以在 thread 進行期間切換 Provider 或模型,`activateOnProviderChange: true` 會在新 Provider 執行前強制啟用已緩衝的觀察記錄。這可避免將大型原始視窗傳送至無法重用先前 prompt 快取的 Provider。 ### 停用 如要停用非同步緩衝,改用同步觀察/反思: ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', observation: { bufferTokens: false, }, }, }, }) ``` 設定 `bufferTokens: false` 會同時停用觀察和反思的非同步緩衝。完整 API 詳情請參閱 [非同步緩衝設定](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory)。 > **備註:** `scope: 'resource'` 不支援非同步緩衝。系統會在 resource 作用域中自動將其停用。 ## Observer 上下文最佳化 根據預設設定,Observer 處理新訊息時會收到完整的觀察記錄歷史作為上下文。Observer 亦會收到先前的 `current-task` 和 `suggested-response` metadata(如有),因此即使觀察上下文被截短,仍能掌握目前情況。對於觀察記錄日益龐大的長時間對話,你可以選擇啟用上下文最佳化,以減少 Observer 的輸入成本。 設定 `observation.previousObserverTokens` 可限制傳送至 Observer 的先前觀察記錄 token 數量。觀察記錄會從尾部截短,保留最新的項目。當有已緩衝的反思等待處理時,系統會先自動以反思摘要取代已反思的行,然後才套用截短。 ```typescript const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', observation: { previousObserverTokens: 10_000, // keep only ~10k tokens of recent observations }, }, }, }) ``` - `previousObserverTokens: 2000` → 預設值。保留約 2k token 的近期觀察記錄。 - `previousObserverTokens: 0` → 完全省略先前的觀察記錄。 - `previousObserverTokens: false` → 停用截短並保留完整的先前觀察記錄。 ## 遷移現有 thread 毋須手動遷移。OM 會讀取現有訊息,並在超出閾值時延後觀察它們。 - **Thread 作用域**:thread 首次超出 `observation.messageTokens` 時,Observer 會處理積壓內容。 - **Resource 作用域**:同一 resource 的所有 thread 中,尚未觀察的訊息會一併處理。對於已有大量 thread 的使用者,這可能需要相當長時間。 ## 比較 OM 與其他記憶功能 - **[訊息歷史](https://mastra.zisheng.pro/zh-HK/docs/memory/message-history)**:目前對話的高保真記錄 - **[工作記憶](https://mastra.zisheng.pro/zh-HK/docs/memory/working-memory)**:用於使用者偏好、名稱及目標的小型結構化狀態(JSON 或 markdown) - **[Semantic Recall](https://mastra.zisheng.pro/zh-HK/docs/memory/semantic-recall)**:以 RAG 為基礎,擷取相關的過往訊息 - **[多使用者 thread](https://mastra.zisheng.pro/zh-HK/docs/memory/multi-user-threads)**:當多人共用同一個 thread 時,OM 如何將事實歸屬至個別使用者 如果你使用工作記憶來儲存對話摘要,或儲存會隨時間增長的持續狀態,OM 會更合適。工作記憶用於小型結構化資料;OM 則用於長時間運作的事件日誌。OM 亦會自動管理訊息歷史,而 `messageTokens` 設定會控制執行觀察前保留多少原始歷史。 實際而言,OM 同時取代工作記憶和訊息歷史,而且比 Semantic Recall 更準確(成本亦更低)。 ## 相關內容 - [Observational Memory 參考資料](https://mastra.zisheng.pro/zh-HK/reference/memory/observational-memory) - [記憶概覽](https://mastra.zisheng.pro/zh-HK/docs/memory/overview) - [訊息歷史](https://mastra.zisheng.pro/zh-HK/docs/memory/message-history) - [Memory Processor](https://mastra.zisheng.pro/zh-HK/docs/memory/memory-processors) - [Mastra Code](https://code.mastra.ai/):使用 Observational Memory 的編程助手 Agent - 📹 [Mastra Processor 與 Observational Memory 工作坊](https://www.youtube.com/watch?v=4Vpp7xQYvl0)