Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
62 lines
5.5 KiB
Markdown
62 lines
5.5 KiB
Markdown
# TASK · 生时校正每轮等待过长:埋点 + 分类超时 + 发出后立即反馈(2026-09-26)
|
||
|
||
## 基线
|
||
|
||
- `origin/staging` 当前 head。分支 `codex/rectification-latency-20260926`。
|
||
- **串行**:排在 `TASK-rectification-dup-question-20260926`(同样改校正面组件)之后。
|
||
|
||
## 事故实证(产品 09-26 真机)
|
||
|
||
打字回答后「正在分析 / 正在处理…」要等很久才出正文。排查结论(`origin/staging` a57c4310,本地实测 + 代码阅读):
|
||
|
||
- 一轮打字回答串行 **5 次模型调用**,全部开思考:
|
||
1. 开流前意图分类 `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.ts` `streamAttempt`,`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_probes` 5.8–6.1 s;cProfile 热点是 `build_refinement_packet`(57–73%),refresh 分支探针算两遍;交付阶段 `vedastro-validate` 串行调外网(≤12 s)。
|
||
- 收尾 `persistNextInterviewIfIdle` 在 `agent-run.ts` 与 route `finalizeSuccessfulTurnExit` 各调一次,第二次多为空转但会重读档案。
|
||
- `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)。
|
||
- D6 不在本单:去掉强制 read-case 第 0 步(需改 Skill 原文与回执不变量,另议);vedastro-validate 改后台(交付语义,另议)。
|
||
|
||
## 硬红线
|
||
|
||
1. 不换分类模型、不关分类思考、不改 Agent 各步是否开思考;不改 Skill 文本与 VOICE 口吻(进度句除外,需进 VOICE)。
|
||
2. D5 每项:同一虚构输入改前改后结果逐位一致(Python 用同机 A/B,不写死跨机浮点哈希,见 BUG-985)。
|
||
3. 分类超时测试:模拟挂起的分类调用,10 秒后进入既有失败路径,不无限等待。
|
||
4. 进度句测试:发出后第一帧(或 ≤ 300 ms)出现第一句;阶段事件驱动更新;结算后进度句消失,不进入持久化正文。
|
||
5. `jyotish_api_server.py` 不增长;全量前端测试与基线逐条一致、新增 0;Python 快速门与定向测试通过;改动断言三栏。
|
||
6. 真实浏览器(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 由重复问题单预留),开工时核对。
|