Files
DevFlow/docs/02-架构设计/构想审查/跑题改进试验记录-2026-06-20.md
绝尘 7911bc292c 文档: 审查回填 CR-22~27 + 跨端 AI Chat 设计 + 跑题试验记录
审查回填(均  PASS):
- CR-22 摘要不改 updated_at / CR-23 P2 批次A 读 / CR-24 批次B 写 / CR-25 跑题P0 /
  CR-26 跑题P1 / CR-27 跑题P2(6维度全过,topic 无破坏 + 双高置信保守)

跨端 AI Chat 设计(F-260620-01):
- 三层架构 df-tunnel/df-relay/df-miniapp + Rust 云后端选型(代码复用/类型一致/团队版演进)
- todo 规划跨端 P1-P4 + 跑题修复 P0-P2

跑题改进试验记录:
- db 基线(3 长对话:assistant 文本仅 4-5%,95% tool_result,47% echo)
- 5 类跑题现象与 P0-P2 五改进精准对应 + 四层测试计划 + 迭代过程
2026-06-20 03:54:59 +08:00

219 lines
14 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.
# AI Chat 跑题改进试验记录
> 创建2026-06-20
> 范围AI Chat 长对话「抓不住重点/跑题」根因治 — 测试计划 + 迭代过程 + 改进前基线 + 遗留
> 关联提交P0 `102d398` / P1 `013ce21` / P2 `a2db5c7`
> 关联设计:`意图识别层论证-2026-06-19.md` / `多主题上下文管理愿景-2026-06-19.md`
> 三原则对齐:优雅 / 可靠 / 易迭代
---
## 一、测试计划
四层覆盖,从机制单测到实跑场景逐层外扩。机制层已闭环,实跑层待人工验证。
### ① 单测(机制正确性)— 189 测,全过
| 模块 | 测数 | 覆盖点 |
|------|------|--------|
| `intent.rs` 意图识别 + filter | 43 | 空 subset 命中 / 置信三重 fallback<0.7、过滤<3、空 subset→全量/ 顺序漂移 / 工具收敛 29→5-10 |
| `context_helpers.rs` 压缩+工具压缩+tokenize | 18 | `extract_keyword_summary`全停用词、全漂移、top-10/ `should_summarize_tool_result`2KB 边界、占比 40% 边界)/ `extract_key_info`(错误行 error/panic/失败、首尾 5 行、空/短直回)/ **2-gram 汉字滑窗**"压缩架构"→"压缩/缩架/架构"、不跨边界) |
| `context.rs` 上下文+主题检测 | 32 | TrackedMessage.topic 推断 / `pending_topic_marker` 双高置信置位 / 任一 None 不标防误报 / take 消费 |
| `prompt.rs` 系统提示 | 6 | 中文「聚焦准则」段 / 英文「Focus」段 / 兜底 lang 回落 / 压缩 prompt 未波及回归保护 |
**df-ai crate 共 189 测全过**commit `a2db5c7` 自验:`cargo test -p df-ai` EXIT 0
### ② 苛刻测(边界/对抗agent 在跑)
针对每条机制的极端输入,验证不崩溃、不误报、有兜底:
- 全漂移user 消息全是无关内容 → 意图 Unknown → fallback 全量工具,不卡死)
- 全停用词(`extract_keyword_summary` 返回空字符串,不 panic
- 全错误行(`extract_key_info` 命中所有 error/panic 行,不超长)
- 2KB 边界(`should_summarize_tool_result` 恰好 2000/2001 字节,阈值判定稳定)
- 连续主题切换(连续两条 user topic 不同 → `pending_topic_marker` 只标末两条,不累积)
> 状态:部分已并入单测(见 `context_helpers.rs` 对抗段),其余 agent 审查阶段补跑。
### ③ db 基线分析(改进前跑题现象)— 本文 §三
挑 3 个长对话(均 600KB 量级glm-5.2),解析 messages JSON归类跑题现象作为改进前基线。
**结论:跑题主因是「工具结果挤占 + 全量工具分散 + 压缩丢主题」三类P0-P2 改进恰好对症。**
### ④ 实跑场景(重启 dev 对话验证)— 待人工执行
改进机制已测过LLM 实际响应效果需实跑验证。建议场景:
| 场景 | 验证改进 | 预期 |
|------|---------|------|
| 单主题长对话(连续 5+ 轮同一主题) | 改进3 压缩增强保留主题锚点 | 续接时不丢主线 |
| 主题切换(话题 A→B | 改进5 主题标记软提示 | 切换后不把旧话题带进新回答 |
| 多主题交织A/B 轮番) | 改进1 聚焦准则 + 改进5 | 始终围绕当前轮核心 |
| 大工具结果(>2KB / >10KB | 改进4 工具结果压缩 | tool_result 不挤占上下文 |
| 工具并发4-12 个并行) | 改进2 意图收敛 29→5-10 | LLM 可见工具收敛,不被工具列表稀释意图 |
---
## 二、迭代过程P0 → P1 → P2
三批改进,每批:根因 → 改进 → 单测 → 审查 → 效果。常量开关均可回退(调参退回接入前行为)。
### P0`102d398`)— 系统提示聚焦 + 意图接入 loop 收敛工具
**根因**
1. 系统 prompt 把「聚焦」混进「行为准则」段被稀释LLM 无独立抓手
2. loop 每轮把全量 29 个工具定义塞给 LLM工具列表本身稀释意图LLM 在 29 个工具里挑,而非围绕 user 目标)
**改进**
- 改进1 `prompt.rs``## 聚焦准则`(中)/ `## Focus`(英)独立段 4 条,机制描述("始终围绕当前请求核心目标""切换话题以最新为准""先结论后解释""不主动展开无关上下文"),不混进行为准则
- 改进2 `intent.rs` `filter_tool_defs` 按意图收敛工具 29→5-10`agentic:487` 三重 fallback置信<0.7 / 过滤后<3 / 空 subset → 回全量执行路径不变audit/execute 走完整 registryfilter 只改 LLM 可见 `tool_defs`
**单测**prompt 4中/英/兜底 lang/压缩未波及)+ intent filter 7空 subset/命中/漂移/顺序)= 11
**审查**CR-25🟡2Debug 加 Data 域 + threshold 注释失准)→ 已修 ✅ PASS
**常量开关**`INTENT_CONF_THRESHOLD = 0.7`(调 1.0 关闭收敛)
### P1`013ce21`)— 压缩增强 + 工具结果压缩
**根因**
3. `compress_old_messages` 压缩时丢主题词(用户反复提及的实体/技术名词是续接锚点),续接时 AI 找不回主线
4. tool_result 原样塞回上下文,>2KB 的搜索/读文件结果直接挤占 token基线95% 内容是 tool_result
**改进**
- 改进3 `context_helpers.rs` 压缩 prompt 加「主题/关键词保留段」;失败兜底从「裸裁剪」改 `extract_keyword_summary`user 消息词素 top-10 去停用词),首位插摘要作锚点
- 改进4 `should_summarize_tool_result`>2KB 或占比>40% 触发)+ `extract_key_info`(错误行 error/panic/失败 + 首尾各 5 行中间省略view-only 不改持久化(原始 tool_result 仍在 DB`build_for_request` clone 视图)
**单测**compress/keyword 2 + should_summarize + extract_key_info 14 = 16
**审查**CR-26🟡1tokenize 中文锚点弱:每汉字单成词素致"压缩/架构"2 字词被拆滤)→ P2 修 ✅ PASS
**常量开关**`KEYWORD_FALLBACK_ENABLED` / `TOOL_RESULT_COMPRESS_ENABLED`
### P2`a2db5c7`)— 主题检测保守 + tokenize 2-gram 汉字
**根因**
5. 主题切换无感知,切换后旧话题被带进新回答(基线 d6614e0b用户问"写文件为什么总写错日期"AI 仍在追旧话题"授权体验"的尾巴)
6. CR-26 🟡1汉字单字词素导致 2 字中文锚点("压缩""架构""审批")被 tokenize 拆滤,关键词摘要抓不住中文主题
**改进**
- 改进5 `context.rs` TrackedMessage.topic 字段push 推断 topic意图置信>=0.7 且非 Unknown+ `pending_topic_marker`(末两条 user topic 双高置信且不同才标,任一 None 不标防误报)+ loop 保守标记(`agentic:571` 顶部读 marker → insert system 软提示,不参与裁剪/压缩)
- tokenize 2-gram 汉字滑窗(`context_helpers.rs:294`):每汉字既单成词素又产出相邻 2-gram"压缩架构"→"压缩/缩架/架构"),非汉字边界重置窗口不跨边界组词
**单测**topic 检测 6 + tokenize 2-gram含不跨边界= 测并入 context 32 + context_helpers 增量
**审查**CR-26 🟡1 已闭环
**常量开关**`TOPIC_MARKER_ENABLED = true`false 跳过标记,排障/对比用)
**保守性**topic 不参与裁剪/压缩、TrackedMessage 不 Serialize只 ChatMessage 落库)、软提示非强制
### 三原则对齐
| 原则 | 落地 |
|------|------|
| **优雅** | filter 只改 LLM 可见 `tool_defs` 不动执行路径view-only 不改持久化topic 软提示不参与裁剪;常量开关可回退 |
| **可靠** | 三重 fallback意图置信/过滤数/空 subset压缩失败兜底关键词摘要view-only clone 视图topic 双高置信才标防误报 |
| **易迭代** | 4 个常量开关(`INTENT_CONF_THRESHOLD`/`KEYWORD_FALLBACK_ENABLED`/`TOOL_RESULT_COMPRESS_ENABLED`/`TOPIC_MARKER_ENABLED`)可独立开关排障;每批独立 commit + 审查回填tokenize 2-gram 是纯函数增量无破坏 |
---
## 三、改进前基线db 对话分析)
> 数据源:`C:/Users/23780/AppData/Roaming/top.1216.devflow/devflow-dev.db``ai_conversations.messages` JSON
> 挑样raw_len>500K 的长对话 3 个(均为 glm-5.2,改进前数据)
### 量化指标3 对话均值)
| 指标 | f89d129a | a95f5d6d | d6614e0b | 均值 |
|------|---------|---------|---------|------|
| 总消息数 | 251 | 213 | 211 | 225 |
| user / assistant / tool | 22 / 111 / 118 | 22 / 88 / 103 | 22 / 96 / 93 | 22 / 98 / 105 |
| tool_calls 总数 | 118 | 103 | 93 | 105 |
| 单轮 ≥3 工具并发 | 6 | 4 | 3 | 4 |
| tool_result >2KB | 39 | 34 | 44 | 39 |
| tool_result >10KB | 24 | 14 | 14 | 17 |
| **空 assistant纯工具 echo** | **69/111 (62%)** | **32/88 (36%)** | **41/96 (43%)** | **47%** |
| user 「继续」 | 5 | 2 | 0 | 2.3 |
| user ≤12 字短问 | 14/22 | 7/22 | 13/22 | 52% |
| **asst 文本 / tool 文本 比** | **0.05** | **0.04** | **0.05** | **0.05** |
**关键信号**
- **asst 文本仅占 4-5%**95% 上下文是 tool_result → 工具结果挤占严重改进4 对症)
- **47% assistant 轮次是纯工具 echo**content 空、只发 tool_calls→ LLM 不产出围绕 user 目标的文本被工具流程推着走改进1+2 对症)
- **单轮 4-12 工具并发** → 工具列表稀释意图改进2 收敛对症)
### 跑题现象归类5 类,含实例)
#### 类型1工具结果挤占最高频3/3 对话)
- **现象**tool_result 占 95% tokenasst 文本仅 4-5%。AI 回复被大块搜索/读文件结果淹没user 要的「结论」淹没在工具回显里。
- **实例**f89d129a [58]):用户问"我做哪些决策,多角度论证"AI 先并发 12 个工具读 4 个文件([9]-[49] 占 50+ 条消息),最后才在 [58] 一次性吐 6760 字决策分析。论证正确但被工具流程拖到 50 条消息后。
- **对症改进**P1 改进4 工具结果压缩(>2KB 触发 extract_key_info 保留错误行+首尾 5 行)。
#### 类型2全量工具分散意图
- **现象**:每轮把 29 个工具全塞 LLMAI 在工具列表里挑而非围绕 user 目标,表现为"读一堆无关文件试探"。
- **实例**d6614e0b [92]-[116]):用户问"消息发送交付功能"AI 并发 3 工具读 useAiEvents/useAiStream/useAiSend/useAiConversations/ai.ts/stream_recv/commands.rs/agentic.rs/persistence 9 个文件,最后才产出分析。
- **对症改进**P0 改进2 意图 filter_tool_defs 收敛 29→5-10。
#### 类型3压缩丢主题长对话续接跑题
- **现象**`compress_old_messages` 裁掉主题词后,续接时 AI 找不回主线,绕旧话题。
- **实例**d6614e0b [174]→[181]):用户问"最新 aichat 权限"AI 先读旧路径 `2025-07-14.md`(不存在),再搜索才发现文件已被手工改名为 `07-15`,绕了一圈。主题锚点("授权方案文件")在压缩中被丢。
- **对症改进**P1 改进3 压缩增强 + extract_keyword_summary 保留主题锚点。
#### 类型4多主题交织切换不干净
- **现象**用户切换话题AI 仍带旧话题尾巴进新回答。
- **实例**d6614e0b [140]→[153]):用户从"消息交付功能不足"切到"写文件为什么写错日期"AI 在 [141]-[152] 还在读 useAiSend/ai_tools 等旧话题文件,[153] 才答到日期根因。
- **对症改进**P2 改进5 主题检测 + pending_topic_marker 软提示。
#### 类型5无聚焦系统提示无独立抓手
- **现象**:系统 prompt 把「聚焦」混在「行为准则」被稀释AI 无明确"围绕当前请求核心"的指令约束。
- **实例**3 对话通用47% assistant 轮次纯工具 echo 不产出围绕 user 目标的文本。
- **对症改进**P0 改进1 系统提示独立聚焦段(中「聚焦准则」/ 英「Focus」4 条)。
### 基线小结
5 类跑题现象与 P0-P2 五条改进**一一对应**,改进设计精准对症基线,无遗漏主因。改进后预期:
| 基线现象 | 改进 | 机制测过 | 实跑预期 |
|---------|------|---------|---------|
| 工具结果挤占 | 改进4 | ✅ 14 测 | tool_result 压缩释放 token |
| 全量工具分散 | 改进2 | ✅ 7 测 | 工具收敛 29→5-10 |
| 压缩丢主题 | 改进3 | ✅ 2 测 | 主题锚点保留 |
| 多主题交织 | 改进5 | ✅ 6 测 | 切换软提示 |
| 无聚焦 | 改进1 | ✅ 4 测 | 独立聚焦段 |
---
## 四、遗留与风险
### 已知遗留
1. **LLM 实际响应效果需实跑验证** — 单测覆盖机制正确性filter/压缩/tokenize/topic 标记),但 LLM 在改进后 prompt + 收敛工具下的实际「抓重点」表现,需重启 dev 对话按 §一④ 场景实跑。机制正确 ≠ LLM 行为改善。
2. **主题检测 F1 天花板** — topic 推断依赖意图置信>=0.7(非 Unknown意图识别本身的准确率决定 topic 检测上限。短问(基线 52% user ≤12 字)意图置信常 <0.7,这类 topic 推断为 None不参与标记保守防误报的代价
3. **中文 tokenize 2-gram 仍有边界** — 3+ 字词("状态机""工作流")能由 2-gram 组合近似,但语义级词("推进链"3 字)仍可能被切;已优于单字方案,非完美。
### 未覆盖的跑题场景(建议补改进,基于基线)
基线 5 类已被 P0-P2 覆盖,未发现遗漏的**主因**。但有两类**次生现象**改进未直接覆盖,建议观察实跑后决定是否补:
1. **「继续」疲劳**f89d129a 5 次"继续")— AI 被工具流程拖到长尾user 不得不催。根因是工具流程过长类型1+2 的次生P0-P2 收敛工具+压缩后应缓解,但若实跑仍高频出现,可考虑加「单轮工具调用数硬上限」或「长工具流程中途主动给中间结论」。
2. **空 assistant 纯工具 echo**47%)— P0 改进1 聚焦段是软约束,不强制 assistant 每轮产出文本。若实跑 echo 率仍高,可考虑 prompt 加「工具调用前用一句话说明意图与当前请求的关系」的硬约束(当前基线已有"执行操作前简要说明你的意图",但未要求与当前请求关联)。
> 两项均为**次生/可选**,不阻塞当前迭代,建议实跑验证后再定。
---
## 附:数据可复现
db 分析脚本核心逻辑python sqlite3标准库
```python
import sqlite3, json
conn = sqlite3.connect(r'C:/Users/23780/AppData/Roaming/top.1216.devflow/devflow-dev.db')
# 按长度排长对话
conn.execute("SELECT id,title,LENGTH(messages) FROM ai_conversations ORDER BY 3 DESC LIMIT 5")
# 解析单对话
msgs = json.loads(row['messages'])
# 量化:空 assistantcontent 空但 tool_calls 非空)/ asst 文本 vs tool 文本比 / 单轮工具并发数
```
复现命令:见本任务分析脚本(已离线保存于 `/tmp/analyze_chat.py` + `/tmp/metrics.py`)。