插话插在哪
跑一条八秒的命令,第一秒就想换成另一条。排队要等到第八秒才生效,中止把整轮工作连着扔掉。两种做法都不顺手,因为系统只知道来了一条消息,不知道这句话是什么。
三个原语
agent 处理插话只有三个原语。follow-up 排到本轮结束,steer 作为下一步输入,abort 直接中止。区别只在时机,都不问这句话是什么。
补一句和叫停重做因此走同一条路。用户只好反复解释,系统也答不出三件事:这句属于哪一类,什么时候动执行,动作停在哪一层——这一步、这一轮,还是连后台任务一起。
两套会话
Posy 里有两个会话。一个听懂用户此刻要什么,一个把活干完,中间一份房间记录存配对关系和接待权。用户什么时候开口,接收者都是接待方;执行方忙不忙,只改变递话的时机。
代码守两条线。控制命令、中止范围、排队规则由代码定死;这句算补充还是追问,交给模型。旁问只读执行方的最近消息、正在跑的工具、输出尾巴和任务树,不产生提交,所以问进度不会变成派新活。
时机也只有一个答案。生成中途改不了,工具执行中改会坏数据一致性,工具轮边界是唯一安全的插入点。语义判定得放在边界外面,否则它会被执行一致性牵着走,最后只剩排队和中止两种选择。
六类话
| 用户说的 | 动作 | 约束 |
|---|---|---|
| 停 | 会话级中止,含后台任务 | 直连模式下说「停」只停当轮 |
| 急改 | 先 steer 入收件箱,再 abortTask 当前工具 | 顺序反了,更正会随中止一起被撤回 |
| 补充 | 在工具轮边界并入当前轮 | 不打断正在跑的工具 |
| 追问 | 接待方自己答 | 不向执行方提交 |
| 旁问 | 读状态后组织回答 | 只读,零副作用 |
| 委托 | 提交任务 | 多执行者时按名字定向 |
急改多一条保护:工具进度过 0.9 时只 steer、不中止,等它跑完再应用更正。剩下那点时间比重开一段还短,杀掉工具反而更贵。
急改快了六秒半
实验跑了 14 个端到端场景,每个 8 次,另加 6 个受控注入场景做对照,共 256 次真实模型运行。核心路径(停止、急改、补充、旁问、后台存活、座位切换)通过率 0.98。
明显的差距只出现在急改,也就是「别跑这个,改跑那个」这类话。
停止在两条件下没有差别(p > 0.5),它走会话级中止,不看工具进度。抢占优化的是纠正方向这一类话,不是所有插话。
补充的 5.9 秒约等于到下一个工具轮边界的剩余时长。补充本来就不该打断正在跑的工具,这个数字是设计的结果。
代价是多一次模型调用
| 指标 | 完整机制 | 仅排队 |
|---|---|---|
| 中位墙钟 | 14.07 s | 15.20 s |
| 中位 token | 17344 | 17505 |
| 接待方 token 占比 | 59% | 48% |
| 接待方首字 p50 | 893 ms | 838 ms |
| 最长沉默 | 7.54 s | 13.21 s |
接待方吃掉约六成 token,这是语义分级加旁读的开销。换回来两件事:停止 0.8 秒、旁问 1.6 秒就有回应;用户等执行的时候能随时问一句,最长沉默从 13.2 秒压到 7.5 秒。
更贵的模型救不了急改
分级质量用 120 条中文插话评测,六类各 20 条,专门收了否定(先别停)、条件(做完再改)、混合(停下改用 pnpm)这些边界说法。对照组是仓库里原有的正则分类器。
| 分级器 | 准确率 | 停止 | 急改 | 时延 |
|---|---|---|---|---|
| mercury-3 | 0.782 | 0.95 | 0.30 | 1.9 s |
| gpt-6-luna | 0.842 | 1.00 | 0.35 | 5.2 s |
| deepseek-flash | 0.824 | 0.95 | 0.42 | 3.4 s |
| 规则基线 | 0.883 | 0.60 | 0.90 | — |
模型和规则各强一头。三档模型在停止召回上 0.95 到 1.00,规则只有 0.60,正则会漏掉「先别继续了」这种否定。反过来规则急改 0.90,模型只有 0.30 到 0.42。
换更强的模型只把整体差距抹平。准确率从 0.782 升到 0.842,与规则的 McNemar 检验从 p = 0.058 变成 p = 0.458,分级时延从 1.9 秒涨到 5.2 秒。
急改召回是 0.30、0.42、0.35,最强的模型没拿到最好的急改。瓶颈不在算力,在提示词契约:判「要改」容易,判「作废当前步骤」难,模型会退到更保守的补充。
延迟和准确率也不单调。deepseek-flash 比 mercury-3 慢 1.5 秒,多拿 4 个点准确率和 12 个点急改召回。接待层要按交互预算选型,这一档最均衡。
时间线
一次急改的过程能导出成时间线,三条泳道分别是用户、接待、执行,上面叠着分级标记、读状态连线和中止标记。这份导出同时用作界面和实验标注。
没过的 39 次
256 次里 39 次没过,原因分四类,改法各不相同。
| 类别 | 次数 | 表现 |
|---|---|---|
| 场景驱动失败 | 13 | 执行方没在 30 秒内调用 shell 或子代理 |
| 分级等级偏移 | 11 | 急改判成补充,或该两级分流只做了一级 |
| 未转述任务 | 9 | 记账类补充被当成本可以直接口头确认 |
| 多执行者误停 | 2 | 停一方时另一方的同类工具被中止 |
| 其他 | 3 | 首次运行没收敛 |
场景驱动失败跟接待机制无关,是执行方没按指令调工具。分级偏移靠提示词和少样本示例能改。未转述暴露了一个语义空洞:用户的话不改变任务语义时,模型倾向口头确认而不转述,而系统把记账也算作补充。多执行者误停是唯一碰到正确性的缺陷,定向中止的作用域靠工具名和角色判断,两个执行者同时跑同类工具的时候有竞态。
0.9 保护在端到端里没起过作用。shell 只在起止两端上报进度,够不到 90%。这段逻辑有确定性的单元测试,三种情形都过了:到 0.9 时只 steer、不产生中止记录;没到 0.9 时立即抢占;关掉保护后即使到 0.9 也抢占。它依赖工具的进度粒度,粗粒度的工具用不上。
这套东西的边界
任务是合成仓库上的小规模改动加测试,规模远小于真实工程。只用了一对模型。没有人类被试,主观负担和信任度不下因果结论。分级语料我自己标的,报准确率时附了混淆矩阵,不宣称与独立标注者一致。
它证明的是机制成立、代价可量化,不证明体验更好。
结论
工具轮边界是插话唯一安全的插入点,意图判定放在边界之外。
这条判据与框架无关。把理解用户和保证一致混在一起,只能退回排队、插队、中止三个粗糙原语;拆开之后,一边量分级准确率,一边量生效时延和被丢弃的工作量。