Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
5.5 KiB
5.5 KiB
TASK · 生时校正每轮等待过长:埋点 + 分类超时 + 发出后立即反馈(2026-09-26)
基线
origin/staging当前 head。分支codex/rectification-latency-20260926。- 串行:排在
TASK-rectification-dup-question-20260926(同样改校正面组件)之后。
事故实证(产品 09-26 真机)
打字回答后「正在分析 / 正在处理…」要等很久才出正文。排查结论(origin/staging a57c4310,本地实测 + 代码阅读):
- 一轮打字回答串行 5 次模型调用,全部开思考:
- 开流前意图分类
classifyTurnIntentWithRetry(v9/turn-intent-classifier.ts;agent/route.ts约 L453 / 534 / 643 / 751 调用),用会话模型、供应商默认开 thinking,每次尝试无超时、最多 2 次,且发生在new ReadableStream之前 → 用户看到的是一段没有任何字节的空等;L643 分支继续时 L751 还会再分类一次。 2–5. Agent 四步(v9/agent-run.tsstreamAttempt,agentGenerationSettings(..., { thinking: "enabled", thinkingTokens: 8192 })):强制第 0 步rectification-read-case(路由已读过档案)→record-evidence-batch(含引擎重算)→set-focus(改写服务端定好的下一问)→ 最终正文模板句。推理内容不下发(stream-mapping.ts),界面只显示「正在分析…」。
- 开流前意图分类
- 引擎:09-15 性能审计四单(BUG-721~726)已全部落地;本地实测 20 个候选 0.4–0.5 s、61 个候选 2.3–2.5 s、带
refresh_probes5.8–6.1 s;cProfile 热点是build_refinement_packet(57–73%),refresh 分支探针算两遍;交付阶段vedastro-validate串行调外网(≤12 s)。 - 收尾
persistNextInterviewIfIdle在agent-run.ts与 routefinalizeSuccessfulTurnExit各调一次,第二次多为空转但会重读档案。 RectificationRunDiagnostic的inputTokens/reasoningTokens恒为 null,stepCount实际是"用过几种工具",分类耗时只在失败时记录 → 线上无法核实各段耗时。- 估计单轮 25–90 s,模型占 85–95%;evidence_not_written 重跑时翻倍。
根因
串行多步 + 每步深度思考 + 开流前无超时空等 + 无进度反馈。
决策记录(产品 2026-09-26)
- D1 不改每轮最后两步(set-focus 改写与最终正文仍由模型生成,口吻不变)。
- D2 分类保持深度思考与会话模型(维持 09-15 决定),只给每次尝试加 10 秒超时;超时按现有失败路径处理(重试一次后走既有兜底),不得换模型、不得关思考。
- D3 发出后立即反馈:用户发出后 ≤ 300 ms 内在活动状态处出现确定性进度句,随后按阶段更新,替代一直不变的「正在分析 / 正在处理…」:
- 发出即:「收到,正在对照你的档案…」
- 记录经历开始:「正在记下这件事…」
- 引擎重算:「正在重新对照盘面…」
- 准备下一问:「正在准备下一个问题…」
- 阶段信号来自现有
persistCommittedPhase/ 工具调用事件,不新增模型调用。这些句子属于"流式生成中",不违反"揭幕后不得出现加载态";进度句不写入assistant_message。 - 为此把分类移到流内:先建流、立刻推第一句进度,再做分类。
- D4 补埋点:每步开始 / 结束时间、每步推理 token(供应商能给则记)、分类耗时(成功也记)、引擎每次调用耗时,写入
RectificationRunDiagnostic(不含用户资料与模型原文,符合隐私红线)。 - D5 无口吻影响的服务端优化(输出必须逐位不变,A/B 证明):
- refresh 分支里
build_refinement_packet探针只算一遍; persistNextInterviewIfIdle第二次调用在第一次已完成时跳过;- 部署未配置时
readV9EngineScoringIdentity的/v5/versions结果在进程内按版本号缓存(短 TTL)。
- refresh 分支里
- D6 不在本单:去掉强制 read-case 第 0 步(需改 Skill 原文与回执不变量,另议);vedastro-validate 改后台(交付语义,另议)。
硬红线
- 不换分类模型、不关分类思考、不改 Agent 各步是否开思考;不改 Skill 文本与 VOICE 口吻(进度句除外,需进 VOICE)。
- D5 每项:同一虚构输入改前改后结果逐位一致(Python 用同机 A/B,不写死跨机浮点哈希,见 BUG-985)。
- 分类超时测试:模拟挂起的分类调用,10 秒后进入既有失败路径,不无限等待。
- 进度句测试:发出后第一帧(或 ≤ 300 ms)出现第一句;阶段事件驱动更新;结算后进度句消失,不进入持久化正文。
jyotish_api_server.py不增长;全量前端测试与基线逐条一致、新增 0;Python 快速门与定向测试通过;改动断言三栏。- 真实浏览器(CDP 假数据 + 人为延迟)截图:发出后立刻出现进度句并随阶段变化。
任务分解
- T1 埋点(D4)。
- T2 分类移入流内 + 10 秒超时(D2、D3 前半)。
- T3 阶段进度句(D3)+ VOICE / DESIGN。
- T4 服务端无口吻优化(D5)+ A/B 证明。
- T5 记录:BUG-1047(每轮等待过长 / 开流前无反馈),关联 BUG-721~726、BUG-722;CHANGELOG;PROGRESS(各段耗时改前 / 改后估计,部署后用新埋点复核);
docs/testing/真机清单(打字回答后立刻出现「收到,正在对照你的档案…」并逐段变化;总耗时记录)。
BUG 编号
本单 BUG-1047(1045 / 1046 由重复问题单预留),开工时核对。