跳转至

2026-09-16 生产正文标签诊断

范围与访问方式

  • 生产主机 SSH 别名 tender,容器 tender-api、tender-worker-generation;环境 prod,数据库 tender_prod。
  • 两容器镜像 ID 一致:sha256:2e268034726003ff792b863999ab01bbc54d2efad2a88311baf07a3262cc2f65。
  • 两容器的 section_service.py SHA-256 一致:cfb91fefa6198d97b30739a8c1de487b1258d42c4629b83a854d5a230ef404b7。
  • 部署版本只接受精确的 <正文>…</正文>,尚无本地新增的 section_output_parser.py。
  • 先按近 30 天汇总标签错误,再对近 7 天失败原文做逐条对照。固定复核创建时间上界为北京时间 2026-09-16 12:22:41(UTC 2026-09-16T04:22:41.550428Z)。近 30 天发现的标签错误均在这 7 天内。
  • 查询使用 SET TRANSACTION READ ONLY 和 20 秒语句超时。完整原文留在服务器内存,只返回协议标签、计数和少量 trace ID;没有导出正文、项目名称或配图 JSON。
  • 自动审批拒绝了初拟的完整原文导出,随后采用上述脱敏方式完成;未部署、重启、重放生成请求或修改生产数据。

失败形态与修正

共检查 916 条 section_content 且错误含“正文…标签”的生成记录。这是生成尝试数,不是用户数或最终失败章节数。

实际返回结构 finish_reason 数量 修正前本地规则 修正后处理
<正文>…<正文>,第二个标签在末尾 stop 519 作为重复标签拒绝 恢复两标签之间的正文
<正文>…,缺少整个结束标签 stop 138 拒绝 仅在正常结束标记下使用 EOF 边界
<正文>…,缺少整个结束标签 length 258 拒绝 仍拒绝,并明确提示生成被截断
<正文>…,缺少整个结束标签 未记录 1 拒绝 仍拒绝,不能推断已经正常结束

此前加入的半闭合括号、转义等规则尚未覆盖这两种生产高频形态;本次修正后,657 条可恢复,259 条继续拒绝。长度截断组的 completion token 数集中在约 8192,和 finish_reason=length 一致;本次未改动模型输出上限。

915 条失败记录的持久化 Prompt 明确包含 </正文>,另 1 条没有 Prompt 记录。因此不能把这些错误归因于用户截图中的结束标签写错。

代表 trace(只用于后续只读关联):

  • 末尾重复开始标签:42a49f8e-5a3f-4035-95aa-bbbdd16f314a。
  • 正常结束但漏结束标签:cbd733e9-6fb1-4c8c-9ea6-bd12dbb5bbbc。
  • 长度截断:34d5ebed-a186-4702-a763-55eb8bc35809。
  • 缺少结束原因:f3b153d9-0e8c-4010-b563-f39132b18e58。

验证结果与限制

  • 将当前本地纯解析函数发送到生产容器的一次性 Python 进程,在内存中对照原文;没有覆盖部署文件或调用 LLM。
  • 657 条恢复记录分别按每片 257 字符重新分片,流式拼接与最终正文提取全部一致(忽略首尾空白)。这是分片模拟,不是实际供应商网络分片回放。
  • 最新 200 条原本成功的记录:新旧最终正文逐字相同;流式输出与最终正文全部一致(忽略首尾空白)。未声称对全部成功记录做了回归。
  • 固定时间窗内 18,731 条正文 trace 均未出现“配图需求”,所以本次没有实际生产配图输出用于证明覆盖率。配图的末尾同名标签兼容已按相同边界规则实现,并补充合成回归用例。
  • 当前 generation_section_jobs 中按同类错误文本查询没有记录;不能将 916 条 trace 直接视为仍待重试的后台任务。
  • 持续运行的 prod 可能在统计上界之后继续产生错误;这些本地修正尚未发布。
  • 初次诊断已补充解析和 service 传递 finish_reason 的回归用例,当时未运行 pytest;后续用户要求模拟后的执行结果如下。

全部留存错误模拟(北京时间 2026-09-16 12:38:54)

本轮按用户要求只做模拟。数据库使用可重复读的只读事务,以同一快照读取全部留存的 scene_key=section_content 且错误文本含“标签”的记录,不再限制近 7 天。共 917 条,创建时间从 2026-09-11T00:56:39.862130Z 到 2026-09-16T04:38:42.266678Z;比前次增加 1 条末尾重复开始标签的失败。

形态 数量 最终模拟结果
末尾重复 <正文>、正常结束 520 全部恢复
漏写结束标签、正常结束 138 全部恢复
达到输出长度上限 258 全部按预期拒绝
未记录结束原因 1 按预期拒绝
  • 658 条恢复正文均与独立按原始标签位置截取的预期正文逐字相同,不仅是两种新解析路径互相比较。
  • 每条恢复记录分别模拟整段输入、每片 17 字符、每片 257 字符和所有实际标签逐字拆分;4 种方式均为 658/658 一致(流式比较忽略首尾空白)。未发现新的未知形态、错误放行或流式不一致。
  • 同一快照抽取最新 200 条成功记录:最终正文与旧规则逐字相同,17 字符分片结果也全部一致。
  • 本地执行 make test PYTEST_ARGS='tests/test_section_output_parser.py tests/test_section_service_full_code_paths.py tests/test_generation_code_paths.py -q',最终结果 38 passed, 26884 subtests passed。这些是定向解析/生成测试,不是全仓测试。
  • 模拟发现并仅在本地修复一处代码围栏边界问题:单反引号标签包装不应跨行吞掉相邻代码围栏的反引号。修正为包装与标签同行,标签内部仍可包含换行;修正后重新完成上述真实记录与本地用例模拟。
  • 最终模拟解析模块 SHA-256:843933e45265a45479c0759fe994a8ecdc927627c8816ab8811dd3b25296e7ec。
  • prod 部署源码哈希仍为前述 cfb91f...404b7。全程没有部署、重启、LLM 请求重放或生产文件/数据写入,原文仍只在服务器内存中处理。

结论:截至本次快照,所有已观察到的可恢复标签错误均被覆盖;剩余 259 条属于截断或缺乏正常结束证据,不能通过盲目补标签认定正文完整。结论不代表任意未来输出格式都已穷尽。