优化: 弱模型治理收尾(AC-2探索预算:单轮上限+目录去重+禁绕行 + AC-5失败画像:合法目标回灌+相近锚点提示)

This commit is contained in:
lxy
2026-08-08 19:38:53 +08:00
parent 02c8d8e5ea
commit fe780c0084
8 changed files with 648 additions and 12 deletions
+44 -1
View File
@@ -219,6 +219,14 @@ pub const STALL_BREAKER_GOAL_REMIND: bool = true;
/// 「最小样本 6」+「单点 3 次」阈值有意义,又不至于扫太长历史稀释近期漂移信号。
pub const STALL_BREAKER_SAMPLE_SIZE: usize = 12;
/// AC-2 ①:单轮工具调用数上限(默认 8)。
///
/// 治弱模型单轮一次性发超多工具调用(实证 09e7abfa:同一目录列 3 次 + run_command 绕行,
/// 单轮十几个 grep/read 并行爆炸)。LLM 看不到"自己本轮发了多少调用",必须在消息流里
/// 显式警告才能感知(机制优先 prompt 说教)。超限即 insert 一条 system 软提示到
/// conv.messages(非静默),下轮 build_for_request 时 LLM 可见,促其聚焦关键操作。
pub const MAX_TOOL_CALLS_PER_ROUND: usize = 8;
/// L1 断路器:连续同类工具失败熔断阈值(治 kms 会话 53 轮 0 产出死循环)。
///
/// 背景:agent 无止损,某工具反复同类失败(权限拒绝/路径错误等)仍每轮重试,
@@ -312,7 +320,7 @@ pub mod command_lock;
pub(crate) mod helpers;
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};
pub(crate) use helpers::{tool_call_signature, is_repetitive_exploration, is_pure_greeting, is_tool_call_over_limit};
// ============================================================
// 单 Provider 流式结果 + fallback 辅助
@@ -1887,6 +1895,8 @@ pub(crate) async fn run_agentic_loop(
if !has_tool_calls { converged = true; break; }
let _ = converged;
// AC-2 ①:记录本轮工具调用数(供超限警告判定;process_tool_calls 会 move 走 tool_calls_acc)。
let round_tool_call_count = tool_calls_acc.len();
// 处理工具调用(Low 自动执行 / Medium+High 待审批)
let pending_count = process_tool_calls(&session_arc, tool_calls_acc, &tools_arc, &db, &app_handle, &conv_id).await;
// DIRAUTH 审批链已闭环。原 eprintln 诊断降级为 tracing::debug,
@@ -1904,6 +1914,12 @@ pub(crate) async fn run_agentic_loop(
return;
}
// AC-2 ①:单轮工具调用数超限 → 注入软提示(机制化,非静默,弱模型能感知)。
// 治单轮并行调用爆炸:LLM 看不到自己发了多少调用,必须在消息流里显式警告。
if is_tool_call_over_limit(round_tool_call_count) {
insert_tool_call_over_limit_warning(&session_arc, &conv_id, iteration, round_tool_call_count).await;
}
// L1 断路器:连续同类工具失败熔断(治 agent 无止损死循环,机制非 prompt 说教)。
// count_recent_failures 读末尾连续 Tool 消息,失败包按结构化信号归一 key 入滚动窗口计数。
if CIRCUIT_BREAKER_ENABLED {
@@ -2472,6 +2488,33 @@ async fn fetch_goal_summary(session_arc: &Arc<Mutex<AiSession>>, conv_id: &str)
format!("(当前目标: {})", goal_summary)
}
// ── insert_tool_call_over_limit_warning: AC-2 ① 单轮工具调用数超限软提示 ──
// 机制化(非 prompt 说教):超限即 insert system 警告到 conv.messages 首位(对齐 G2
// insert_stall_warning 模式),下轮 build_for_request 时 LLM 可见,促其聚焦关键操作。
async fn insert_tool_call_over_limit_warning(
session_arc: &Arc<Mutex<AiSession>>,
conv_id: &str,
iteration: usize,
count: usize,
) {
let warn_text = format!(
"⚠ 本轮工具调用达 {} 个,超过单轮上限 {} 个。请聚焦关键操作,减少并行调用,勿重复探索同一区域。",
count, MAX_TOOL_CALLS_PER_ROUND
);
let mut session = session_arc.lock().await;
if session.per_conv.contains_key(conv_id) {
let conv = session.conv(conv_id);
conv.messages.insert_at(0, ChatMessage::system(&warn_text));
tracing::info!(
conv_id = %conv_id,
iteration,
count,
limit = MAX_TOOL_CALLS_PER_ROUND,
"[ai] AC-2 单轮工具调用数超限:注入软提示"
);
}
}
// ── emit_fatal_error: 致命错误统一 emit AiError(扁平抽自原 Fatal/Exhausted 双分支重复代码) ──
// emit+publish 双写 Tauri 事件总线。error_type=Network 对齐原 Fatal 分支(鉴权/4xx归类)。
async fn emit_fatal_error(app_handle: &AppHandle, conv_id: &str, error: &str) {