SOP:碎步合并措施补强 —— 可并组分列 + 改-验批量化(2026-10-06)¶
主题目录:
merge-scenarios-20261006/|类型:C 类变更(改分析脚本 + 改全局规则) 变更对象:cost_audit/step_profile.py、~/.trae-cn/user_rules/rule-agent-efficiency.md交付物:本 SOP、backup/README.md、analyze_merge_scenarios.py
1. 背景¶
用户提问「还有哪些碎步场景可以上措施」。以 logs/req_shape.jsonl 中带 tool_names
的记录(2026-10-02 起)做全量归类——4532 步 / 327 轮 / 总成本 ¥56.48:
- 同轮内疑似可并组 530 组 / 2322 步;若全部合并,上限可省 ¥17.79(该期 31.5%);
- 分列后暴露的关键事实:
| 类别 | 组数 | 可省 ¥ | 占比 |
|---|---|---|---|
| 改-验循环(编辑与验证交替) | 311 | 14.02 | 78.8% |
| 取数命令(多次 RunCommand) | 148 | 2.67 | 15.0% |
| 其他 | 31 | 0.63 | 3.5% |
| 纯编辑连续(同一文件多次改) | 43 | 0.54 | 3.0% |
| 只读白名单(原口径唯一候选) | 13 | 0.18 | 1.0% |
- 「改-验循环」里 ≥6 步的 115 组独占 ¥9.33(全部可省的一半);
step_profile.py原口径只把「纯只读白名单」组当可信候选,实测仅覆盖 1% 的可并机会 —— RunCommand 取数(15%)与改-验循环(79%)全部隐形,这是自评连续几轮"看不见碎步"的根因;- 触发条件:原「强制合并优先」规则已下发,但度量口径与之不匹配,无从验收。
2. 目标(可验证)¶
step_profile.py的「疑似可并组」按类别分列输出(只读 / 取数命令 / 改-验循环 / 纯编辑 / 其他),排名视图与单会话视图都要有;- 全局规则「执行方式」表新增「改-验循环」行(批量化再合,边界为不减必要验证);
- 收尾自查 D 组「工具调用」「指标回填」、无异常判据 D 行、E 组 ② 改按分列口径;
- 向后兼容:
merge_groups返回值由 2 元组变 3 元组,全工程仅本文件调用(已 grep 确认)。
3. 前置条件¶
- 工程根
/home/rain/Documents/services/token_proxy,含venv/; logs/req_shape.jsonl可读(不可再生,绝不可删);- 改全局规则会使每轮前缀分叉(约 0.35 元/次),收尾后须开新会话。
4. 影响范围¶
| 项 | 说明 |
|---|---|
| 主机 | 仅 192.168.31.250(rain),单机 |
| 需停服 | 否:不动代理、不重启服务、不碰 8788 |
| 数据 | 只读 logs/req_shape.jsonl;不新增、不改写任何日志 |
| 窗口期 | 无外部依赖,数分钟内完成 |
| 规则 | 改 user_rules 后需开新会话才进前缀 |
5. 分步操作¶
步骤 1:备份(高危前置)¶
cd /home/rain/Documents/services/token_proxy
ts=$(date +%Y%m%d-%H%M%S)
mkdir -p merge-scenarios-20261006/backup/cost_audit merge-scenarios-20261006/backup/docs
cp -p cost_audit/step_profile.py "merge-scenarios-20261006/backup/cost_audit/step_profile.py.bak.$ts"
cp -p docs/HANDOFF.md "merge-scenarios-20261006/backup/docs/HANDOFF.md.bak.$ts"
cp -p /home/rain/.trae-cn/user_rules/rule-agent-efficiency.md \
"/home/rain/.trae-cn/user_rules/backup/rule-agent-efficiency.md.bak.$ts"
chmod 600 merge-scenarios-20261006/backup/cost_audit/*.bak.* \
merge-scenarios-20261006/backup/docs/*.bak.* \
/home/rain/.trae-cn/user_rules/backup/rule-agent-efficiency.md.bak.$ts
预期:三份备份 md5sum 与原件一致、权限 600。
失败判断:md5 不一致 → 重新复制。
台账:项目文件见 backup/README.md;
全局规则按既有约定登记在 ~/.trae-cn/user_rules/backup/README.md(避免两处重复登记)。
步骤 2:采集口径分列(step_profile.py)¶
三处改动,全部为新增/扩展,不改既有语义:
① 常量区新增 WRITE_TOOLS、KINDS(五类)与 classify_group(tools_per_step):
grep -n "WRITE_TOOLS\|KINDS = \|def classify_group" cost_audit/step_profile.py # 预期各命中
判类优先级:含写类且含 RunCommand → write+run(改-验);含写类 → write;
含 RunCommand → run;否则全在 READ_TOOLS 内 → read;其余 → other。
② merge_groups(detail) 由返回 2 元组改为 3 元组,第三个返回值按 KINDS 给出
{"groups": n, "steps": m};组内是否"只读"的判定逻辑不变。
③ analyze() 增 merge_kind 字段;print_rank 在合计行后、print_conv 在只读行后
各打印一行分列。
坑:分类只做归类、不判依赖——req_shape 不记工具参数,组内各步是否互为依赖
在数据上不可判定,文档与输出提示均须写明「判不出依赖则不可强并」,避免被误读成"必须合并"。
./venv/bin/python -m py_compile cost_audit/step_profile.py # 预期无输出,退出码 0
实现体:cost_audit/step_profile.py,实际执行以实现体为准。
步骤 3:全局规则补「改-验循环」与分列口径¶
在 ~/.trae-cn/user_rules/rule-agent-efficiency.md 共改 6 处:
- 「执行方式」表「同一轮内多个独立信息收集」行之后插入「改-验循环」行;
- 收尾自查 D 组「工具调用」行:可并组改为分列,并要求点名取数命令与改-验循环;
- D 组「指标回填」行:样本字段由「只读组 y」改为「可并组分列 y」;
- 无异常判据 D 行:加「同轮内取数命令 / 改-验循环组数未回落」;
- E 组「逐条判定」② 补「含改-验循环批量化——验证项合并为一次执行」;
- D 组取数注释行同步为分列口径。
grep -n "改-验循环" /home/rain/.trae-cn/user_rules/rule-agent-efficiency.md # 预期命中 4 行
坑:该文件进每轮 system prompt,改动后旧会话每轮多付约 0.35 元——收尾即开新会话。
步骤 4:验证(见第 6 章)¶
6. 验证¶
| 项 | 命令 | 预期 |
|---|---|---|
| 语法 | ./venv/bin/python -m py_compile cost_audit/step_profile.py |
退出码 0 |
| 排名视图 | python3 cost_audit/step_profile.py --top 3 |
合计行下出现「可并组分列:只读 … | 取数命令 … | 改-验循环 … | 纯编辑 … | 其他 …」 |
| 单会话视图 | python3 cost_audit/step_profile.py --conv <新格式会话 id> |
出现「分列:… 取数命令 N 组/M 步 | 改-验循环 …」 |
| 旧记录兼容 | 同日 --top 3(命中 9 月旧会话) |
类别全落「其他」,不报错 |
| 调用方影响 | grep -rn "merge_groups" --include=*.py |
仅 step_profile.py 自身 |
| 规则落地 | grep -n "改-验循环" <规则文件> |
命中 4 行(新会话后生效) |
取数复核(与本次分析对账用):
python3 merge-scenarios-20261006/analyze_merge_scenarios.py
# 口径差异须知:本脚本按 (conv, turn) 分组(同轮内),step_profile 按 conv 分组(可跨轮),
# 故两组数不同;分列占比应量级一致(改-验循环 ~79% 可省成本)。
7. 回滚¶
备份位置:merge-scenarios-20261006/backup/;全局规则备份在 ~/.trae-cn/user_rules/backup/。
台账:backup/README.md。
cd /home/rain/Documents/services/token_proxy
ts=<备份时间戳>
# 回滚脚本
cp -p "merge-scenarios-20261006/backup/cost_audit/step_profile.py.bak.$ts" cost_audit/step_profile.py
./venv/bin/python -m py_compile cost_audit/step_profile.py && echo ROLLBACK_OK
# 回滚全局规则
cp -p "/home/rain/.trae-cn/user_rules/backup/rule-agent-efficiency.md.bak.$ts" \
/home/rain/.trae-cn/user_rules/rule-agent-efficiency.md
# 回滚 HANDOFF(若本次已更新)
cp -p "merge-scenarios-20261006/backup/docs/HANDOFF.md.bak.$ts" docs/HANDOFF.md
回滚后验证:--top 3 不再出现「可并组分列」行;规则文件 grep 改-验循环 无命中。
回滚触发条件(任一达标即回滚):py_compile 非 0、两个视图报错、分列行缺失、
或旧记录导致异常(类别全落「其他」属正常,不算异常)。
8. 风险说明¶
| 风险 | 缓解 |
|---|---|
| 改全局规则致前缀分叉(约 0.35 元/次) | 收尾即开新会话(Hook 已提醒) |
| 分列被误读为「这些步必须合并」 | 脚本 docstring、输出提示、规则行三处均写明「只归类、不判依赖;必要验证不可省」 |
旧记录(10-02 前无 tool_names)类别全落「其他」 |
属预期,已在输出提示中说明,非缺陷 |
| 分类阈值仍用「末尾 tool 消息 < 2000 字节」 | 与原口径一致,保证与既有基线可比;如需调整用 --small |
附录¶
A. 交付物清单¶
| 产物 | 说明 |
|---|---|
analyze_merge_scenarios.py |
一次性只读分析脚本(本次结论的数据来源,可复跑) |
SOP.md |
本文件 |
backup/README.md + backup/ |
项目内两份备份的台账与文件 |
~/.trae-cn/user_rules/backup/rule-agent-efficiency.md.bak.20261006-224350 |
全局规则备份(按其既有目录与台账) |
B. 为何不出 RUNBOOK¶
本次为既有只读脚本的统计维度增强:入口命令(--top / --conv)、参数、
数据源与使用方式零变化,变的只是输出内容;其用法由脚本 docstring 与
docs/PROJECT-MAP.md 第 1 节路由表承载。若日后新增子命令或独立工具,再补 RUNBOOK。
C. 本次分析的口径与局限¶
- 组判定:同一轮(turn)内连续 ≥2 步、每步末尾消息为 tool 且字节数 < 2000;
- 「可省」= 组内除首步外各步成本之和(合并后不再单独重放的部分),是上限,未扣除合并失败的代价;
- 成本单价沿用
step_profile.py:命中 0.02 / 未命中 1.0 / 输出 4.0(元每百万); - 无法从数据判定组内依赖关系,故所有结论均为「疑似」。
来源:
/home/rain/Documents/services/token_proxy/merge-scenarios-20261006/SOP.md| 最后更新:2026-10-06 22:46(由build/sync.py同步,请勿在站点侧修改)