mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-04 00:03:59 +00:00
fix(llm): 参数无法解析时给出真因,不再静默丢弃整条调用
★ 上次修复误判了成因。真实根因(本次运行日志 34/34 同形):
{"command": "…完好的长命令…", "timeout": 20s}
command 一字节没错,只是 timeout 值少了引号 —— cmd_run 的 schema 把 timeout
声明成 string、示例写着 "10s, 1m, 30s",模型照抄格式却忘了引号。
finish_reason=length 出现 0 次 ⇒ 上次那条"截断"分支从不生效。
旧行为把**整个参数**丢掉,模型只看到 "command is required",看不出坏在 timeout,
只能原样重试。实测本次运行 cmd_run 失败率 35%(34 败 / 71 成),
12 分钟的任务里更是 48% 时间耗在这上面 —— 每次失败都付一次完整 LLM 往返。
三处改动:
1. repairToolArgsJSON:解析失败时先试窄修复 —— 只给"值位置上未加引号的带单位
数字"补引号,且修完必须真能解析成功才接受。不碰合法 JSON、不动正文里的 20s、
不会把真截断"修好"。
2. 修复仍失败时不再静默降级成空 map,改为带 __arg_error 交给模型,并按成因
分流文案:截断→拆小参数;JSON 写坏→提醒带单位的值要加引号。
3. 统一键名 __arg_error(原 __truncated_error 只覆盖截断,语义过窄)。
同一缺陷面不止 cmd:agentcli/healthcheck/timer 都有 string 类型却以
"5m, 1h" 作示例的参数,此修复一并覆盖。
回归测试:真实日志样本修复、保守性(不碰合法/正文/截断)、
端到端(修复后 timeout 仍能被 time.ParseDuration 接受)。
This commit is contained in:
@ -44,11 +44,12 @@ func (a *Agent) executeToolCall(tc agentAPI.ToolCall, channel string, turnScenes
|
||||
}
|
||||
|
||||
func (a *Agent) executeToolCallInner(tc agentAPI.ToolCall, channel string, turnScenes []string) string {
|
||||
// 参数被 max_tokens 截断(见 accumulateStream):**不要**拿着残缺/空参数去调工具。
|
||||
// 否则工具会报 "path is required" 这类与真因无关的错,模型看不出是截断,
|
||||
// 只会原样重试(实测连续 4 次)。直接把可执行的指引交回模型。
|
||||
if msg, ok := tc.Arguments["__truncated_error"].(string); ok && msg != "" {
|
||||
log.Printf("[agent] tool %s skipped: arguments were truncated by max_tokens", tc.Name)
|
||||
// 参数没法用(被 max_tokens 截断,或 JSON 写坏了):**不要**拿着空/残缺参数去调工具。
|
||||
// 否则工具会报 “path is required”“command is required” 这类与真因无关的错,
|
||||
// 模型看不出真因、只能原样重试(实测 cmd_run 失败率高达 34%~48%)。
|
||||
// __arg_error 里带的已经是分因写好的可执行指引,直接交回模型。
|
||||
if msg, ok := tc.Arguments["__arg_error"].(string); ok && msg != "" {
|
||||
log.Printf("[agent] tool %s skipped: arguments unusable (truncated or malformed)", tc.Name)
|
||||
return msg
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user