驗(yàn)提煉與 MEMORY.md 記憶沉淀機(jī)制全解析)
OpenHuman Archivist 后臺知識館員會話歸檔、經(jīng)驗(yàn)提煉與 MEMORY.md 記憶沉淀機(jī)制全解析【免費(fèi)下載鏈接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/op/openhumanOpenHuman 的Archivist知識館員是一個在會話結(jié)束后于后臺運(yùn)行的專用 Agent負(fù)責(zé)把每一輪對話沉淀為可檢索的記憶資產(chǎn)回合索引寫入 FTS5 情景記憶表、經(jīng)驗(yàn)教訓(xùn)抽取與分類、知識庫文件 MEMORY.md 增量更新。本文以 Archivist 的系統(tǒng)提示詞prompt.md為骨架結(jié)合其 Agent 配置agent.toml、提示詞裝配器prompt.rs以及后端 Hook 實(shí)現(xiàn)hook_impl.rs、lifecycle.rs深入剖析 OpenHuman 的「會話 → 記憶」流水線幫助你理解其記憶系統(tǒng)如何做到低開銷、可檢索、防泄露、不重復(fù)。一、Archivist 是誰后臺知識館員的角色定位在 OpenHuman 的 Agent 注冊表中Archivist 被定義為一個典型的「后臺 輕量」Agent。它的when_to_use字段一句話點(diǎn)明使命Background librarian — extracts lessons from a completed session, updates MEMORY.md, and indexes to FTS5. Runs cheap and slow.后臺知識館員——從已完成的會話中提取經(jīng)驗(yàn)更新 MEMORY.md并索引到 FTS5。以低成本、低速度運(yùn)行。這段描述見 agent.toml揭示了三個關(guān)鍵設(shè)計(jì)意圖后臺觸發(fā)background true不占用前臺交互路徑低成本temperature 0.4低隨機(jī)性、輸出穩(wěn)定、max_iterations 3最多 3 輪工具循環(huán)防止無限迭代知識歸檔產(chǎn)出物橫跨兩類存儲——結(jié)構(gòu)化數(shù)據(jù)庫FTS5 情景記憶與人類可讀的 Markdown 知識庫MEMORY.md。系統(tǒng)提示詞把 Archivist 的全部職責(zé)收斂為三條明確指令I(lǐng)ndex turns— 將每一輪對話記錄到情景記憶FTS5中供未來檢索召回Extract lessons— 識別可復(fù)用的模式、需要規(guī)避的錯誤以及用戶偏好Update MEMORY.md— 將重要的學(xué)習(xí)成果追加到工作區(qū)知識庫。從源碼結(jié)構(gòu)看這三條職責(zé)分別對應(yīng)了三條獨(dú)立但聯(lián)動的實(shí)現(xiàn)路徑回合索引走ArchivistHook::on_turn_completehook_impl.rs經(jīng)驗(yàn)提煉走分段 recap 事件啟發(fā)式提取lifecycle.rs知識庫更新則通過白名單工具update_memory_md完成update_memory_md.rs。二、系統(tǒng)提示詞如何裝配prompt.md → 完整提示詞Archivist 的提示詞并非一段寫死的字符串而是由 prompt.rs 中的build()函數(shù)在運(yùn)行時(shí)動態(tài)拼裝而成通過include_str!(prompt.md)把本文的 archetype角色原型嵌入二進(jìn)制依次追加render_user_files(ctx)用戶可見文件、render_tools(ctx)可用工具清單與render_workspace(ctx)工作區(qū)上下文。這正是 OpenHuman「提示詞即產(chǎn)物」的設(shè)計(jì)理念——build()的輸出就是 LLM 最終看到的內(nèi)容Runner 不做任何二次加工見 prompt.rs 模塊注釋。這意味著 prompt.md 中每條規(guī)則都會原樣生效且工具清單由運(yùn)行時(shí)上下文決定而非硬編碼。對應(yīng)的單元測試 prompt_tests.rs 驗(yàn)證了build()在最小上下文空工具集、空工作區(qū)下也能產(chǎn)出非空提示詞保證該 Agent 在任何場景下都能被加載。三、agent.toml 運(yùn)行參數(shù)詳解agent.toml 是 Archivist 的完整運(yùn)行配置理解這些參數(shù)是自定義 Agent 的最佳范本配置項(xiàng)值含義與影響idarchivist注冊表中的唯一標(biāo)識delegate_namearchive_session編排器調(diào)用該子 Agent 時(shí)使用的委托名temperature0.4低隨機(jī)性保證歸檔內(nèi)容穩(wěn)定、可復(fù)現(xiàn)max_iterations3最多 3 輪工具調(diào)用循環(huán)防止后臺任務(wù)失控max_result_chars8000歸檔摘要回流到編排器的字?jǐn)?shù)上限約 2000 tokens與普通子 Agent 上限一致防止冗長的「記憶寫入確認(rèn)」撐爆編排器上下文issue #4099sandbox_modenone無需沙箱因?yàn)槠涔ぞ呒瘜?MEMORY.md / 寫數(shù)據(jù)庫本就受白名單約束backgroundtrue后臺運(yùn)行不阻塞主會話omit_identity/omit_memory_context/omit_safety_preambletrue跳過身份、記憶上下文與安全前言進(jìn)一步壓縮上下文開銷model.hintlocal優(yōu)先使用本地模型契合「便宜、慢速、后臺」的定位tools.namedupdate_memory_md、insert_sql_record、memory_store僅暴露三個寫工具權(quán)限面最小化值得強(qiáng)調(diào)的是tools.named的最小權(quán)限設(shè)計(jì)Archivist 只能通過update_memory_md寫 Markdown 知識庫、通過insert_sql_record寫 FTS5 表格、通過memory_store訪問記憶存儲——它沒有文件系統(tǒng)通用讀寫權(quán)限從機(jī)制上杜絕了后臺 Agent 越權(quán)操作工作區(qū)。四、職責(zé)一Index turns — 回合索引與情景記憶FTS5Archivist 的后端實(shí)現(xiàn)是一個PostTurnHook回合后鉤子核心入口是ArchivistHook::on_turn_completehook_impl.rs。每輪對話結(jié)束后它依次執(zhí)行寫入用戶回合把用戶消息作為一條EpisodicTurnroleuser插入 FTS5 情景記憶表insert_turn返回?cái)?shù)據(jù)庫分配的自增 ID寫入助手回合把助手回復(fù)作為第二條記錄寫入時(shí)間戳加0.001毫秒偏移確保同一輪內(nèi)「用戶在前、助手在后」的排序穩(wěn)定工具調(diào)用摘要tool_calls_json隨助手記錄一并落庫輕量教訓(xùn)提取若本輪存在失敗的工具調(diào)用則調(diào)用extract_lesson_from_tools生成一條純啟發(fā)式教訓(xùn)不消耗 LLM格式為Tools that failed in this turn: xxx, yyyhelpers.rs雙寫 md 歸檔同時(shí)把回合寫入workspace/memory_tree/content/episodic/session_id/seq:06.md的 md 備份存儲最佳努力模式寫失敗不阻斷回合為 FTS5 → md 的存儲遷移做并行驗(yàn)證hook_impl.rs。會話分段把長對話切成「知識單元」原始回合是零散的時(shí)間序列Archivist 通過**會話分段conversation segmentation**把同主題的回合聚合成 Segment為后續(xù) recap 提供邊界。分段判定由 boundary.rs 的detect_boundary()完成按「從便宜到昂貴」的順序執(zhí)行四重檢查boundary.rs檢查項(xiàng)判定條件默認(rèn)閾值TurnCountExceeded段內(nèi)回合數(shù)超上限max_turns_per_segment 20TimeGap相鄰回合間隔過長max_time_gap_secs 60010 分鐘ExplicitMarker回合以話題切換短語開頭如now lets、switching to、by the way,等內(nèi)置 15 個英文短語表EmbeddingDrift回合向量與段質(zhì)心的余弦相似度低于閾值min_cosine_similarity 0.4邊界判定產(chǎn)出BoundaryDecision::Continue繼續(xù)積累或Boundary::Boundary(reason)關(guān)閉當(dāng)前段、以當(dāng)前回合為起點(diǎn)新建段段 ID 形如seg-{uuid}。這個設(shè)計(jì)的精妙之處在于「便宜檢查先跑、貴檢查后跑」——一個回合若命中前三條任一規(guī)則就永遠(yuǎn)不會支付 embedding 比較的成本。五、職責(zé)二Extract lessons — 經(jīng)驗(yàn)提煉的三層漏斗Archivist 的教訓(xùn)提取不是單一機(jī)制而是「無 LLM 啟發(fā)式 → 啟發(fā)式事件 → LLM recap」的三層漏斗按成本從低到高排列第一層工具失敗教訓(xùn)零成本extract_lesson_from_tools純規(guī)則實(shí)現(xiàn)遍歷本輪工具調(diào)用記錄只要存在success false的調(diào)用就生成一條「哪些工具失敗」的教訓(xùn)。這是唯一逐輪執(zhí)行的教訓(xùn)提取因?yàn)樗幌娜魏瓮评碣Y源。第二層事件啟發(fā)式提取segment 關(guān)閉時(shí)在段關(guān)閉on_segment_closed時(shí)Archivist 對段內(nèi)所有用戶消息做句子切分按.!?換行符再與四組模式表做子串匹配events_heuristic.rsDecision決策如i decided、going with等模式Commitment承諾如i will、ill make sure等Preference偏好如i prefer、i like、i dont like等Fact事實(shí)如my name is、i work at、i live in、my timezone等。每個事件被寫入EpisodicEvent表confidence 固定 0.6其中Preference 與 Fact 事件還會二次寫入用戶畫像Profile Facets通過extract_profile_key取內(nèi)容前 4 個有意義的詞生成鍵與upsert_provider_facet合并置信度低的重復(fù)觀察不會覆蓋更強(qiáng)的舊記錄lifecycle.rs。第三層LLM 段摘要recap可回退每個被關(guān)閉的 Segment 都會產(chǎn)出一段摘要recap默認(rèn)使用summarization角色的推理模型生成見 lifecycle.rs 中RECAP_INFERENCE_ROLE常量。整個流程遵循軟回退契約若with_config階段探測到無法構(gòu)建summarization角色的模型則回退到啟發(fā)式摘要on_segment_closed永不返回 Err所有失敗只記日志不中斷回合recap 生成后持久化段摘要 → 調(diào)用 embedder 生成向量并寫入segment_embeddings段關(guān)閉時(shí)是唯一寫入點(diǎn)空摘要直接跳過以避免上游 embedding API 400→ 提取事件 → 更新畫像。這里有一個重要的**「證據(jù) vs 解讀」數(shù)據(jù)策略**在config.learning.chat_to_tree_enabled true時(shí)Archivist 會把該段的原始散文回合用戶 助手消息剝離工具調(diào)用 JSON以source_idconversations:agent整批灌入記憶樹而絕不把 LLM recap 喂給記憶樹——樹必須基于原始證據(jù)自己歸納否則就成了「對摘要再做摘要」lifecycle.rs。六、職責(zé)三Update MEMORY.md — 知識庫的并發(fā)安全寫入update_memory_md是 Archivist 更新工作區(qū)知識庫的唯一通道update_memory_md.rs其實(shí)現(xiàn)體現(xiàn)了 OpenHuman 對「后臺并發(fā)寫文件」這一危險(xiǎn)場景的完整防護(hù)白名單約束工具只能修改MEMORY.md與SKILL.mdALLOWED_FILES常量其他工作區(qū)文件一概拒絕進(jìn)程內(nèi)互斥每個工作區(qū)目錄對應(yīng)一把全局 async 互斥鎖以 canonicalize 后的路徑為鍵并發(fā)跑并行 fork、cron的歸檔寫操作排隊(duì)執(zhí)行而非互相覆蓋issue #4458跨進(jìn)程文件鎖由于 cron 通過獨(dú)立子進(jìn)程啟動進(jìn)程內(nèi)互斥鎖無法覆蓋因此再對工作區(qū)下的哨兵文件.memory-write.lock做flock獨(dú)占鎖阻塞式、運(yùn)行在線程池同時(shí)拒絕 symlink 鎖文件并用O_NOFOLLOW關(guān)閉 TOCTOU 窗口防止符號鏈接把鎖重定向到工作區(qū)之外原子寫入臨時(shí)文件 原子重命名進(jìn)程被 kill 也不會留下截?cái)辔募_@套機(jī)制與 prompt.md 中的Deduplicate規(guī)則形成「機(jī)制 智能」的雙保險(xiǎn)鎖保證寫入不互相破壞LLM 負(fù)責(zé)在追加前比對已有 MEMORY.md 內(nèi)容、避免重復(fù)條目。七、質(zhì)量規(guī)則五條提示詞紀(jì)律prompt.md 的 Rules 部分是 Archivist 輸出質(zhì)量的靈魂逐條展開規(guī)則含義落地方式Be concise教訓(xùn)濃縮為一兩句密集而非啰嗦max_result_chars 8000從物理上限制回流體量Be selective并非每輪都有教訓(xùn)只沉淀真正有用的觀察默認(rèn)只對工具失敗做逐輪啟發(fā)式提取其余留給段級 recapNever log secrets脫敏 API 密鑰、令牌、密碼與 PII由提示詞紀(jì)律約束配合 log_redaction 等安全機(jī)制Use categories按類型打標(biāo)簽pattern模式、mistake錯誤、preference偏好、fact事實(shí)與事件啟發(fā)式的 Decision/Commitment/Preference/Fact 分類一一呼應(yīng)Deduplicate追加前先查 MEMORY.md避免重復(fù)配合update_memory_md的讀-改-寫加鎖流程八、可配置開關(guān)learning 配置族Archivist 的行為并非硬編碼而是由 learning.rs 中的學(xué)習(xí)配置族統(tǒng)一開關(guān)以下參數(shù)均可通過learning配置節(jié)或環(huán)境變量覆蓋配置項(xiàng)默認(rèn)值作用環(huán)境變量覆蓋episodic_capture_enabledtrue情景捕獲總開關(guān)即使learning.enabled關(guān)閉也保持活動情景記憶是對話回合的系統(tǒng)事實(shí)來源OPENHUMAN_LEARNING_EPISODIC_CAPTURE_ENABLED0\|1chat_to_tree_enabledtrue是否把對話原始回合灌入記憶樹conversations:agent—goals_enrichment_enabledtrue段關(guān)閉后是否后臺觸發(fā)goals_agent刷新長期目標(biāo)清單MEMORY_GOALS.mdOPENHUMAN_LEARNING_GOALS_ENRICHMENT_ENABLED0\|1stm_recall_enabledtrue是否在會話開始注入跨會話的近期情景召回FTS5 關(guān)鍵詞 cosine 段摘要OPENHUMAN_LEARNING_STM_RECALL_ENABLED0\|1explicit_preferences_enabledtrue顯式固定偏好是否注入系統(tǒng)提示詞OPENHUMAN_LEARNING_EXPLICIT_PREFERENCES_ENABLED0\|1注意learning.enabled默認(rèn)是false而episodic_capture_enabled默認(rèn)true——這體現(xiàn)了「情景記憶是獨(dú)立于推理學(xué)習(xí)棧的基礎(chǔ)設(shè)施」這一架構(gòu)判斷即使關(guān)閉反射/穩(wěn)定性檢測等推理組件對話歸檔依然持續(xù)運(yùn)轉(zhuǎn)。九、會話收尾flush 保證最后一段不丟失一個容易被忽略的邊界情況是會話結(jié)束時(shí)往往沒有一個觸發(fā)邊界的回合導(dǎo)致最后一個 Segment 永遠(yuǎn)處于 open 狀態(tài)、得不到 recap。Archivist 通過flush_open_segment解決lifecycle.rs在會話結(jié)束Agent::spawn_session_memory_extraction時(shí)強(qiáng)制關(guān)閉殘留的 open segment并走與正常段關(guān)閉完全相同的路徑——recap embedding 事件提取 樹灌入。該操作冪等段只會從open → closed遷移一次可安全重復(fù)調(diào)用。十、小結(jié)一條完整的「會話 → 知識」流水線將以上機(jī)制串聯(lián)一次會話在 OpenHuman 中的記憶沉淀路徑是逐輪on_turn_complete將用戶/助手回合寫入 FTS5 情景表雙寫 md 歸檔工具失敗生成零成本教訓(xùn)分段detect_boundary按回合數(shù)、時(shí)間間隔、話題短語、向量漂移四重檢查切分 Segment段關(guān)閉LLM recap或啟發(fā)式回退→ 段摘要與 embedding 落庫 → 啟發(fā)式事件提取 → 畫像 Facet 合并 → 原始散文灌入記憶樹 → 后臺刷新長期目標(biāo)知識庫update_memory_md以白名單 進(jìn)程內(nèi)鎖 跨進(jìn)程 flock 原子重命名的方式安全追加 MEMORY.md/SKILL.md會話結(jié)束flush_open_segment兜底收尾最后一個開放段。Archivist 的設(shè)計(jì)核心可以概括為三句話用便宜機(jī)制做逐輪工作用昂貴機(jī)制做段級工作用并發(fā)安全機(jī)制做文件寫入。如果你想在 OpenHuman 中自定義類似的后臺記憶 Agentagent.toml 的「background 最小工具集 低 temperature max_result_chars 限流」組合加上 prompt.md 的「職責(zé) 規(guī)則」雙層結(jié)構(gòu)是一份可以直接復(fù)用的模板。【免費(fèi)下載鏈接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/op/openhuman創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考