對齊:對話記憶與背版—設計、對話記憶系統—彙整與探討 共識。
狀態圖例:✅ 已完成 ⬜ 未實作 🟡 部分完成
| 狀態 | 階段 | 目標 | 產出/改動 |
|---|---|---|---|
| ⬜ | 階段 1 | 固定背版(identity)只讀,回覆時帶入 context | 背版讀取模組、對話流程接線 |
| ⬜ | 階段 2 | archival 儲存+寫入+檢索,回覆前 top-k 注入 | 儲存結構、Load/Save、Insert、Search、對話流程接線;可選 embedding |
| ⬜ | 階段 3 | blocks 可更新(summary/relationship) | 背版 JSON 或 store、定時/觸發整理 |
以下為粉碎性步驟:每步對應「做什麼 → 模組/API/型別」。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 1.1.1 | 新增背版讀取模組 | 只做「讀取/組裝」背版,不寫入。 |
| ⬜ | 1.1.2 | 定義 GetIdentity(subject_id) string 或等價 |
回傳該主體的 identity 字串(1~3 句)。 |
| ⬜ | 1.1.3 | 無自訂時回傳預設(例如從設定檔或固定字串) | 控制總長度數十字~百字。 |
| ⬜ | 1.1.4 | 單元測試:有/無背版資料時回傳符合預期 | 驗收:能取得 identity 字串。 |
產出:呼叫 GetIdentity(subject_id) 即可取得該主體的 identity 字串。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 1.2.1 | 在處理「使用者輸入→回覆」的流程中,在組 prompt 前取得背版:backstory := GetIdentity(subject_id) |
回覆時傳入背版。 |
| ⬜ | 1.2.2 | 組 prompt 時新增參數 backstory string |
可先僅傳入 system/context,預留給模型用。 |
| ⬜ | 1.2.3 | 若 backstory != "",將該字串納入 system 或 context |
完成接線。 |
產出:每次回覆都能取得並傳入該主體的 identity。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 1.3.1 | 定義 GenerateReply(userInput, backstory string, memorySnippets []string, context map) (reply string, err error) |
介面先存在,內部可先 fallback 或 stub。 |
| ⬜ | 1.3.2 | 在對話流程:若啟用則呼叫上述介面;err 或 reply 空則 fallback 既有邏輯 | 背版與記憶片段可傳入。 |
產出:背版字串可傳入生成介面;記憶片段階段 2 再填。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 3.1.1 | 定義單條記憶結構:ArchivalEntry { SubjectID, Content, Tag, CreatedAt };Tag 可為 fact/preference/event/user_xxx |
與設計 §四對齊。 |
| ⬜ | 3.1.2 | 決定儲存後端:A 單一 JSON 檔(陣列,依 subject_id 分區查詢);B JSONL 逐行 append;C 關聯式表 | 建議先 A 或 B:一檔一表,實作簡單。 |
| ⬜ | 3.1.3 | 實作 LoadArchival(path) ([]ArchivalEntry, error)、SaveArchival(path, entries) error 或等價讀寫 |
讀寫分離,方便測試。 |
產出:可依 subject_id 取得該主體全部記憶條目、可 append 新條目並持久化。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 3.2.1 | 定義 InsertArchival(subject_id, content, tag string) error:組 ArchivalEntry、append 至儲存、寫回 |
tag 可選,空則 "" 或 "event"。 |
| ⬜ | 3.2.2 | 節流:同一 subject_id 在「同一場對話」內寫入上限 M 條(如 M=5);可在對話 session 中計數 | 對應對話記憶系統 §7.4。 |
產出:對話結束或本輪結束時可呼叫 InsertArchival(subject_id, content, tag) 寫入 1~3 條。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 3.3.1 | 定義 SearchArchival(subject_id string, query string, topK int) ([]string, error) 回傳該主體的記憶內容字串(最多 topK 條) |
介面先定。 |
| ⬜ | 3.3.2 | 簡易版(無 embedding):該 subject_id 全部條目依 CreatedAt 倒序取前 topK 條,或依 query 關鍵字過濾後再取 topK |
階段 2 可先上線。 |
| ⬜ | 3.3.3 | 語意版(可選):對每條 Content 做 embedding;query 做 embedding;用餘弦相似度排序取 topK;需 embedding 模型(如本地 bge-m3)與向量儲存 |
設計 doc 提及可本地。 |
| ⬜ | 3.3.4 | 在組 prompt 前:snippets, _ := SearchArchival(subject_id, userInput, 5);將 snippets 傳入背版或 GenerateReply |
完成「回覆前檢索 → 注入 context」。 |
產出:回覆前能依 subject_id 與使用者輸入(或最近一句)取回 top-k 記憶並帶入 prompt。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 3.4.1 | 在回覆成功後,呼叫「本輪寫入」:例如 AfterTurnWriteMemory(subject_id, user_id, userInput, reply) |
可抽成獨立函式。 |
| ⬜ | 3.4.2 | AfterTurnWriteMemory 內:以規則組 1 條內容(例如「使用者說:{userInput};回覆:{reply}」縮寫),或呼叫 LLM 抽取一句「要旨」;然後 InsertArchival(subject_id, content, "event") |
階段 2 可先用規則寫 1 條。 |
| ⬜ | 3.4.3 | 節流:同一 session(同 subject + 同 user)本場最多寫 M 條(如 5);超過則只累積不寫,或對話結束時再合併成 1 條 | 對應 §7.4 寫入節流。 |
產出:對話結束或本輪結束時可寫入 1~3 條至該主體的 archival;再次對話時能被檢索到。
| 狀態 | 步驟 | 動作 | 說明 |
|---|---|---|---|
| ⬜ | 4.1 | 定義背版 blocks 儲存:BackstoryBlocks { SubjectID, Identity, Summary, Relationship };Identity 可繼續由 GetIdentity 算出或改為從此讀取 |
與設計 §四對照。 |
| ⬜ | 4.2 | 實作 GetBackstoryBlocks(subject_id) *BackstoryBlocks、UpdateBackstoryBlock(subject_id, blockName, content string) |
讀取時 Identity 可覆寫為 blocks 內值(若有)。 |
| ⬜ | 4.3 | 觸發更新:每 N 次對話或定時,將該主體的 archival 最近若干條交給 LLM 產出 summary/relationship 摘要,再呼叫 UpdateBackstoryBlock | 設計 doc 階段 3。 |
| ⬜ | 4.4 | 組 prompt 時改為:背版 = GetBackstoryBlocks 的 Identity + Summary + Relationship(若無則 Summary/Relationship 空);其餘同階段 2 | 背版「會長大」。 |
| 狀態 | 序 | 項目 | 時機 |
|---|---|---|---|
| ⬜ | 1 | 背版讀取模組(GetIdentity) | 階段 1.1 |
| ⬜ | 2 | 對話流程接線(背版帶入) | 階段 1.2 |
| ⬜ | 3 | 生成介面插槽(可選) | 階段 1.3 |
| ⬜ | 4 | archival 儲存結構 + Load/Save + Insert | 階段 3.1~3.2 |
| ⬜ | 5 | 資料檔(如 archival.json 或 archival.jsonl) |
階段 3.1(首次寫入時建立) |
| ⬜ | 6 | 對話結束寫入 + 節流(AfterTurnWriteMemory) | 階段 3.4 |
| ⬜ | 7 | SearchArchival(簡易版 → 可選語意版) | 階段 3.3 |
| ⬜ | 8 | BackstoryBlocks 儲存與更新 | 階段 4 |
1.1 背版讀取(GetIdentity)
→ 1.2 對話流程帶入 backstory
→ 1.3(可選)生成介面 stub
3.1 archival 儲存結構 + Load/Save
→ 3.2 InsertArchival
→ 3.3 SearchArchival(簡易版)
→ 3.4 AfterTurnWriteMemory + 節流
→ 3.3 語意版(可選)
| 狀態 | 驗收項 | 對應步驟 |
|---|---|---|
| ⬜ | 記憶1:回覆前能依 subject_id 取回背版+top-k 記憶 | 1.1 GetIdentity、3.1~3.3 儲存與 SearchArchival、1.2/3.3.4 接線 |
| ⬜ | 記憶2:對話結束能將 1~3 條寫入該主體的 archival | 3.1~3.2 儲存與 InsertArchival、3.4 AfterTurnWriteMemory |
| ⬜ | 記憶3:同一 subject_id 再次對話能檢索到前次寫入 | 3.3 SearchArchival、3.4 寫入;端到端測試 |
對話記憶與背版實作步驟 v1