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

14 KiB
Raw Permalink Blame History

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_result2KB 边界、占比 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

三批改进,每批:根因 → 改进 → 单测 → 审查 → 效果。常量开关均可回退(调参退回接入前行为)。

P0102d398)— 系统提示聚焦 + 意图接入 loop 收敛工具

根因

  1. 系统 prompt 把「聚焦」混进「行为准则」段被稀释LLM 无独立抓手
  2. loop 每轮把全量 29 个工具定义塞给 LLM工具列表本身稀释意图LLM 在 29 个工具里挑,而非围绕 user 目标)

改进

  • 改进1 prompt.rs## 聚焦准则(中)/ ## Focus(英)独立段 4 条,机制描述("始终围绕当前请求核心目标""切换话题以最新为准""先结论后解释""不主动展开无关上下文"),不混进行为准则
  • 改进2 intent.rs filter_tool_defs 按意图收敛工具 29→5-10agentic: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 关闭收敛)

P1013ce21)— 压缩增强 + 工具结果压缩

根因 3. compress_old_messages 压缩时丢主题词(用户反复提及的实体/技术名词是续接锚点),续接时 AI 找不回主线 4. tool_result 原样塞回上下文,>2KB 的搜索/读文件结果直接挤占 token基线95% 内容是 tool_result

改进

  • 改进3 context_helpers.rs 压缩 prompt 加「主题/关键词保留段」;失败兜底从「裸裁剪」改 extract_keyword_summaryuser 消息词素 top-10 去停用词),首位插摘要作锚点
  • 改进4 should_summarize_tool_result>2KB 或占比>40% 触发)+ extract_key_info(错误行 error/panic/失败 + 首尾各 5 行中间省略view-only 不改持久化(原始 tool_result 仍在 DBbuild_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

P2a2db5c7)— 主题检测保守 + 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 = truefalse 跳过标记,排障/对比用) 保守性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.dbai_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 轮次是纯工具 echocontent 空、只发 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 纯工具 echo47%)— P0 改进1 聚焦段是软约束,不强制 assistant 每轮产出文本。若实跑 echo 率仍高,可考虑 prompt 加「工具调用前用一句话说明意图与当前请求的关系」的硬约束(当前基线已有"执行操作前简要说明你的意图",但未要求与当前请求关联)。

两项均为次生/可选,不阻塞当前迭代,建议实跑验证后再定。


附:数据可复现

db 分析脚本核心逻辑python sqlite3标准库

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)。