清理: 停滞判定工具名映射构建去重
两处重复的 id 到 name 映射抽共用 helper
This commit is contained in:
@@ -80,25 +80,14 @@ pub(crate) async fn count_recent_failures(
|
||||
if recent_tool_results.is_empty() {
|
||||
return (0u32, String::new());
|
||||
}
|
||||
// tool_call_id → tool_name 反查表:遍历 Assistant 消息的 tool_calls(开销与消息数线性)。
|
||||
// tool_result 消息只带 tool_call_id,工具名在其前驱 Assistant 头里。
|
||||
let mut id_to_name: std::collections::HashMap<&str, &str> = std::collections::HashMap::new();
|
||||
for m in &messages {
|
||||
if let MessageRole::Assistant = m.role {
|
||||
if let Some(calls) = m.tool_calls.as_ref() {
|
||||
for c in calls {
|
||||
id_to_name.insert(c.id.as_str(), c.function.name.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let id_to_name = build_id_to_name(&messages);
|
||||
// 本轮失败的归一 key 追加进窗口(顺序:消息正序,即工具执行顺序)。
|
||||
for m in recent_tool_results.into_iter().rev() {
|
||||
if is_failure_content(&m.content) {
|
||||
let tool_name = m
|
||||
.tool_call_id
|
||||
.as_deref()
|
||||
.and_then(|id| id_to_name.get(id).copied())
|
||||
.and_then(|id| id_to_name.get(id).map(|s| s.as_str()))
|
||||
.unwrap_or("unknown_tool");
|
||||
let key = failure_key(tool_name, &m.content);
|
||||
fail_window.push_back(key);
|
||||
@@ -151,6 +140,24 @@ fn failure_key(tool_name: &str, content: &str) -> String {
|
||||
format!("{}::{}:{:08x}", tool_name, bucket, h)
|
||||
}
|
||||
|
||||
/// 构建 tool_call_id → tool_name 反查表(断路器失败分组与 tool_result 摘要压缩共用)。
|
||||
///
|
||||
/// Tool 结果消息只带 tool_call_id,真实工具名在前驱 Assistant 消息的
|
||||
/// tool_calls[].function.name 里;查不到的 id 由调用方按各自语义兜底。
|
||||
fn build_id_to_name(messages: &[ChatMessage]) -> std::collections::HashMap<String, String> {
|
||||
let mut id_to_name = std::collections::HashMap::new();
|
||||
for m in messages {
|
||||
if let MessageRole::Assistant = m.role {
|
||||
if let Some(calls) = m.tool_calls.as_ref() {
|
||||
for c in calls {
|
||||
id_to_name.insert(c.id.clone(), c.function.name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
id_to_name
|
||||
}
|
||||
|
||||
/// a 32-bit 哈希(零依赖,纯函数,断路器 key 归一专用;非密码学用途)。
|
||||
fn fnv1a_32(bytes: &[u8]) -> u32 {
|
||||
let mut hash: u32 = 0x811c9dc5;
|
||||
@@ -227,21 +234,10 @@ pub(crate) fn summarize_tool_results(
|
||||
let mut original_bytes: usize = 0;
|
||||
let mut summarized_count: usize = 0;
|
||||
|
||||
// 构建 tool_call_id -> tool_name 映射:role=Tool 消息只带 tool_call_id(调用 ID),
|
||||
// 真实工具名(read_file/run_command/...)在前序 role=Assistant 消息的 tool_calls[].function.name。
|
||||
// 旧实现误把 tool_call_id(如 call_f892)当 tool_name 传给 extract_key_info,导致:
|
||||
// 1) 摘要头注释显示 call_f892 而非 read_file(显示 bug);
|
||||
// 2) extract_key_info 的 read_file 豁免永远命中不了(传入的不是真实名)。
|
||||
// 用 owned String(非 &str 借用)避开与 messages.into_iter() 的所有权冲突;
|
||||
// tool_call 数量极少(单轮几次),克隆开销可忽略。
|
||||
let mut id_to_name: std::collections::HashMap<String, String> = std::collections::HashMap::new();
|
||||
for m in &messages {
|
||||
if let Some(calls) = m.tool_calls.as_ref() {
|
||||
for c in calls {
|
||||
id_to_name.insert(c.id.clone(), c.function.name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// tool_call_id → tool_name 反查与断路器共用 build_id_to_name;查不到(异常/老数据)
|
||||
// 退化为 "tool"。旧实现曾误把 tool_call_id 当工具名,致摘要头显示 call_f892、
|
||||
// read_file 豁免永远命中不了。
|
||||
let id_to_name = build_id_to_name(&messages);
|
||||
|
||||
let msgs: Vec<ChatMessage> = messages
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user