一次重构咨询聊了四十轮,中间做过三处方向不同的尝试,全部留在同一个会话里。到最后模型给出的方案里混进了第一轮已经被否决的设计——因为它仍然在上下文里,而且被反复提及过。
长会话的失效不是"模型变笨",而是上下文里累积了互相矛盾的约束。旧约束不会因为后来被否决而消失,它只是变成了一个更早、更频繁出现的信号。判断何时该重开,是使用这类工具最实际的一项技能。
1. 会话里会累积什么
| 累积物 | 影响 |
|---|---|
| 被否决的方案 | 仍作为候选反复出现 |
| 过期的约束 | 与新目标冲突 |
| 调试过程的噪音 | 占据窗口、稀释重点 |
| 失败尝试的错误信息 | 被当作已知事实 |
| 早期的口误与笔误 | 被后续引用 |
还有一个不对称:上下文是线性的,而任务状态是树状的。对话记录里,被放弃的分支与被采纳的分支占同样的篇幅;但在任务上,只有一条分支是活的。这个不对称随时间越拉越大。
第二项最隐蔽:约束的失效没有被记录。第一轮说"这个模块不能改",第五轮需求变了可以改,但上下文里"不能改"出现了十次,"可以改"只出现一次——权重上后者几乎不存在。
2. 该重开的五个信号
| 信号 | 说明 |
|---|---|
| 目标变了 | 不再是同一个任务 |
| 关键前提被推翻 | 之前的结论基础不成立 |
| 输出开始重复旧错误 | 否决过的方案又回来 |
| 上下文接近窗口上限 | 压缩会丢细节 |
| 需要"干净推理" | 要求无偏的评估 |
第三项是最直接的操作信号:当你第二次纠正同一个错误时,重开比继续争论便宜。
第五项在评审场景很典型:想让模型对一个方案做无偏评估,而它刚刚参与了这个方案的讨论——带着"我建议过"的上下文,它很难再给出独立意见。
第五个信号有个可操作的量化方式:当一次回答开始需要解释"我之前说的"时,说明上下文正在成为负担而不是助力。
// 重开判据:三个连续问题
Q: 当前目标与开头还是同一个吗? 否 → 重开
Q: 有没有被推翻但仍在上下文里的前提? 有 → 重开或显式声明作废
Q: 是否第二次纠正同一个错误? 是 → 重开
3. 重开时该带走什么
重开不是从零开始,而是把状态提炼成一份交接。
| 带走 | 丢弃 |
|---|---|
| 目标与验收标准 | 试错过程 |
| 已确认的事实与证据 | 被否决的方案细节 |
| 未决问题清单 | 情绪化表达 |
| 关键约束(有效期内) | 过期约束 |
| 已有的产物路径 | 中间草稿 |
交接单的写法有个要求:必须能被不认识这段历史的人读懂。所以它不该出现"按上面的方案"这类指代,每个条目都要自带上下文。
最容易丢的是"被否决的原因"。它应当被保留,但以结论形式("方案 B 因 X 不可行"),而不是以对话形式——后者会重新激活那段讨论。
// 交接单:重开时贴进去,成本低于重新解释
goal: 把订单导出改为异步任务,5 分钟内可下载
confirmed:
- 现有导出同步执行,超时阈值 30s,已确认会超
- 任务表可复用 existing_job 表(有 status/owner 字段)
decided_against:
- 方案B 流式响应:客户端不支持断点续传(已验证,见日志 #412)
open_questions:
- 失败重试次数上限由谁定
constraints:
- 不改动现有导出接口签名(兼容期一个季度)
artifacts:
- docs/export-async.md(第 3 节有表结构草稿)
4. 长会话里维持卫生的三种做法
| 做法 | 效果 | 成本 |
|---|---|---|
| 阶段性复述当前状态 | 让后续对话以最新状态为准 | 低 |
| 显式声明"以下作废" | 主动降低旧约束权重 | 低 |
| 分主题分会话 | 隔离不同任务 | 需要纪律 |
| 定期重开 + 交接单 | 彻底清理 | 中 |
分段复述的最小形态只有三行,成本极低:
// 阶段性状态复述:三行,插在对话里即可
当前目标:<一句话>
已确定:<两三条事实>
已作废:<一两条,带原因>
// 作用不是让模型"记住",而是把最新状态放到最近的位置
第二项常被忽略:作废声明要写在对话里,而不是只在脑子里。"第一轮提到的 X 已作废,因为 Y"这一句能显著降低旧信号的复现率。
// 作废声明的写法:说明什么、为什么、现在用什么
作废:不要再用同步导出的方案(第 3 轮提过),因为要求改为 5 分钟内异步下载。
现在以异步任务方案为准,任务表复用 existing_job。
5. 什么时候长会话反而更好
| 场景 | 为什么 |
|---|---|
| 反复打磨同一段文字 | 需要风格一致 |
| 逐步调试同一处缺陷 | 上下文连续是关键 |
| 同一份材料的连续追问 | 细节不宜丢 |
| 需要"记住我说过的偏好" | 累积有价值 |
第一项与第二项是长会话的典型优势:连续性能带来一致性,而重开会破坏语气或推理链。所以重开不是越多越好,判断依据是"上下文里有没有互相矛盾的信号"。
6. 排错:五种"越聊越不对"
| 现象 | 成因 | 处理方向 |
|---|---|---|
| 方案里混进旧设计 | 否决未显式声明 | 写作废声明或重开 |
| 反复纠正同一错误 | 错误在上下文里权重高 | 重开 + 交接单 |
| 细节记错 | 上下文被压缩 | 关键事实单独贴 |
| 回答越来越笼统 | 窗口接近上限 | 重开,只带结论 |
| 建议与我的约束冲突 | 约束过多互相矛盾 | 列出约束并去重 |
约束自检可以写成一个小清单,贴在任务开头:
// 约束自检四问:任何一条不成立,方案必然违反某条约束
1. 这些约束之间有没有直接冲突?(零停机 vs 不改接口 vs 一周上线)
2. 每条约束的有效期是什么?(兼容期一个季度,不是永久)
3. 哪些是硬约束、哪些是偏好?(硬:合规;偏好:命名风格)
4. 冲突时谁让步?(必须事先定,否则每次讨论都重来)
第五项值得单独处理:约束本身要先自检。如果一个任务里同时要求"零停机""不改接口""一周上线",那么模型给出的任何方案都会违反其中一条——问题不在工具,在约束集合本身不可行。
7. 边界:什么情况不必在意上下文卫生
| 场景 | 为什么 | 做法 |
|---|---|---|
| 一次性问答 | 无累积 | 不用管 |
| 短会话(五轮内) | 累积量小 | 不用管 |
| 纯信息查询 | 无约束冲突 | 不用管 |
| 已用外部文档承载状态 | 状态不在对话里 | 引用文档即可 |
还有一条与工具使用习惯有关的边界:把状态写在外部文件里,比留在对话里更可靠。计划、已完成项、待确认项写进一份文档,对话只负责当前这一步的推理——这样即使重开,成本也只是重新贴一次摘要,而不是重新解释整个过程。
判断口径一句话:这次对话里的旧结论会不会与当前目标冲突。会,就重开;不会,继续。
8. 自测
- 长会话的失效为什么不是"模型变笨"?旧约束为什么不会因为被否决而消失?
- 五个重开信号中,哪一个是最直接的操作信号?为什么"第二次纠正同一错误"就该重开?
- 重开时要带走哪五类内容、丢弃哪三类?为什么"被否决的原因"要以结论形式保留?
- 为什么"作废声明"要写在对话里而不是只在脑子里?
- 什么场景下长会话反而更好?判断依据是什么?
- 如果一个任务同时要求"零停机""不改接口""一周上线",该先检查什么?