跳转至

SOP:轮次口径修复 —— 新增 turn_seq(步/轮 终于可算准)

  • 变更日期:2026-09-23
  • 变更主题:turn-seq-fix-20260923
  • 影响对象:
  • proxy.py:_extract_turn_meta 新增 turn_seq,_record 落盘该字段
  • cost_audit/analyze_usage.py:轮次标识新增 turn_id_of(),优先 conv_key#turn_seq、旧记录回退 turn_key
  • 新增 turn-seq-fix-20260923/verify_turn_seq.py(离线验证)
  • 未生效状态:proxy.py 是 systemd 服务,改动需重启代理才生效(见第 5、8 章)

1. 背景

「步/轮」是判断「执行效率规则是否有效」的核心指标,但它的分母一直不可靠:

  • turn_key = 末条用户输入的哈希。用户重复发同一句话(例如连说多次「好的,执行吧」)时哈希相同, 该 Agent 的多次步进会被合并成一轮。本会话实测:实际 10 次用户输入被算成 6 轮 → 「步/轮」20.7 被高估 至真值 12.3(偏差约 7 成)。
  • 尝试用「相邻请求时间间隔」切分校正,失败:阈值 120s 就把本会话 10 轮压成 3 轮、300s 压成 1 轮 —— 长任务里 Agent 连续工作,间隔根本分不开。

结论:只能改数据源,让 proxy 直接记录与文本无关的轮次序号。

2. 目标

  1. usage.jsonl 每条新记录含 turn_seq = 该会话内用户输入条数(同一轮内多次步进不变、用户新发一次 +1)。
  2. 分析脚本统计轮次时优先用 conv_key#turn_seq;2026-09-23 之前的旧记录无该字段,自动回退 turn_key。
  3. 离线验证(假上游 + 临时端口)覆盖:序号递增、同文本重复提问不再合并、同轮重复步进不被拆开、 内部调用为 None。
  4. 不改变任何转发行为;旧数据兼容。

3. 前置条件

  • 工程内 venv(./venv/bin/python,分析脚本需 PyYAML)
  • 可写 proxy.py 与 cost_audit/analyze_usage.py
  • 离线验证需两个空闲本地端口(自动探测),不触碰生产端口 8788、不写生产 logs/
  • 生效需重启代理:systemctl --user restart token-proxy(会打断在途流式回答,见第 8 章)

4. 影响范围

项 值
主机 192.168.31.250(单机),用户服务 token-proxy
组件 请求路径上的 proxy.py(仅新增一个记账字段,不改转发逻辑)+ 只读分析脚本
是否需停服 需重启代理(不是停服:重启即恢复,约 1 秒;但会打断在途流式回答)
数据影响 usage.jsonl 新增字段,旧行不变 → 向后兼容;不可再生数据无删除风险
回滚成本 覆盖回备份 + 再重启一次
窗口期 由用户选(建议在自己不在等待回答时执行)

5. 分步操作

本节为等价操作序列(供复核与手工复现),实现以实际编辑为准。

cd /home/rain/Documents/services/token_proxy
stamp=$(date +%Y%m%d-%H%M%S)                                       # 时间戳
base=turn-seq-fix-20260923/backup/home/rain/Documents/services/token_proxy
mkdir -p "$base/cost_audit" "$base/docs"                            # 备份目录(高危动作前置)
cp -p proxy.py "$base/proxy.py.bak.$stamp"                          # 备份(覆盖写前必做)
cp -p cost_audit/analyze_usage.py "$base/cost_audit/analyze_usage.py.bak.$stamp"
# ① proxy.py:_extract_turn_meta 返回 "turn_seq": len(texts);empty 与 meta 模板补该键;
#              _record 的 entry 落盘 "turn_seq": meta.get("turn_seq")
# ② cost_audit/analyze_usage.py:新增 turn_id_of(),collect() 的 turn 字段改用它
python3 -m py_compile proxy.py cost_audit/analyze_usage.py          # 语法自检
./venv/bin/python turn-seq-fix-20260923/verify_turn_seq.py          # 离线验证(不碰生产)
./venv/bin/python cost_audit/analyze_usage.py                       # 兼容性:旧数据仍可分析
systemctl --user restart token-proxy                                # 让新字段生效(由用户择机执行)

6. 验证

离线验证(已执行,9/9 通过;临时目录保留在 /tmp/turn-seq-verify-*):

[通过] 6 次请求均 200
[通过] usage.jsonl 落 6 条
[通过] turn_seq 依次为 1,2,3,4,4(第 5 条为同轮重复步进)
[通过] 旧口径事实:重复同一句话的两次提问 turn_key 相同(会被合并成一轮)
[通过] 新口径:两条记录的轮次标识不同(不再合并)
[通过] 新口径:同一轮内的多次步进轮次标识相同(步/轮 分母不被拆大)
[通过] 同一会话的 conv_key 稳定
[通过] 内部调用(无 <user_input>)turn_seq 为 None
[通过] 运行日志无异常栈

兼容性:改后的分析脚本跑现有(无 turn_seq)数据正常,轮次计数与此前一致(回退 turn_key)。

生效后验证(已于 2026-09-23 04:50:56 重启并实测通过):04:51:05 的记录 turn_seq=11 —— 与本会话真实 用户输入条数(11 次)一致,而旧口径只算得 6 轮;同一会话 turn_key 仍为同一哈希(5 次「好的,执行吧」 文本相同)—— 旧口径把多轮合并成一轮由此定证。核对命令:

tail -n 3 logs/usage.jsonl | ./venv/bin/python -c "import sys,json; [print({k: json.loads(l).get(k) for k in ('ts','turn_seq','turn_key','prompt')}) for l in sys.stdin]"

预期:新记录含 turn_seq(整数,随用户新提问递增);再跑 ./venv/bin/python cost_audit/analyze_usage.py, 「用户轮次」应比旧口径更大(重复提问被正确拆开)。

7. 回滚

  • 备份位置:turn-seq-fix-20260923/backup/home/rain/Documents/services/token_proxy/...(4 条);台账见 turn-seq-fix-20260923/backup/README.md。
  • 回滚步骤:
cd /home/rain/Documents/services/token_proxy
b=turn-seq-fix-20260923/backup/home/rain/Documents/services/token_proxy
cp "$b/proxy.py.bak.20260923-044750" proxy.py                                 # 覆盖回改动前
cp "$b/cost_audit/analyze_usage.py.bak.20260923-044750" cost_audit/analyze_usage.py
systemctl --user restart token-proxy                                          # 需再重启一次
  • 回滚后验证:./venv/bin/python cost_audit/analyze_usage.py 正常输出;新记录不再含 turn_seq(旧字段不变)。
  • 触发判据(任一达标即回滚):① 代理重启后 /healthz 不通或转发报错;② 新记录缺 turn_seq; ③ 落盘的 turn_seq 在同轮内跳变(说明口径写错)。

8. 风险说明

风险 缓解
重启代理会打断在途流式回答(改的是请求路径上的代码,必须重启) 由用户择机执行重启,命令已给出;重启约 1 秒,失败可用第 7 章回滚
turn_seq 语义是「会话内 <user_input> 条数」,若 Trae 在同一轮里追加额外 <user_input> 块(如同一轮补充发言)会 +1 那确实是新的用户输入,算作新轮次符合预期;若将来发现系统注入的合成块,应在 _extract_user_inputs 侧过滤,不改本字段语义
第三方客户端(不注入 <user_input>)全程无该字段 turn_seq 为 None,分析脚本自动回退 turn_key,不影响其它调用方
新增字段使 usage.jsonl 单行略变大 仅一个整数,量级可忽略

附录:交付物清单

文件 说明
proxy.py 新增 turn_seq(待重启生效)
cost_audit/analyze_usage.py 轮次口径切换 + 旧数据回退
turn-seq-fix-20260923/verify_turn_seq.py 离线验证脚本(可重复执行)
turn-seq-fix-20260923/SOP.md 本文件
turn-seq-fix-20260923/backup/README.md 备份台账(4 条)

来源:/home/rain/Documents/services/token_proxy/turn-seq-fix-20260923/SOP.md | 最后更新:2026-09-23 04:51(由 build/sync.py 同步,请勿在站点侧修改)