前言¶
DeepSeek Harness(DSH)裏,模型上下文沒有天然的長期記憶。常見做法要麼把整段歷史塞進 prompt,token 隨對話線性增長;要麼讓模型自己「回想」,容易編造細節。社區插件 dsh-time-memory(倉庫名 Moontail-Ling/dsh-time-memory,維護者 Moontail-Ling)換了一條路:對話按發生時間寫成磁盤上的事件,只有用戶點名的那段時間纔會被檢索進上下文;兩次擴大仍無命中時,只允許回答「我忘記了」,不推測、不編造。
這是什麼¶
dsh-time-memory 是 DSH 分類爲「記憶」的插件 bundle。它給會話註冊 memory_recall 與 memory_save 兩個工具,並可選附帶「時憶」人格:回答與檢索相關的問題前,會先輸出幾行 [調試] 自檢,把「時間錨點 → 檢索層數 → 命中數 → 判定」攤開可見。
記憶默認落在 $DSH_HOME/time-memory/events.jsonl(未設置 $DSH_HOME 時,Windows 上爲 %USERPROFILE%\.dsh\time-memory\events.jsonl),一行一條 JSON;插件不導入 DSH 包,只依賴 Node 內置模塊。當前 package.json 版本爲 0.1.0,許可證 MIT,Node 僅在跑離線測試時需要 ≥ 22.19。
三條由代碼保證的規則¶
README 把行爲歸納成三條,不靠模型自覺:
- 按時間存 —— 每條真實的用戶消息與助手回覆,按事件時間寫入 jsonl(
capture默認開啓)。 - 按時間查 —— 用戶提到時間段時,應先調用
memory_recall。 - 查不到就說忘了 ——
maxExpansions次擴大仍無結果時,verdict="forgot",人格只能回答「我忘記了」。
檢索流程¶
用戶通過 time_hint 指認時間(共 26 種說法,含相對、周曆、時段、絕對日期與整句摳時間)。檢索在時間窗內用關鍵詞打分(中文按二元組切詞),不是向量語義檢索。
| 層 | 窗口 | 結果 |
|---|---|---|
| 第 0 層 | 用戶指認的時段 | 命中即返回 |
| 第 1 層 | 以窗口中心等比擴大 × expandFactor(默認 3) |
命中即返回,並標註擴大 1 次 |
| 第 2 層 | 再擴大一次(默認 1 天 → 3 天 → 9 天) | 命中即返回 |
| 兩次擴大後仍空 | — | verdict="forgot" |
| 時間說法解析不了 | — | verdict="unparsed",提示改用 2026-10-20 這類寫法 |
典型調試輸出形態如下(摘自 README):
[記憶檢索] 時間錨點:"上週二" → 2026-10-20(週二)全天
[記憶檢索] 線索:海邊
[記憶檢索] 第 0 層(原始時段):2026-10-20(週二)全天 · 庫內 3 條 · 命中 0 條 → 擴大
[記憶檢索] 第 1 層(擴大 1 次):2026-10-19 至 2026-10-21(3 天) · 庫內 9 條 · 命中 1 條
[記憶檢索] 說明:原始時段沒有命中,擴大 1 次後才找到,引用時要說明大致範圍。
[記憶] 2026-10-20 20:14 · 用戶:我說想去海邊看日出,風很大
兩個工具¶
裝好後正常聊天即可;說起某段時間會自動走檢索,值得單獨記的事可由模型調用 memory_save 釘在指定時間點。PTC 代碼也可直接調用同一套工具。
| 工具 | 參數 | 作用 |
|---|---|---|
memory_recall |
time_hint(必填)、query、limit |
按時間段 + 關鍵詞檢索,自帶分層擴大與忘記判定 |
memory_save |
summary(必填)、happened_at、details、tags |
手工歸檔一條事件到指定時間點 |
安裝與啓用¶
前提:DeepSeek Harness(Desktop 或源碼 checkout)已能正常使用。
官方 README 給出的安裝步驟是先克隆倉庫,再在 DSH Web GUI 裏指向本地目錄(資料中沒有 dsh plugin add github:… 一類命令):
git clone https://github.com/Moontail-Ling/dsh-time-memory.git
然後在 DSH 裏:
- 側邊欄 插件 頁 → 安裝;
- 粘貼克隆下來的絕對路徑,例如
D:\code\dsh-time-memory; - 確認,插件默認啓用。
裝完對當前 profile 的所有會話生效(啓用 HMR 時熱加載,否則重啓 DSH)。Creator 模式下也可用 plugin_manager 的 install_bundle,target 填同一路徑。卸載時在插件頁移除 bundle 即可,記憶文件不會被刪。
插件以當前 DSH 進程權限運行;安裝前應自行查看倉庫源碼與 MIT 許可證,確認路徑與數據文件位置可接受。
配置¶
在 profile 的 cordis.patch.yml 中覆蓋 time-memory 條目,例如:
- id: time-memory
name: dsh-time-memory
config:
dataFile: 'D:\my-memories\events.jsonl'
expandFactor: 3
maxExpansions: 2
常用字段(完整表見 README):
| 字段 | 默認值 | 含義 |
|---|---|---|
dataFile |
$DSH_HOME/time-memory/events.jsonl |
記憶庫 jsonl |
capture |
true |
是否自動把對話按時間入庫 |
expandFactor |
3 |
每次擴大窗口的倍數 |
maxExpansions |
2 |
最多擴大幾次 |
maxResults |
3 |
單次最多返回幾條記憶 |
minScore |
2 |
關鍵詞命中閾值 |
includePersona |
true |
是否把人設放進 charter |
人格是 profile 級的;若只想在某類會話啓用,把 time-memory 放進對應 agent preset 的 patch。檢索是「時間窗 + 關鍵詞」,換說法(如「看海」與「海邊」)可能不中;擴大窗口只能兜時間偏差,兜不住詞義偏差。
token 與記憶文件¶
README 說明:人格、認知、協議爲靜態文本,穩態下可命中前綴緩存;單次檢索輸出有上界(默認約 3 條 × 90 字),成本與庫大小無關,但多一輪工具調用。記憶庫很小時,直接滾上下文可能更省 token——本插件買的是按時間精確定位與不隨庫增長。
jsonl 單行示例:
{"v":1,"id":"m_…","t":1792500000000,"kind":"user","text":"……","session":"…","seq":42,"source":"auto","stored":1792500000123}
同一會話同一條事件用 session + seq 去重;清空記憶需在停掉插件後刪除該文件。
離線測試(不依賴 DSH):
node test/run.mjs
結尾¶
dsh-time-memory 把聊天記憶做成時間軸上的事件庫:先查用戶點名的時段,沒命中就擴大兩次,仍沒有就如實忘記。適合需要「按時間段回憶、控制上下文體積、禁止瞎編歷史」的 DSH 用戶。
- 社區目錄頁:https://www.skillhub.cn/plugins/Moontail-Ling/dsh-time-memory
- 源碼與完整文檔:https://github.com/Moontail-Ling/dsh-time-memory
DSH 生態強調「一切皆插件」;SkillHub 等社區目錄爲獨立站點,與 DeepSeek / 幻方無官方從屬關係。