caoqianming
|
1685004f96
|
feat(loop): 空响应防御——provider 吐空自动重试 + warn 自停不静默 done + 面板留痕(bump 0.58.32)
task 2a1bc25d 复盘:unifyllm 网关对某档 Claude 偶发把 tool_use 漏成正文/直接吐空,回来的轮
tool_calls=[] 且正文空,loop 当"模型答完"静默 done(run_status=idle、无报错、无终态失败),
表现为"自己中断",只能人肉挖 DB 才发现。复测该 bug 现已消失/瞬态,但"空 tool_calls 直接
done"这个失败模式本身太隐蔽,任何 provider 未来吐一次空都会静默卡死,故加防御(对称既有畸形
salvage 链)。
- _is_empty_response(tc 空且 content 去空白为空;纯 tool_call 轮不误判)挂进 _stream_llm 的
attempt 循环:空-空丢弃本轮走非流式重试(多数瞬态重发一次即恢复,用户无感)
- run() 收尾点分空-空分支:重试耗尽仍空不发静默 done,改发可见 warn「模型返回空响应,已停止,
回复继续可重试」+ done(复用 stall 熔断自停话术,run_status 落 idle 可续),不引入终态 error
- _log_empty_response stdout + usage_events(kind=empty_response,cost 0)双写留痕;core/toolfail
加第四段扫描聚成 tool=(empty)/kind=empty cluster(sample=model_profile 看哪个网关档在吐空),
admin 面板 + 巡检邮件零改动自动带上(单次瞬态 <阈值不触发,跨 task 系统性吐空才冒头)
- 刻意不做内容嗅探式"narrated tool_call 特征→重试":marker 每次变且与正常正文高度重叠,假阳性
(合法回答判坏反复重试)比罕见静默停更糟,那类只靠面板留痕兜、不改热路径行为
- tests: test_loop_empty_response.py 新增 7 件 + test_toolfail_malformed.py +2;顺手补回
test_loop_malformed_retry.py 因 salvage(0.58.24)落地后失修的 loop.executor 桩。全 247 测试绿
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-15 15:29:49 +08:00 |
caoqianming
|
859c02cf65
|
feat(ops+web): run 级错误持久提示+失败聚集+provider 致命错误即时告警(bump 0.58.21)
反 2a1bc25d 教训(Zai 余额不足连挂 3 次续跑,前端零提示、admin 零感知):
- chat.js: renderPersistedRunError 挂 renderMessages 末尾——run_status=error
且无 live run 时消息流末尾补「上次运行出错」持久卡(live 错误卡被收尾
loadMessages 整屏重建冲掉是"发了继续啥也没发生"的根因);下次 run 起跑
后端清 run_error 自然消失
- usage.py: record_run_error(kind=run_error, cost 0)——tasks.run_error 只留
最后一次,此行才是聚合的完整数据源;app.py _run_agent_bg except 落库
- toolfail.py: 第三段扫描聚成 kind=run / tool=(run),admin 面板+巡检邮件
零改动带上;alert_provider_critical 余额/配额/认证关键词命中即时邮件
ZCBOT_DEVELOPER_EMAIL(同签名 6h 进程内冷却,全路径静默失败)
- tests/test_toolfail_malformed.py +3 用例;PROGRESS/CHANGELOG/RUN 同步
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-13 14:06:29 +08:00 |
caoqianming
|
da289b2ce2
|
feat(ops): 畸形 tool_call 进工具失败聚集 + 巡检邮件只发活跃聚集(bump 0.58.19)
畸形轮整轮丢弃、messages 无痕,admin「工具失败聚集」原本看不见这类失败
(toolfail 只扫 role=tool 报错);且巡检邮件去重集是内存态,每次部署清零,
高频部署期每次重启都把 7 天窗口内早已安静的存量聚集重发一遍。
- 新增 record_malformed_tool_call:丢弃畸形轮时写 usage_events 一行
kind=tool_malformed(units={tool,len,err,head,tail,tokens_in/out}),
cost_cny 恒 0 —— cost 全 kind 合计且随任务展示,provider 抖动不算用户
花销;真实 token 快照进 units 供反推浪费。DB 写失败静默不阻塞重试
- core/toolfail.py 加第二段扫描(usage_events kind=tool_malformed),聚成
kind=malformed 同构 cluster,admin 面板/巡检邮件零改动自动带上;聚合
逻辑抽 _add 闭包双数据源复用
- 巡检邮件发信前加 count_24h>0 过滤:已安静的聚集重启后不再重发,还在
烧的重启后再提醒一次(刻意保留)
- 新增 tests/test_toolfail_malformed.py 4 用例(mock session_scope);
RUN.md env 巡检段 + 故障兜底同步;PROGRESS 更新
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-13 12:04:22 +08:00 |