# AI 对话「目标丢失 / 意图丢失」诊断报告 > 日期:2026-06-26 > 触发:AI Chat 使用中,用户发送 Bug / 分析需求目标后,分析过程中目标丢失,系统不知道做什么、完全跑偏。 > 方法:直读对话数据库(`AppData/Roaming/top.1216.devflow/devflow-dev.db`)实测会话 + 源码机制走查。 > 性质:基于代码 + 数据库实证的机制级诊断(非模型分析猜测)。 --- ## 一、现场铁证(会话 `54c8b5bd`) | 指标 | 实测值 | 含义 | |---|---|---| | `prompt_tokens` | **4,809,714**(约 480 万) | 远超 GLM 1M 窗口,反复触发压缩 / 裁剪 | | 消息数 | 308 条 | 长 ReAct 链,工具结果堆积 | | 原始目标 `[seq5]` | `分析一下 灵感模块 存在的不足 [项目: DevFlow]`,`status=compressed` | **目标消息已被踢出 LLM 上下文**(`sanitize_messages` step0 过滤 `is_active`) | | 话题标记 `[seq0]` | `task → project`(active) | 系统判定「当前 project 话题」,但真实目标是 idea 域(灵感模块) | | 尾部 `[seq287–307]` | 连续 10+ 次 `search_files`,关键词 `auto-execute-mode / auto_execute / 全部接管 / autoExecute / execute-mode / execute_mode / auto-exec / 接管 / df-ai-auto`,**全部 `total:0` 空结果** | 失去目标后的游荡死循环 | **结论**:原始目标是「分析灵感模块存在的不足」,LLM 最终在反复搜索「自动执行模式 / 全部接管」——与目标毫无关系。目标彻底丢失。 --- ## 二、根因(机制级) ### 根因 1:上下文爆炸 → 目标消息物理出局(核心) - `df-ai/src/context.rs`:`sanitize_messages` step0 按 `is_active()` 过滤发送视图。目标 user 消息被 F-15 压缩标 `status=compressed` 后,**不再进入 LLM 上下文**。 - 目标仅靠**压缩摘要 system 消息**「续命」。`prompt.rs::compress_prompt` 四段式(意图 / 决策 / 文件 / 约束)+ 主题词锚点保留——但摘要是 **LLM 二次生成,信息降级严重**。「分析灵感模块不足」这类具体目标,在数次压缩后语义稀释到无法指导后续动作。 - 480 万 token 的会话,目标消息经历多轮压缩,保真度无法保证。 ### 根因 2:话题切换标记误判,反向强化错误方向 - `agentic/mod.rs:735-772`:`pending_topic_marker` 基于末两条 user 消息的 `IntentRecognizer` 关键词推断(双高置信 ≥0.7 才标),`insert_at(0)` 软提示 system「请以新话题为准」。 - 失效点: - 长链里 user 消息早被压缩出局,topic 推断基于**已失真历史**。 - 本例最后 active 标记是 `task→project`,与真实目标(灵感模块 / idea 域)**背离**——软提示反而告诉 LLM「现在是 project 话题」,帮倒忙。 - marker 只在 push **user 消息**时检测,工具轮次间不参与。 ### 根因 3:单链 ReAct,无目标重锚定(架构本质) - `df-ai/src/coordinator.rs`:**纯空壳 TODO**(B 路线占位,`AgentCoordinator::run` 直接返 `"TODO: Agent 协作结果"`)。 - `df-ai/src/planner.rs`:Plan DAG + Kahn 分层 + validate 齐全,但文件头明确「纯函数零 IO 零状态」「不接入 agentic loop,待 Phase B+C」。`PLANNING_ENABLED=true` 只门控**工具排序**(`filter_tool_defs_planned`),**不做多步规划执行**。 - agentic loop 每轮只在 push 新 user 消息时检测话题切换,**工具轮次间不重申目标**。没有「当前目标 + 进度」结构化状态,LLM 每轮自行决定下一步,长链必然游荡(`[seq287–307]` 实证)。 ### 根因 4:无探索熔断 - `[seq287–307]` 连续 10+ 次空结果不中断。系统不跟踪「已搜过什么 / 连续 N 次无进展」,LLM 无限换关键词。 - 这是目标丢失的**放大器**:不知道目标 → 不知道该停 → 无限游荡,token 失控(480 万)。 ### 根因 5:system prompt「聚焦准则」是文字说教,非机制 - `prompt.rs:104-108` 有「聚焦准则:始终围绕用户当前请求的核心目标」——纯 prompt 文字,靠 LLM 自觉。 - 目标一旦从上下文(消息流)消失,文字准则**无锚点可抓**。没有「每轮把目标钉在 system 顶部」的机制。 --- ## 三、为什么现有设计压不住 | 现有机制 | 性质 | 为什么压不住 | |---|---|---| | 压缩摘要(F-15) | **被动**信息降级 | 摘要保真靠 LLM,多轮压缩后目标语义稀释 | | 话题切换标记 | 软提示 + 关键词推断 | 基于失真历史,本例反向误导 | | 聚焦准则 prompt | 文字说教 | 目标消息出局后无锚点 | | `insert_at(0)` system 锚点 | 多个堆首位 | 话题标记 + 压缩摘要 + 关键词兜底三个锚点互相稀释 | 三个 `insert_at(0)`(话题标记 `agentic/mod.rs:762`、压缩摘要 `:918`、关键词兜底 `:969`)堆在首位,互相稀释,没有一个是「权威目标」。 --- ## 四、关联现状 - 当前分支 `conv-state-convergence` + `agentic/conv_state.rs`(452 行状态机)已在尝试收敛对话状态,**但目标作为一等状态尚未固化进状态机**——这是未完成的工作。 - memory `devflow-aichat-session-analysis-2026-06-22` 已标的「最高杠杆 P0-2 编排规划能力弱」即此问题的上层概括。本报告是其**数据库实证版**。 --- ## 五、方向建议(仅诊断,未实施) 最高杠杆:**把「用户当前目标」从消息流提升为一等结构化状态**。 1. **目标钉扎**:首轮提取用户目标为结构化字段(不依赖压缩摘要),每轮 agentic loop 顶部重注入 system。目标消息压缩出局后,结构化目标仍在。 2. **探索熔断**:跟踪连续无进展 / 空结果次数,超阈值强制「回顾目标」或停止,防游荡死循环 + token 失控。 3. **状态机收敛**:把目标 + 进度纳入 `conv_state.rs` 状态机(当前分支已在做),目标作为状态而非消息。 4. **弱化 / 修正话题标记**:话题标记基于失真历史且可能反向误导,宜降级或改为「目标漂移检测」而非 topic 关键词切换。 --- ## 附:待查 Bug - `[seq1]` 一条 LLM 内部独白("等等,`process_tool_calls` 是从 `super::audit` 导入的。让我检查一下…")被存为 `system` 消息(`status=active`)。疑似 reasoning / 思考内容泄漏进 system 消息(`stream_recv` 归位问题),进一步污染上下文。待独立排查。 --- ## 证据定位(源码) | 机制 | 位置 | |---|---| | 上下文压缩 / sanitize / topic 字段 | `crates/df-ai/src/context.rs` | | 话题切换 marker 消费 | `src-tauri/src/commands/ai/agentic/mod.rs:735-772` | | 压缩 insert_at 摘要 | `src-tauri/src/commands/ai/agentic/mod.rs:820, 918, 969` | | 多 Agent 协调(空壳) | `crates/df-ai/src/coordinator.rs` | | Plan 规划(未接入 loop) | `crates/df-ai/src/planner.rs` | | 意图识别(关键词) | `crates/df-ai/src/intent.rs` | | system prompt 聚焦准则 / 压缩 prompt | `src-tauri/src/commands/ai/prompt.rs:104, 233` | | 对话状态机(进行中) | `src-tauri/src/commands/ai/agentic/conv_state.rs` |