收斂自討論:不維護 MD 對話紀錄、僅以短期 JSON + 長期 JSON 雙池構成記憶;完整對話由使用者自行備份。對齊 對話記憶與背版—設計、對話記憶系統—彙整與探討。
| 項目 | 內容 |
|---|---|
| 對話紀錄(MD) | 不維護。使用者若要完整紀錄可自行備份;系統不寫、不讀任何對話紀錄檔。 |
| 記憶儲存 | 僅兩類:短期記憶池(JSON)、長期記憶池(JSON)。 |
| 短期池 | 每輪結束後,用當下這一輪(使用者句+助手句)做 deconstruct,抽出要旨/關鍵事實,直接寫入短期 JSON。 |
| 長期池 | 等同人物背版;由短期池在滿足條件時(如 n 輪、時間、或條數上限)經提煉後寫入。 |
| 回覆時 | 只讀短期 + 長期池:依本次輸入檢索出幾條,注入 prompt,不讀任何 MD、不傳遞原文對話歷史。 |
| Context | 理論上較省:模型從未看到整段對話,只看到固定上限的「精選條目」,token 隨對話長度不膨脹。 |
使用者發送一句
↓
依本次輸入從「短期池」與「長期池」檢索(各取 top-k)
↓
背版(SOUL/MEMORY 等)+ 短期檢索結果 + 長期檢索結果 = 組 prompt
↓
模型回覆
↓
本輪結束:deconstruct(本輪對話)→ 寫入短期池
↓
(背景)若滿足條件:提煉短期池 → 寫入長期池;短期池可清空或滾動
不存在的路徑:不寫 MD、不讀 MD、不把「最近 N 輪原文」塞進 context。
| 既有概念 | 本定稿對應 |
|---|---|
| archival、長期記憶 | 長期池 JSON(人物背版)。 |
| session、短期記憶 | 短期池 JSON(本場/近期提煉條目)。 |
| 不依賴「MD 對話紀錄 + 硬式檢索」 | 明確不維護 MD;完整紀錄由使用者自行保存。 |
| 抽出的要旨 → 少數條目注入 | 短期/長期皆為「條目」;回覆時只注入檢索到的少數幾條。 |
| 背版 blocks(identity/summary/relationship) | 仍可保留 SOUL.md、MEMORY.md 等「固定/可更新背版」;長期池為動態累積的背版補充。 |
- 人類要看完整紀錄可自行備份,無須系統再存一份。
- 若系統再寫 MD,要嘛(a)從不讀——等於多餘 I/O,要嘛(b)讀來提煉——但短期池已可由「每輪 deconstruct」直接寫入,讀 MD 提煉會多繞一步。故定稿為不維護 MD。
- 每輪結束時,系統已有「使用者句+助手句」在記憶體,直接 deconstruct 寫入短期池即可。
- 不需先寫入 MD、再另時機讀 MD 做提煉;路徑最短、邏輯最單純。
- 回覆路徑只依「本次輸入」從兩池取固定條數(如長期 3 條、短期 2 條),每條可再截斷字數。
- 不塞整段對話、不塞整份 MD,故 token 用量不隨對話長度成長,理論上較省 context。
以下留待實作階段再定,不影響「雙池、無 MD、回覆只讀兩池」的概念:
| 項目 | 說明 |
|---|---|
| 短期 → 長期的觸發條件 | 例如:n 輪、一段時間、短期條數上限、或上下文容量閾值。 |
| 提煉形式 | 合併相似條目、摘要、或篩選後逐條寫入長期等。 |
| 檢索方式 | 目前為關鍵字重疊;可改為 embedding+向量檢索,仍維持「只讀兩池、固定條數」。 |
| 條目格式 | 短期/長期 JSON 的欄位(content、tag、timestamp 等)與可選的關鍵字索引。 |
本設計只決定送進模型的 context(背版 + 短期幾條 + 長期幾條),不決定模型「會答出什麼」。實際回答品質仍取決於:
- 模型能力與訓練分佈;
- system prompt 與指令設計;
- deconstruct/提煉的品質(抽得是否精準、是否有噪音)。
因此實作後需依實際對話表現,微調條數、字數上限、以及 deconstruct/提煉的 prompt,必要時可對照 網上常見的記憶機制—彙整 做小改。
提煉(短期 → 長期)決定「什麼會變成人物背版」,建議如下。
| 方式 | 說明 | 建議 |
|---|---|---|
| 短期條數上限 | 短期池達到 N 條就觸發一次提煉 | 主觸發。與現有 rolloverLimit 對齊:滿 N 條時改為「整批送提煉」而非「最舊一筆直接搬」。 |
| 每 M 輪 | 每 M 次使用者訊息觸發一次 | 可選。避免很久沒滿 N 條、短期堆太多才提煉。 |
| 時間間隔 | 例如每 30 分鐘、或 session 結束時 | 可選。適合「一段時間沒聊就收斂一次」。 |
建議先做**「滿 N 條觸發」**,必要再加輪數或時間。
篩選(C)、摘要(B)、合併相似(A)三者在同一輪提煉裡一起做,不拆成多階段、一次到位。
| 取徑 | 在提煉流程裡的角色 |
|---|---|
| C. 篩選 | 只保留「值得長期記住」的內容,其餘視為噪音、不產出。 |
| B. 摘要 | 多條若在講同一件事,合併成一句話總結,不重複羅列。 |
| A. 合併相似 | 同主題、同類型的多條合併成一條,背版精簡、不重複。 |
實作上:一次 Ollama Generate,prompt 同時要求「篩選 + 摘要 + 合併相似」,產出 1~3 條最終事實;不做「先 C 再 B 再 A」的多段呼叫。
- 輸入:短期池目前條目(或本次要處理的那批)的
content列表;每條可先截斷字數(如 80~120 字)再送,省 context。 - 呼叫:一次 Ollama
Generate(非串流),prompt 同時涵蓋 C+B+A,範例:- 「以下是近期對話抽出的要旨(每行一條)。請做三件事:(1) 篩選:只保留值得長期記住的;(2) 合併相似:同主題或同類型合併成一條;(3) 摘要:若多條在講同一件事,用一句話總結。產出 1~3 條人物背版事實,每條一句話、不重複、不廢話。若都無長期價值就回傳「無」。偏好:使用者偏好、重要決定、與使用者的關係或承諾。」
- 輸出解析:若回傳為「無」或無法解析則不寫入;否則每條一行,逐條
Insert(content, tag)進長期池(tag 如refined或沿用fact)。 - 短期池處理:提煉完成後,將已送提煉的那批從短期池移除(或清空整池,依你定義的「一批」為何);避免同一批重複提煉。
與現有 AddSessionFact 的改動:目前是「超過 rolloverLimit 就把最舊一筆直接 Insert」。可改為「超過 rolloverLimit 時,改為觸發提煉流程」:取短期池內要處理的條目(例如最舊的 K 條,或全池)、送上述 prompt、得到 1~3 條後寫入長期、再從短期移除這批」。若提煉 API 失敗或超時,可 fallback 為「最舊一筆直接 Insert」,避免丟失。
- Token 控制:一次提煉送進的短期條目不宜過多(建議最多約 10~15 條,每條已截斷),否則小模型容易爆 context 或輸出品質下降。
- 同模型或專用模型:提煉可與回覆共用同一
CHATMERY_MODEL;若未來要省成本,可另設較小模型專做 deconstruct/提煉(如CHATMERY_EXTRACT_MODEL)。 - 寫入前再過濾:若模型回傳的某條過短(如 <5 字)、或明顯廢話(如「無」「沒有」),程式端可捨棄不寫入長期。
- 非同步:提煉可與回覆一樣在 background goroutine 執行,不擋使用者下一則訊息。
記憶流程概念定稿 v1