Files
eaiadminandClaude Code c1af86c934 feat(asr): 本地语音转写接入为一级路由 + 并行工作流合并提交
按用户指示做**一包提交**,不按工作流拆分。本提交刻意混合了多条并行线:

  · 本地 ASR 接管:audio 成为与 chat/embed/image/video 同等的路由类别
    (IsLocalRoute 单一判据、audio 健康探测、default_audio_route、
    auto 占位、GET /api/ai/routes/audio、回退云端时界面明示「音频已出网」)
  · LLM 调用层:ctx 贯穿、ToolCall/ToolSchema、EmptyCompletionError /
    TransientUpstreamError(按错误类型而非文案判重试)
  · 编排 Agent:general_assistant orchestrate/persistence/spec_driver
  · 联网搜索:internal/search(playwright)
  · 网盘:backend + 前端
  · 前端 UI:导航/路由/工作台若干页
  · 交付文档:DELIVERY.md / AR04 / 部署文档的「无 Python」表述据实改写,
    新增 eai_agentplatform-asr.service、asr.env、clonezilla-cleanup 清 ~/asr-poc

不分拆的原因:dev 早期,粒度不该打断工作节奏。且实测过——这些改动
**在编译上是同一个单元**(llm.go 的 ctx 签名变更牵动 12 个调用点,
chat_message.go 的 ctx 改动又与编排重写同处一个 hunk),拆出来的中间态编不过。
详见 TOP_CODING_RULES.md G14.5 与 bugs_and_errors.md E09。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-26 22:21:39 +08:00

3.9 KiB
Raw Permalink Blame History

run_15(上下文:编排超时兜底修复回归)

  • 类型:编排型(HTTP/2 vs HTTP/3 对比,「对比」命中编排信号词)
  • 目的:验证「编排 150s 硬截止兜底」在 ctx 贯穿 + agent 轮次 ctx 检查 + executeSubTasks wall-clock 截止后真正生效
  • 结果:✅ HTTP 200,150.0s 收敛(此前同用例 run_14 为 210s 无限挂起,curl 200s 0 字节)
  • 时间:2026-09-25 21:30:22 → 21:32:52

修复内容(本回归所验证)

  1. llm.go:所有 LLM 调用(Generate/GenerateFull/GenerateStream/xxxFallback/Embed)加 context.Context 参数,post 用 http.NewRequestWithContext,使上层 ctx(编排 150s 兜底)真正能取消进行中的 HTTP 请求。
  2. agent.go RunWithUsage:每轮 tool_calls 前检查 ctx.Err(),ctx 取消立即退出,避免慢 worker 靠单次已发起成功的 HTTP 响应续命拖死 wg.Wait()。
  3. orchestrate.go executeSubTasks:分批 worker 的 wg.Wait() 改为与 ctx.Done() 竞争(select),到点不等最慢 worker,150s 硬截止返回当前已完成产物。

效果对照

维度 修复前(run_14) 修复后(run_15)
请求收敛 210s 无限挂起,curl 200s 0 字节 ✅ 150s HTTP 200 返回
后续请求 被阻塞(run_14 曾连带超时) ✅ 不阻塞
ctx 传导 失效 ✅ ai_call_log 出现 context deadline exceeded 的快速失败(0ms)
产物 - 超时兜底返回「已按子任务完成,但结果为空」+ 部分子任务标题

多策略修复后 → 成功(2026-09-25 22:02)

对「worker 空回复 / tool_calls 死循环」叠加三重策略后重跑同用例(request 见 request.json,结果存 response_success.json):

指标 结果
收敛时长 ✅ 94s(无需 150s 兜底,正常完成)
产物体量 ✅ 约 19KB 深度对比正文(含核心判断/共同点/各自问题/RTT/传输效率/选型/来源引用)
编排完整性 ✅ plan(5子任务)→worker 执行→merge→审核 worker 全部跑通
ai_call_log 4 个 worker 1.4-2.1s 极快产出(无工具收敛路径)+ 2 个 worker 21-23s + 主回复 94s

三重策略明细(internal/ai/agent.go + orchestrate.go)

  1. roundWithEmptyRecovery:单轮「空响应」→ 带工具重试一次 → 仍空降级「无工具纯文本」重试,兼容「带工具即空、纯文本正常」的路由。
  2. tool 死循环收敛:RunWithUsage 统计连续「只发工具调用、无结论文本」轮数,≥3 轮即中断,用无工具纯文本基于已回填的搜索结果重生成结论——直接掐断模型反复搜索不下结论的死循环。
  3. worker 级兜底:executeSubTasks.runOne 在 agent 失败/空时,用无工具 GenerateWithFallback 再生成一次,保证每个 worker 至少有可拼接内容。

遗留问题(非本次修复范围)

  • 部分子任务产物仍含模型原样输出的 |tool| 转义残留(个别 worker 未完全收敛时把工具调用文本化),但最终 merge 正文干净,不影响主交付。

回归确认(修改未误伤其它路径)

用例 路径 结果
run_03(周末闲聊) direct_answer ✅ HTTP 200,4.2s,内容完整(纯文本直答,无产物)
run_12(2026 诺贝尔奖联网查) single_search / orchestrated ✅ HTTP 收敛返回(ai_call_log 记录 123s success;curl 90s 断开属本端上限,服务端实际 123s 完成,不挂死)

下一步建议

  • 单考 worker 空回复:在 RunWithUsage 或 worker 侧对「模型最终回复为空」做一次退避重试;或对不兼容 tool_calls 的路由降级为无工具生成。
  • 已确认修改未误伤 direct_answer / single_search 路径;剩 worker 空回复与单问调用偏慢,根因是当前路由 deepseek-v4-flash 对带 web_search 工具的多轮 tool_calls 支持不佳,属独立问题待商定。