Files
Jyotisha/docs/tasks/PROGRESS-consult-latency-quickwins-20261005.md
T
Jesse_ChenandClaude Opus 5.5 45ec6e55a1
Independent Staging Quality Gate / validate (push) Successful in 14m12s
Independent Staging Quality Gate / publish (push) Successful in 3m38s
docs(tasks): accept consult latency quickwins (BUG-1231/1232)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-10-05 08:38:12 +08:00

152 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROGRESS:普通对话耗时两项快修 — 2026-10-05
基线:任务书写成时已部署的是 `1252de3e`。开工时 `origin/staging` 为 `853772bc`(相对已部署提交只有文档)。执行中又快进到 `4c64733f`(再加一份纳迪研究任务书,产品代码与 `853772bc` 相同)。分支 `codex/consult-latency-quickwins-20261005`,工作树 `.worktrees/consult-latency-quickwins-20261005`。测试基线工作树停在 `853772bc`,没有改它。
未推送,未部署。用量页没有登录打开。修复版本:待发布。
## 做了什么
1. 咨询路径上,校正闸不再为官方快照干等。请求里已有「外部证据可以后做」这个标记时:先复用当天已经验证的官方快照;没有就查当天的失败记录;都没有就记 `deferred_in_consultation`,不起 4 秒子进程,也不标成已验证。直接做生时校正、请求里没有这个标记时,仍走原来的官方快照。顶层那一次前台核对仍做(BUG-301 不推翻)。BUG-1231。
2. 普通对话补上分段计时。分类耗时、第 0 步、第 1 步的耗时和供应商 token,以及第 1 步开始到第一个正文字的时间,写入运行日志和用量账本里已有的 JSON 字段。用量页多一列「分段」。不改表。BUG-1232。
3. 记录:BUG-1231、BUG-1232、CHANGELOG、本文件、状态板改为「已实现待验收」。
推理强度、精简说明、第 0 步关闭思考,按产品决定不在本单。
## T0 环境缺口
本轮没有登录态,也没有测试账号。公开接口测到:
| 检查 | 结果 |
| --- | --- |
| `GET https://staging.jyotisha.chat/api/health` | 200。`deployment.gitCommit` = `1252de3e6363f3097668efa1b1d5d47186c9c2d0` |
| `POST https://staging.jyotisha.chat/api/consultation_workflow` | 404。公网边缘没有这条 Python 引擎路由 |
| 本机 `vedastro` 模块 | 未安装 |
任务书里的 4.6 秒是沙箱网络下测的。当前测试环境跑的仍是改前版本。要确认生产机器是不是也在等这 4 秒,请在这次上线之前看现在的 `/admin/usage` 或容器日志:工具耗时是否接近「领域数 × 4 秒以上」。这次上线之后,同一处不应再出现这段等待;新的「分段」列用来看分类、第 0 步、第 1 步。
## T1 耗时
本机没有 VedAstro SDK,产品路径的冷热耗时没有重测。下表「改前」用任务书里的沙箱数字,「改后」是本轮测试能证明的行为。
| 场景 | 改前 | 改后 |
| --- | --- | --- |
| 装了 SDK、按产品路径,每个领域 | 约 4.6 秒,第二轮仍约 4.6 秒 | 本机测不了秒数。测试证明:不起快照子进程,状态是 `deferred_in_consultation`,不是已验证 |
| 同一天再问,上次是超时或失败 | 再等约 4.6 秒(失败不进缓存) | 负缓存同日命中,文件不重写,子进程不调用 |
| 下一个 UTC 日 | 任务书未单列 | 当天的负缓存失效,重新记 `deferred_in_consultation` |
| 当天已经有已验证的官方快照 | 顶层能用缓存,校正闸仍去等 | 校正闸复用同一份缓存。整数小时和进闸后变成的浮点小时,用原始请求对齐,避免对不上键 |
| 生时校正自己的请求(没有咨询标记) | 走原来的官方快照 | 仍走原来的 gateway,返回字段与现场结果逐项相同 |
| 顶层前台 VedAstro | 照旧(BUG-301) | 照旧。标记只作用在校正闸,不作用在顶层 gateway |
3 位公开名人 × 父母 / 年运、冷热各两轮:环境缺口,没有秒数。
## T2 产品在哪里看
用量页 `/admin/usage` 的「分段」列,旧记录没有这些数时显示「—」。数字来自用量账本已有的 JSON 字段,没有新表、没有迁移。同一组数也在服务端日志 `[agent-observability]` 里。本轮没有登录,页面没有点开;列的文字由单元测试锁住。
| 你看到的 | 含义 | 没有数时 |
| --- | --- | --- |
| 分类 180 ms | 分类这一步的耗时 | 分类 — |
| 第 0 步 … · 推理 · 出 · 入 · 缓存入 | 决定要不要排盘的那一步。耗时是毫秒;后面四个是供应商返回的 token | 该项为 — |
| 第 1 步 … | 写答案的那一步,字段同上 | 同上 |
| 写到正文 450 ms | 第 1 步开始,到第一个正文字出现。第 0 步的旁白不计 | 写到正文 — |
| 各领域工具耗时 | 原有字段,本单没有改含义 | 原样 |
日志和用量记录里的对应名字:`classification.durationMs`、`modelSteps`(只保留第 0 步和第 1 步)、`answer.reasoning_ms`、工具调用上原有的 `durationMs`。供应商没返回的 token 是空值,不估算。这些字段里没有提示词、答案正文、出生资料、用户标识。
## 开工预检
读了 `docs/research/pre_work_error_ledger.md`。本单不涉及碎片目录或镜像仓,没有再读两份碎片清扫。`scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45` 的结果:
| 项 | 结果 |
| --- | --- |
| Python 运行时 | 通过 |
| 外部引擎适配器 | 通过 |
| 远端可见 | 通过,远端是 `https://git.copse.top/root/Jyotisha.git` |
| 碎片扫描 | 90 秒超时 |
| 聚焦测试 | 45 秒超时 |
| 检查当时的分支 | 比 `origin/staging` 落后 1 个提交;随后已快进到 `4c64733f` |
碎片扫描和聚焦测试超时是这次预检命令自己的时限,不是远端同步失败。没有新的镜像路径要记。
磁盘:开工时 G: 约 557 GB 空闲,D: 约 135 GB,C: 约 24 GB。
## 已完成的检查
| 项 | 结果 |
| --- | --- |
| 新增 Python 测试 + 增长合同 | 11 项通过 |
| 两个新 Python 文件的 ruff | 通过。`jyotish_api_server.py` 里原有的 ruff 问题没有顺手改 |
| 前端计时测试 | 4 项通过,0 失败,0 cancelled |
| `tsc --noEmit` | 0 错 |
| `npm run lint` | 0 error,126 条既有 warning,没有为消 warning 改业务代码 |
| v5 打分文件 | 工作区没有改动。没有重跑 77 例 |
| 生时校正打分 | 没改 |
全量 `pytest tests`、英文对照、隐私测试、全量 `npm test`、快速门:见下面「套件对照」。对照完成前,不把本单说成套件已通过。
## 套件对照
前端全量 `npm test`(本机,不设 CI)。基线工作树 `853772bc`,本分支在快进后的产品代码上。两边都是退出码 1,cancelled 0,skipped 0。
| | tests | pass | fail | cancelled |
| --- | --- | --- | --- | --- |
| 开工基线 | 4844 | 4700 | 144 | 0 |
| 本分支 | 4848 | 4703 | 145 | 0 |
多出来的 4 个测试是本单的计时测试,全量里 4 个都通过。144 条旧失败名字与基线逐条相同。多出来的那 1 条是 `database roles have no cluster privileges`:全量并行时 Docker 里的 Postgres 正在关闭,`psql` 报 `the database system is shutting down`。这条测试不读本单改过的文件。单独重跑该文件:2 项通过,0 失败。不是这次改动引进的。
英文对照 `tests/test_report_english_dictionary.py` 与隐私 `tests/test_repo_privacy_markers.py`:一起跑,退出码 0。
`tsc --noEmit`:0 错。`npm run lint`:0 error,126 条既有 warning。
全量 `pytest tests`(`--tb=line`,退出码以失败名单为准;日志里的短摘要计数行没有落盘)。用量页没有用浏览器点开。
| | 失败条数 | 与对方相比多出来的名字 |
| --- | --- | --- |
| 开工基线 `853772bc` | 130 | — |
| 本分支 | 131 | `tests/test_consultation_native_layers.py::test_the_new_layer_leaves_every_existing_output_unchanged` |
其余 130 条名字与基线相同。多出来的这一条是既有的盘缓存抖动:缓存命中读回的 VedAstro 请求清单键序和现场重算不一样。这条测试会先跑掉新层再比整份输出,并且会剥掉 `vedastro_gateway`。它用的请求没有咨询标记,不走本单的校正闸开关。全量里失败一次。单独再跑:第一次失败,紧接着再跑一次通过。快速门里又失败一次,失败后用同一比较再跑,差异条数是 0。不记成新 bug。
v5 打分文件没有改动,没有重跑 77 例。
快速门 `scripts/run_quality_gate.py --profile quick`:退出码 1。1056 通过,1 跳过,1 失败。唯一失败仍是上面那条盘缓存测试。失败后立刻用同一比较再跑一遍,两边剥掉易变字段后差异条数是 0。这条失败跟着缓存时序走,不跟着本单的校正闸开关走。门禁跑完后,5 份待处理的 oracle 模板只多了回车换行,已还原,不进提交。
`next build`:这个工作树的 `frontend/node_modules` 是指到主检出的联接,Turbopack 拒绝「联接指向项目根以外」。改用门禁同一条 webpack 构建(`next build --webpack`):编译 3.6 分钟通过,TypeScript 2.5 分钟通过。收集页面数据时停在 `/api/consult`,原因是 Windows 不允许为 Skill 运行别名建符号链接(`EPERM`,`SKILL.md` → 临时目录)。路由表没有打出来,所以没能在这台机器上确认 `/` 仍是 Static。首页源文件没改。没有为了构建去改符号链接,也没有在工作树里重装依赖。
## Claude 验收(2026-10-05,Linux,Node 22)
**结论:通过,快进合入 staging。** 环境是 Linux,Node v22.14,Python 3.13。基线工作树是 `4c64733f`,被验分支是 `137ed6f4`。
| 项 | 基线 `4c64733f` | 本分支 `137ed6f4` | 判定 |
| --- | --- | --- | --- |
| Python 全量 `pytest tests`(-n 4) | 62 失败 | 62 失败,名单逐条相同 | 通过 |
| 新增 Python 测试 + 增长合同 | — | 11 passed | 通过 |
| 快速门 Python 段 | — | `pytest` ✓;唯一红是 npm test 步,即下一行的同一批环境失败 | 通过 |
| 前端 `npm test` | 4932 / 24 fail / 0 cancelled | 4936 / 24 fail / 0 cancelled,失败名单逐条相同,新增 4 条全过 | 通过 |
| `tsc --noEmit` / `npm run lint` | — | 0 错 / 0 error、126 warning | 通过 |
| `next build`(Turbopack,硬链 node_modules) | `/` ○ Static | `/` ○ Static | 通过 |
| 首屏 gzip(index.html 引用 JS+CSS,gzip -9 求和) | 636,225 B | 636,225 B(0%) | 通过 |
24 条前端失败与 62 条 Python 失败,两边名单相同,属于本机无 Docker / 无模型凭据等环境项。执行方在 Windows 上看到的 Docker 关停与盘缓存抖动,这次在 Linux 上没有出现。
**T1 实测**(补上执行方的环境缺口):在隔离 venv 里装 VedAstro SDK,走产品路径(`defer_optional_external_evidence: true`)。3 位名人 × 父母 / 年运,跑两轮共 12 次,每次都用全新的缓存目录。
| | 每领域耗时中位 | 校正闸 `official_closure_reason` |
| --- | --- | --- |
| 改前 `4c64733f` | 4.47 s(首次 5.89 s) | `official_raw_response_missing` |
| 改后 `137ed6f4` | 1.66 s(首次 2.02 s) | `deferred_in_consultation` |
- 每个领域省下约 2.8 s,降幅约 63%。
- 任务书写的「≤1.0 s」**没有达到**。我用 cProfile 拆过剩下的 1.66 s:
- 约 1.33 s 是顶层前台 VedAstro 的等待上限(`vedastro_foreground.finish → _join_foreground_vedastro`);
- 引擎本体约 0.07 s(盘缓存是热的)。
- 顶层这次等待是决策记录第 3 条(BUG-301)明确要保留的。任务书的 1.0 s 目标,是照着「外网全屏蔽」时的 0.75 s 定的,定得不对。这是任务书的问题,不是实现的问题。
- 本沙箱里顶层 VedAstro 拿不到已验证的结果,所以「复用当日已验证快照」这条路径没有被线上式请求走到,只有单元测试 `test_same_day_verified_snapshot_is_reused_ahead_of_the_negative_cache` 覆盖。
**审查意见(不阻断,留给后续)**:
1. 咨询路径从来不启动快照子进程,所以负缓存里存的只会是固定的 `deferred_in_consultation` 包,起不到「记住失败」的作用。而且它每人每天在 `api_scratch` 里写一个文件,没有清理。以后可以简化成不写盘。
2. `modelSteps` 默认第 1 步就是写答案的那一步。如果模型连续调用两次工具,第 1 步其实是第二次工具调用,这时 `answer.reasoning_ms` 记为空值。读数据时要注意这一点。
3. 部署后由产品在 `/admin/usage` 的「分段」列看一轮真实数字。这一列本轮没有在浏览器里点开过。