新增: AI 对话目标钉扎+探索熔断+话题标记降级
治 AI Chat 目标丢失/意图丢失(实测会话 480万token,目标消息被压缩出局,LLM 尾部盲搜死循环): - G1 目标钉扎:首条 user 目标提取存 PerConvState.pinned_goal,run_agentic_loop 入口拼进 system_prompt 尾部(loop 不变量,免疫 F-15 压缩/裁剪/sanitize,治目标物理出局) - G2 探索熔断:连续 N 次空结果无进展 → 两段式警示 + AiHelpRequired 熔断(治游荡死循环) - G4 话题标记降级:pinned_goal 存在时跳过 topic marker insert(治反向误导+双锚点稀释) - G3 衔接:pinned_goal 内容态与 ConvState 生命周期态正交,不进 enum 各改进配开关 flag(GOAL_PIN_ENABLED/STALL_BREAKER_*/TOPIC_MARKER_GOAL_AWARE)可单点回退。 诊断报告见 docs/02-架构设计/专项设计/AI对话目标丢失诊断-2026-06-26.md。
This commit is contained in:
@@ -757,6 +757,18 @@ mod tests_f09_per_conv {
|
||||
/// 读写,AiSession 顶层单例字段已全部删除。
|
||||
///
|
||||
/// 字段初值逐字对齐 [`AiSession::new`](#method.new)。
|
||||
///
|
||||
/// # 字段正交性(G1 目标钉扎 / G3 状态机收敛衔接,2026-06-26)
|
||||
///
|
||||
/// 本 struct 同时持有两类正交状态:
|
||||
/// - **生命周期态**(`conv_state: ConvState`):loop 是否在跑(Idle/Generating/Stopping/...),
|
||||
/// 归 `ConvState` enum 管(写收敛见 [`ConvState::transition_to`])。
|
||||
/// - **内容态**(`pinned_goal` 等):用户想达成什么 / 会话进度等内容信息,挂本 struct 兄弟字段。
|
||||
///
|
||||
/// 两者**正交共存**于同一 struct,不互相进变体:目标**绝不**塞进 `ConvState` enum(否则
|
||||
/// 5 态会膨胀成 `GeneratingWithGoalA`/`GeneratingWithGoalB` 爆炸组合,违反 conv-state-convergence
|
||||
/// 分支「轻量状态机不引入框架」原则,见 agentic/conv_state.rs 文件头)。目标钉扎字段随会话
|
||||
/// 销毁不落库(对齐 `knowledge_extracted` 语义,PerConvState 无 serde derive)。
|
||||
pub struct PerConvState {
|
||||
/// 对话历史(ContextManager:会话级消息真相源,裁剪仅影响发送视图)
|
||||
pub messages: ContextManager,
|
||||
@@ -764,6 +776,17 @@ pub struct PerConvState {
|
||||
/// 写收敛:经 GeneratingGuard/入口 transition_to 守卫迁移,非直接赋值。
|
||||
/// 批3 双轨收口:generating bool 已退役,此 enum 成为生成态唯一真相源。
|
||||
pub conv_state: ConvState,
|
||||
/// G1 目标钉扎真相源:用户首条 active 消息提取的目标(内容态字段,与生命周期态正交)。
|
||||
///
|
||||
/// 治 R1(目标消息被压缩/compressed 物理出局,sanitize step0 过滤 is_active 致目标丢失):
|
||||
/// 目标存本字段绕过消息 active 状态过滤,即使原始 user 消息出局,goal 字段仍在。
|
||||
/// run_agentic_loop 入口把它拼进 system_prompt 尾部(system_prompt 是 loop 不变量,天然
|
||||
/// 免疫压缩/裁剪/sanitize,见 agentic/mod.rs:683)。
|
||||
///
|
||||
/// 写:chat.rs send/force_send push 后提取(仅 None 时写首条);读:loop 入口拼接。
|
||||
/// GOAL_PIN_ENABLED=false 时不提取不注入,本字段永远 None(单点回退等价改动前)。
|
||||
/// 随会话销毁不落库(对齐 knowledge_extracted L795 语义,PerConvState 无 serde derive)。
|
||||
pub pinned_goal: Option<String>,
|
||||
/// 停止信号(会话级):ai_chat_stop 置位,agentic loop / stream_llm 检测后尽快退出
|
||||
pub stop_flag: Arc<AtomicBool>,
|
||||
/// 即时停止唤醒(会话级):阻塞在 stream.next() 时 notify_one() 立即唤醒跳出 select!
|
||||
@@ -810,10 +833,12 @@ impl PerConvState {
|
||||
/// - session_trust: HashSet::new()
|
||||
/// - created_at: None(批1 新增字段,AiSession 现有 active_conv_created_at 同语义)
|
||||
/// - knowledge_extracted: false(新会话未提炼,P1 去重标志)
|
||||
/// - pinned_goal: None(G1 目标钉扎,新会话未提取目标)
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
messages: ContextManager::new(ContextConfig::default()),
|
||||
conv_state: ConvState::Idle,
|
||||
pinned_goal: None,
|
||||
stop_flag: Arc::new(AtomicBool::new(false)),
|
||||
notify: Arc::new(tokio::sync::Notify::new()),
|
||||
iteration_used: 0,
|
||||
|
||||
Reference in New Issue
Block a user