Chat 审查与换窗守则
这一页讲的是 Chat 里故意写死、不建议随手改的 11 条限制。每条分三部分:现在是什么样,为什么这样设计,真要改的话得一起动哪些地方。装上以后觉得某处「太死了」,先看这里。
审查:草稿写完、发出之前
01审查开始以后,本轮不能再调用任何工具
草稿一进审查,宿主就在数据库里给这一轮记上 tools_sealed。之后这一轮再调工具,宿主直接拒绝。只有一个例外:官端信箱的那两个工具会被截下来,当作「待发出的意图」先存着,不往上游写。
- 审查审的是这份草稿。改稿时如果还能调工具,模型就会拿新查到的东西写出新断言,可这些断言谁都没审过,审查等于白做。
- 只改一次,才有尽头。要是允许「改稿 → 调工具 → 再审 → 再改」,一条回复可能来回转好几圈,用户在手机上一直看着空白。
- 查证据是宿主的活。需要翻历史的地方,宿主在审查阶段已经查过,证据直接递给模型,模型用不着自己再去翻。
- 写操作不能抢在终稿前面。信箱这类「我说过什么」的写入,要等终稿定下来再按实际发出的内容提交。不然就会出现「记了说过,其实没发」。
- 封条由宿主记,不靠模型自觉。封条存在宿主的数据库里,不是写在提示词里求模型别用。审查前拿到的工具许可,也不能在审查后拿来重放。
草稿里写「我这就去翻一下」,审查一过,模型真去调工具,就会撞上封条,这一轮失败。现在只让这一轮失败,会话不锁,下一条消息照常发。
在人格或系统提示里写清楚:要用的工具先用完,再写草稿;草稿里不要承诺「待会去查」。「拒绝工具但让这一轮正常收尾」还没做:要做,得一起改换窗对审查轮的证明。
02只改一次,改完不再审
保证延迟有上限、不打转。审查意见里专门写着「这是本轮唯一一次核对或改稿」「不要再调用核对、检索或其他工具」。
03审查提示词被哈希锁在三个地方
审查说明的 sha256 同时写在 adapter 的审查客户端、rollout 配置和 Brain 的审查中转里,三处对不上,审查就不启用。
App 的 hook 路径和官端 pending 路径必须用同一份规则。哈希锁住了,就不会有人只改了一边、另一边还在按旧规则审,悄悄跑偏。
三处的哈希一起重算,两条路径一起测。V4 里审查模型的名字放在配置文件里,换模型不用动哈希。
04查历史有固定时限
整个审查查历史的总时限是 4500ms:第一段 3700ms,留 800ms 给补查。adapter 会检查这个值,对不上就拒绝。
审查卡在用户和回复之间,多等一秒用户就多看一秒空白,所以总时间必须封顶。超时了只算「没核到」,不算「查过、没有」:草稿不会因为超时就被改成不确定的说法,也不能借超时编出相反的事实。
05三道不靠审查模型的硬规则
审查模型是个又小又快的模型,大约半秒一次,偶尔会漏。下面三类句子长相固定,宿主用规则直接抓,一旦命中就强制查一次历史:
- 说「不记得」「没印象」「找不到」:拿说忘了的那个名字去查。
- 承认「是猜的」「没去翻」:拿猜的那件事去查。
- 反问用户早就说过的稳定事实,比如宠物的品种、名字、生日、毛色、长相、年龄:拿名字去查,查到答案就别再问。
查询只用名字,不要加「品种」这类词。加了以后,检索就不把它当名字查,结果篇幅会变小,答案可能挤不进去。
规则只认人名和代词。「你今天想吃什么」这种普通问句,以及用户这一轮才第一次提到的新对象,都不会命中。
06冰箱贴
冰箱贴是用户写给模型的固定提醒。审查时,草稿只要违反了某一张,就要改。冰箱贴原文会原样交给模型,不改写,也不摘要。包里的冰箱贴是空的,用户自己写。
换窗:窗口快满时自动接上
上下文快到上限时,宿主把旧对话折叠成一张窗口便签,只保留最近一段原话,开一个新的 Claude 会话,把便签和这段原话接上。对用户来说,聊天不断。
07保留下来的原话逐字节核对
换窗后保留的那段原话,包括工具调用、工具结果和带签名的 thinking,必须跟旧会话里的逐字节一致,对不上就拒绝换窗。
宁可这次不换,也不能让模型在新窗口里读到一段被改过、却以为是原话的东西。
08Claude Code CLI 的版本要锁定
adapter 会改写 CLI 发出去的请求,比如把工具目录折叠、给缓存加断点。它也会解析 CLI 写下的会话记录,比如附件的字段形状。
CLI 一升级,记录格式就可能变。踩过的真坑:新版 CLI 省掉了几个可选字段,换窗时的核对失败,消息全被挡住。
升级 CLI 之前,先在隔离环境把换窗和审查各跑一遍。
09触发线和预算
换窗线 = min(140k, 上限 − 收尾预留 − 16384)
保留区只算对话、开窗承接和便签,约 3 万 token。图片按 宽 × 高 / 750 估算,上限 2576;以前一张图按 16000 算,结果总是提早换窗。
每多换一次窗,提示缓存就要冷启动重写一次,又慢又贵。所以只在真满的时候换,而且一次换到位。
10审查材料用完就从记录里剥掉
每轮审查交给模型的材料(证据、问题清单)在本轮结束后从会话记录里去掉,只保留最新一轮的召回包。
不剥的话,每轮多出 6–8k,窗口很快就满。剥离时会在上一条回复的末尾加缓存断点,缓存不会因此失效。
11失败的轮次只影响这一轮
用户中途按停止、审查后撞了封条、服务器重启时正在跑的轮次,都只把这一轮记为失败,会话本身不锁。换窗时,宿主会把能证明的失败片段排除在外。
早期一出错就锁整个会话,只能重建窗口,最近的对话也跟着丢了。现在要求每一种失败都要有「证明」:能证明是哪一段、为什么失败,才排除那一段。证明不了的,才停下来等人处理。
在交给模型之前就卡住的轮次,现在没有时限,会一直挂着,要人手取消。
运维上的硬规矩
- 用户正在聊天时不要重启 adapter。重启会把进行中的回复打断。发布脚本都会先等聊天空闲。
- 改审查,App hook 和官端 pending 两条路径一起改、一起测。只改一边,两边就会按两套规则审。
- 测试不要整库拷贝聊天库。用只读方式打开,或者只拷需要的几张表,用完就删。