fix(consult): stop the consult-gate VedAstro wait and record step timing

Consult turns reuse a same-day official snapshot inside the rectification gate, or record deferred_in_consultation instead of starting another 4-second snapshot. Classification, step 0, step 1, and the time to the first answer character go into the existing usage metadata and a new admin usage column.

BUG-1231, BUG-1232
This commit is contained in:
jesse-ux
2026-10-05 02:33:36 +08:00
parent 4c64733f91
commit 137ed6f408
16 changed files with 1188 additions and 9 deletions
+30
View File
@@ -16627,3 +16627,33 @@
- 相关记录:BUG-995(前端测试要同时看 cancelled 和退出码)。
- 复发自:无
- 修复版本:待发布
## BUG-1231 | 咨询链校正闸同步白等 VedAstro 官方快照,失败还不缓存
- 状态:resolved(分支 `codex/consult-latency-quickwins-20261005`)
- 首次发现 / 最近更新:2026-10-04 / 2026-10-05
- 来源:10-04 只读审计。任务书 `docs/tasks/TASK-consult-latency-quickwins-20261005.md`。写任务书时,在装了 vedastro SDK 的沙箱网络下按产品路径测得每个领域约 4.6 秒,第二轮仍是 4.6 秒。这组秒数不是本轮在这台机器上重测的。
- 影响面:普通对话引擎里校正闸附带的 `rectification.vedastro_gateway`。顶层前台 VedAstro(BUG-301)不改。直接调用 `/api/rectification_gate`、请求里没有咨询标记时,仍走原来的官方快照。
- 现象:同一份咨询响应里,顶层 `vedastro_gateway` 可以已经是 `official_verified`(BUG-727 的当日缓存),校正闸里的 `official_closure_reason` 仍是 `official_raw_response_missing`。校正闸每次再起一个最多 4 秒的子进程。失败结果不进正缓存,同一天每一轮都再等。屏蔽外网时引擎每个领域约 0.75 秒,这 4 秒是额外等待。生产机器是不是也在等,本轮没能在 staging 上确认(进度记录 T0)。
- 根因:咨询工作流把「外部证据可以后做」这个标记只传给顶层前台任务。校正闸仍调用原来的官方快照。出生时间进校正闸时被规范成浮点,和正缓存的键对不上,所以当天已经有的官方结果也复用不到。
- 修复:只在校正闸、且请求带了这个标记时,改走咨询专用路径。先用原始请求里的出生数据、岁差、交点、UTC 日期查正缓存,命中已验证结果就复用;否则查当天的负缓存;都没有就记 `official_closure_reason = deferred_in_consultation`,不起子进程,也不标成已验证。负缓存单独存放,只认当天的 UTC 日期。没有这个标记的校正请求仍调用原来的 gateway。
- 验证:`tests/test_vedastro_consultation_snapshot.py`。咨询路径不调用快照子进程,也不调用原来的 gateway。负缓存同日命中、次日失效,邮箱不进缓存。当天已验证快照优先于负缓存,整数小时和规范后的浮点小时靠原始请求对齐。没有标记的校正面,返回包与现场结果逐项相同。增长合同通过,没有新增类方法。本机没有 vedastro SDK,4.6 秒降到 1 秒以内没有重测。v5 打分文件没有改动,本轮没有重跑 77 例。
- 防复发:上述测试。开关只放在校正闸里,不放进顶层 gateway,避免把 BUG-301 的前台核对也跳掉。
- 相关记录:BUG-727(当日正缓存)、BUG-301(顶层前台照旧,本单不推翻)。
- 复发自:无
- 修复版本:待发布
## BUG-1232 | 普通对话看不到第 0/1 步耗时和推理 token,分类耗时进不了用量
- 状态:resolved(分支 `codex/consult-latency-quickwins-20261005`)
- 首次发现 / 最近更新:2026-10-04 / 2026-10-05
- 来源:10-04 只读审计。任务书同上。审计写答题步大约 1 万推理 token、大约 45 秒,但线上记录里没有逐步耗时和推理 token,后面的「限制推理强度」「精简说明」对不上数。这组数字不是本轮实测。
- 影响面:`[agent-observability]` 日志,以及用量账本里已有的 JSON 字段。不改表,不加迁移。不改提示词和数据卡。
- 现象:已有首字节、工具耗时、答案首输出、整轮耗时、总 token。没有第 0 步和第 1 步各自的耗时,也没有推理、输出、输入、缓存输入 token。分类耗时没有进用量记录。没有「第 1 步开始到第一个正文字」的时间。
- 根因:流式过程没有按步骤记下供应商返回的 usage。用量记录和用量页都没有这些字段。
- 修复:流式过程记下第 0 步和第 1 步的耗时和供应商 usage。供应商没返回的数写空,不估算。`answer.reasoning_ms` 从第 1 步开始计到第一个非空白正文字;第 0 步的旁白不计。分类耗时同时写入可观测事件和用量记录。步骤数字写入用量记录的 `modelSteps` 和 `answer.reasoning_ms`。用量页多一列「分段」。各领域工具耗时保持原字段。正文、提示词、出生资料、用户标识不写入这些字段。
- 验证:`frontend/tests/consult-latency-timing-20261005.test.ts` 4 项通过。模拟步骤的日志和用量字段齐全,不含植入的正文。流式一轮把计时留在运行状态上,公开回执和响应正文里没有这些字段,也没有那段正文。`tsc --noEmit` 0 错。`npm run lint` 0 error,既有 warning 未动。用量页本轮没有登录打开。
- 防复发:上述测试锁住对话路由、用量列表查询和页面列名。可观测结构是严格对象,多出来的正文字段进不了事件。
- 相关记录:10-04 咨询耗时审计(任务书事故实证第 2 条)。
- 复发自:无
- 修复版本:待发布
@@ -0,0 +1,115 @@
# 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。首页源文件没改。没有为了构建去改符号链接,也没有在工作树里重装依赖。
+1 -1
View File
@@ -421,5 +421,5 @@
| `TASK-astrologer-rulings-batch5-20261004.md` | `PROGRESS-astrologer-rulings-batch5-20261004.md` | 占星师第六轮:Rath 双主星按 p.43(a)–(e)、罗计尊贵按 Rath Table 9(仅 Narayana 内)、子运方向 p.51 例外与书内分歧标注、Wadiyar 两对标软件特例;年主选不出时不再用 Muntha 主星顶替(对齐上游 03bea6ed);Rath 替换校正 v5 重试算(研究)(BUG 从 1223 起) | 已实现待验收(T2–T5 完成;T1 按红线停下 blocked;T6 研究分支已跑) | 分支 `codex/astrologer-rulings-batch5-20261004`(未推送;BUG-1223~1227;校正分数不变、未升版本);研究分支 `codex/narayana-rath-rectification-trial-20261004`(不合入) |
| `TASK-astrologer-rulings-batch6-20261004.md` | `PROGRESS-astrologer-rulings-batch6-20261004.md` | 第七轮裁定(共享仓书面回复,产品采用;问 1 选 A):Rath 版双主星按 p.43 (a)–(e)(BUG-1227 解除 blocked,推翻第五批红线 2 的 Table 17 年数底线);第 5 级宫主度数只倒算计都(p.71 脚注 42);罗计旺陷 ±1 年;同宫两主比经度;BUG 从 1228 起 | 待验收 | 分支 `codex/astrologer-rulings-batch6-20261004`(BUG-1227~1229;校正分数文件未改、未升版本) |
| `TASK-gate-log-volume-20261004.md` | `PROGRESS-gate-log-volume-20261004.md` | 门禁 validate 单步日志 4.4 万行 / 2 MB 网页打不开(run 3170):快速门只打摘要(失败给末 200 行 + 日志文件)、前端测试门禁上 dot + 失败汇总(本机仍 TAP)、拆分 validate 为 7 个 step(产品授权改 workflow,只限拆分与重定向);检查一项不少 | **已实现待验收**(BUG-1230;未推送、未部署;Gitea 各 step 页面是否打得开留待推送后由产品确认) | 分支 `codex/gate-log-volume-20261004` |
| `TASK-consult-latency-quickwins-20261005.md` | `PROGRESS-consult-latency-quickwins-20261005.md` | 普通对话耗时两项快修:咨询链校正闸不再同步白等 VedAstro 官方快照子进程(每域约 4 s,复用顶层缓存 + 负缓存,不推翻 BUG-301);补分段计时(第 0/1 步耗时、推理 token、分类耗时进日志与 usage)。推理强度/精简说明待模型 key 另单(BUG 从 1231 起) | 待领取 | 分支 `codex/consult-latency-quickwins-20261005` |
| `TASK-consult-latency-quickwins-20261005.md` | `PROGRESS-consult-latency-quickwins-20261005.md` | 普通对话耗时两项快修:咨询链校正闸不再同步白等 VedAstro 官方快照子进程(每域约 4 s,复用顶层缓存 + 负缓存,不推翻 BUG-301);补分段计时(第 0/1 步耗时、推理 token、分类耗时进日志与 usage)。推理强度/精简说明待模型 key 另单(BUG-1231、BUG-1232) | 已实现待验收 | 分支 `codex/consult-latency-quickwins-20261005` |
| `TASK-rectification-nadi-seconds-research-20261005.md` | `PROGRESS-rectification-nadi-seconds-research-20261005.md` | **「纳迪秒级校准」可证伪检验(离线)**:竞品宣传「问前事到天 → 秒级」。本仓主链只用三层小运,Sookshma / Prana 与 D150 从未进评价集;v5 真值 52/77 是整 5 分钟(秒级无真值可对)。N0 五层小运 + D150 底座(前三层与主链对账 0 差)、N1 拟合率 vs 安慰剂日期(核心)、N2 留一件预测、N3 六题后区间内再细分能否提头名、N4 岁差 / 坐标 / 时间扰动的噪声地板、N5 D150 结构层(原文比对 blocked)、N6 结论 + 对外口径草稿。规则先登记再跑;不改生产代码;不得重调 BUG-1091 已关的权重 | 待领取 | 分支 `codex/rectification-nadi-seconds-research-20261005`(BUG-1240) |