修复: G2 签名熔断误杀红绿迭代
- 同签名死磕判定改无写间隔连续段口径,间插写类调用=红绿验证不累计 - 写证据=is_write_evidence_tool 五个改文件工具,读类不算证据 - 阈值 3 与纯死磕语义不变,根治脚本失败致执行中断 - 新增红绿迭代豁免与读间隔死磕两场景测试
This commit is contained in:
@@ -185,6 +185,8 @@ pub const TOPIC_MARKER_GOAL_AWARE: bool = true;
|
||||
// grep 无匹配是有效排除信号非漂移,误熔断正常排除式搜索(实证 ac448296)。
|
||||
// - 新(当前):连续 N 轮工具调用签名重复(is_repetitive_exploration 判 tool_call_signature)。
|
||||
// 漂移本质 = AI 卡住反复同样调用;正常探索(换词/换路径/换工具)签名不同,真死循环签名重复。
|
||||
// 红绿迭代(同验证命令反复跑+间插写调用)按写间隔豁免不算漂移,见 is_repetitive_exploration。
|
||||
// 红绿迭代豁免:同验证命令反复跑但间插写类调用(patch/write)不算漂移,见 is_repetitive_exploration 写间隔论证。
|
||||
//
|
||||
// 机制(非 prompt 说教,骨架沿用):连续 N 轮判定签名重复 → 两段式(WARN_FIRST 先警示再熔断):
|
||||
// 警示注入下轮 prompt 给 LLM 自纠机会,熔断(guard.reset + AiHelpRequired)逼用户换思路/人工介入。
|
||||
@@ -373,7 +375,7 @@ pub(crate) use stall_detector::{
|
||||
pub(crate) use helpers::try_continue_agent_loop;
|
||||
pub(crate) use helpers::infer_goal_from_tool_calls;
|
||||
pub(crate) use helpers::{
|
||||
tool_call_signature, is_repetitive_exploration, is_pure_greeting, is_tool_call_over_limit,
|
||||
tool_call_signature, is_repetitive_exploration, is_write_evidence_tool, is_pure_greeting, is_tool_call_over_limit,
|
||||
DestructiveLoopSample, destructive_loop_sample, detect_destructive_loop,
|
||||
};
|
||||
|
||||
@@ -1947,7 +1949,10 @@ async fn check_stall_breaker(
|
||||
// 就抽取每工具签名(name + arguments JSON parse),累积到 STALL_BREAKER_SAMPLE_SIZE 个。
|
||||
// arguments 非合法 JSON 时 to_string 兜底(签名仍可比,只是兜底全量)。
|
||||
// 同时并行抽取回环样本(写/删工具记路径,其他占位),两缓冲同序位对齐。
|
||||
let (signatures, loop_samples): (Vec<String>, Vec<DestructiveLoopSample>) = {
|
||||
// 签名样本带写证据标记(写类调用 true),喂 is_repetitive_exploration 做红绿迭代豁免。
|
||||
// 写类调用同时打写证据标记(is_write_evidence_tool),供 G2 单点死磕的写间隔豁免:
|
||||
// 红绿迭代(同验证命令反复跑+间插写)=验证行为不算漂移,根治脚本失败致执行中断。
|
||||
let (signatures, loop_samples): (Vec<(String, bool)>, Vec<DestructiveLoopSample>) = {
|
||||
let session = session_arc.lock().await;
|
||||
// BE2只取尾部 BREAKER_TAIL_N 条(签名抽取只需最近几轮工具调用,
|
||||
// 全量 clone 纯浪费;STALL_BREAKER_SAMPLE_SIZE=12 ≪ 40,样本充足)。
|
||||
@@ -1955,7 +1960,7 @@ async fn check_stall_breaker(
|
||||
Some(conv) => conv.messages.recent_messages(BREAKER_TAIL_N),
|
||||
None => Vec::new(),
|
||||
};
|
||||
let mut sigs: Vec<String> = Vec::new();
|
||||
let mut sigs: Vec<(String, bool)> = Vec::new();
|
||||
let mut loops: Vec<DestructiveLoopSample> = Vec::new();
|
||||
for m in messages.iter().rev() {
|
||||
if sigs.len() >= STALL_BREAKER_SAMPLE_SIZE {
|
||||
@@ -1972,7 +1977,7 @@ async fn check_stall_breaker(
|
||||
}
|
||||
let args: serde_json::Value =
|
||||
serde_json::from_str(&tc.function.arguments).unwrap_or(serde_json::Value::Null);
|
||||
sigs.push(tool_call_signature(&tc.function.name, &args));
|
||||
sigs.push((tool_call_signature(&tc.function.name, &args), is_write_evidence_tool(&tc.function.name)));
|
||||
loops.push(destructive_loop_sample(&tc.function.name, &args));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user