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

81 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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("")(当前取舍: 不接,防丢决策态;待版本计数漂移观察后复议)。