Files
DevFlow/docs/05-代码审查/aichat知识库与记忆走查-2026-09-29.md
lxy dfa38f6259 修复: 上下文记忆与工作流注入生产侧空壳接通
WorkingContext 写入链落地(用户轮目标钉扎+压缩后 JSON 卡片回填重锚定,含 6 单测);
工作流 DAG 摘要注入生产侧接通(AI 路径启动写入+终态回写,审批调用点透传会话)。
附知识库与记忆走查诊断(「笨/丢历史」根因:消息压缩视图丢失+知识检索四重收口),
todo 登记修复分档(含随批补登 09-28 交互走查索引条目)。
2026-09-29 13:28:56 +08:00

6.8 KiB
Raw Permalink Blame History

aichat 知识库与记忆能力走查 — 用户反馈「笨/丢历史会话」根因诊断

日期: 2026-09-29 | 触发: 用户反馈「明显感觉丢历史会话特别严重」「感觉很笨」 方法: 双代理只读走查(知识库链路/记忆四层) + 运行时 DB 实证(devflow.db 副本只读查询) 结论处置: 会话内上下文生产侧已修复(同日实施,见文末);跨会话召回/知识检索收口登记待办


一、DB 实证(核心证据)

数据源: %APPDATA%/top.1216.devflow/devflow.db 副本(104MB,82 会话/10647 消息)。

指标 数值 含义
compressed 消息占比 4758/10647 (44.7%) 压缩是常态而非例外
user 消息被压缩 363/892 (41%) 四成用户请求模型看不到
最大会话 5fea6024 828 条消息,模型可见仅 44 条 (5%) 26 条用户消息 0 条可见
user 可见率最差大会话 Top4 0b0a46e5: 0/6 · 5c3bc8a0: 0/8 · 5fea6024: 0/26 · f64dee94: 0/39 「我说过的话他全忘了」属实
compressed 原文保留 363 条全部非空 存储没丢,丢的是发送视图
四段式压缩摘要落库 仅 1 条 大量压缩走关键词兜底/旧格式,摘要质量无保障

定性: 丢历史会话 = 机制性视图丢失(DB 单向 compressed 标记永不回 LLM 上下文),不是存储损坏。压缩触发阈值 0.6×可用预算,长会话大半历史必然出局;摘要 ≤1024 token 替代全部被压缩内容,且 user 原话不保证进摘要。

二、知识库链路: 四重收口(管道铺好,水龙头拧死)

代码事实(走查证据,均为当前 HEAD 实核):

  1. 整句 LIKE 检索(最致命): 检索 query=末条用户消息全文,idea_repo.rs:640-661 用 %整句% 做 LIKE——知识标题是短语,整句子串匹配命中率≈0。自动注入即使有已发布知识也几乎空转。
  2. candidate↔published 断链: 自动提炼(knowledge_inject.rs:441+)与 MCP insert_knowledge 产物全是 status='candidate';检索只认 'published'(idea_repo.rs:651)。不手动去 /knowledge 页发布,沉淀的知识(现库 962 条!)永不进对话。reuse_count 排序形同虚设。
  3. 语义检索默认关: vector_enabled=false(knowledge_config.rs:58),需手配 embedding provider;默认纯 LIKE,中文同义表达必漏。
  4. LLM 零知识工具: tool_registry.rs 73 个工具无任何 knowledge 注册;9eb2995 的 search/insert_knowledge 挂在 df-mcp(127.0.0.1:18765)只服务外部 MCP 客户端,ai-chat 自己的 agentic loop 不接。「记住这个」只会落进对话文本,会话结束即散。

次要: 注入剂量 top-3×500 字符;source_project 存而不用于检索过滤;提炼只看最后 6 条消息且每会话仅 1 次。

知识维度总评: 管道全部 wired(auto_inject 默认开),但四重收口使普通对话实际获得知识的概率趋近于零。

三、记忆能力分层盘点

层 现状 判定
L1 轮内 全量历史进请求,预算≈102k token,namespace 大结果引用化 ✅ wired
L2 跨轮 两道丢失闸门: ①单向压缩(保护最近 6 条,其余换 ≤1024 token 摘要,不可逆);②超预算视图裁剪无摘要补偿(只保最近 6 条) ⚠️ 半残
L3 跨会话 零召回: 新会话全空,无全局摘要/项目记忆/跨会话检索,完全隔离 ❌ 空壳
L4 跨重启 恢复消息(compressed 仍是压缩态)+pinned_goals;不恢复: working_context/namespace_store(重启清空)/agent_language/session_trust ⚠️ 半残

空壳机制(有代码无调用方/断链):

  • MemoryAdapter(df-ai/src/memory_adapter.rs): 语义记忆 trait,全仓零调用方,注释中的 VectorMemoryAdapter 不存在。
  • Persona 人设(5 内置人设+prompt 模板): 唯一实例化点在两个默认关闭的实验门内,不进正常对话链路,无持久化。
  • 跨会话记忆: 无任何机制——这是「丢历史会话」主观感受的最大来源(与 DB 实证互为表里: 同会话压缩出局 + 跨会话零召回 + 重启再丢一层)。
  • DB 落库截断: >8192 字符的 user/assistant 文本落库截为 前3072+后3072+省略标记(conversation.rs:101-119)——重启后连原文都只剩骨架。

四、本次已修(同日实施批,已过编译门禁)

「上下文管理演进」07-20 设计中 T4/T5 的生产侧空壳补齐(消费侧早已落地但无数据源):

  • T5 WorkingContext 写方法(df-ai/context_helpers.rs): begin_turn(新用户轮目标钉扎)+sync_after_compress(压缩后从 T3 JSON 卡片回填决策+重锚定)+reset_all 实现,6 个新单测全绿。
  • T5 接线: chat.rs:651/1978 用户消息入库点 begin_turn;context_lifecycle.rs:278 压缩成功分支 sync_after_compress(TODO 清零)。效果: 压缩不再裸丢目标/决策,下轮 system prompt 重锚定。
  • T4 生产侧: workflow.rs::run_workflow_inner 增加 conv_id 参数,AI 路径启动写 workflow_id+workflow_dag_summary,终态回写完成/失败摘要;chat.rs:896/1278 审批调用点透传。休眠链路闭环。

门禁: cargo check --workspace 0 错误;cargo test -p df-ai 494 过/4 挂(4 挂均在 anthropic_compat/model_fetch_helpers,本批零触碰的存量失败,见待办)。

边界说明: 本批只解「会话内压缩后目标/决策丢失」一块。跨会话零召回、知识四重收口、重启失忆均未动,登记待办。

五、待办分档(修复方向,未实施)

P0(直接治「笨」):

  1. 知识检索去整句 LIKE: 分词/抽关键词后多条件 OR,或默认开语义检索(补 embedding 配置引导)。改动点 idea_repo.rs:640-661 + knowledge_inject.rs:364-384。
  2. candidate 断链打通: 自动提炼产物到阈值 confidence/reuse 自动晋升 published(或检索纳入高置信 candidate),人工审核保留为可选。
  3. 视图裁剪补摘要: 超预算淘汰单元被丢弃时生成滚动补偿摘要(现在无声丢失)。

P1: 4. LLM 知识工具: tool_registry 注册 search_knowledge/insert_knowledge(复用 df-mcp 实现),让 agent 能按需查/存。 5. 跨会话召回最小闭环: 项目级记忆条目(知识表已有 source_project 字段)+会话结束时提炼进知识库(现有 auto_extract 扩为跨会话通道)。 6. 存量测试修复: anthropic_compat::anthropic_full_stream_accumulates_usage(assert usage.is_none() 失败)+model_fetch_helpers::non_chat_sensenova_u1_image_filtered 等 4 个,疑似 6bafdcd 流式 usage 语义变更后未同步测试。

P2: 7. DB 截断放宽/取消(user 原话平均 41 字,3072 截断对 user 无必要,主要风险在工具结果;可分 role 定阈值)。 8. namespace 持久化或重建(DB 原文在,重启可懒重建,免「已超出内存上限」占位)。 9. 兜底压缩路径接 sync_after_compress("")(当前取舍: 不接,防丢决策态;待版本计数漂移观察后复议)。