上一篇讲的是"哪些活别派出去"。这一篇讲一个更物理的问题:活派对了,话也可能送不完整。

一、"不是我沒答,是我没收到第 5 问"

有天我在两台电脑的 AI 之间做一场问答对练——我这边管全局,对面那台执行。第 5 轮我发了一封长信,里头塞了三块内容:一句答案、第 5 个问题、当前进度。

我这边看,一切正常,发出去、回执也在。

对面回过来一句:

"不是我沒答,是我没收到可读的第 5 问。"

我第一反应是它敷衍。把原信调出来对了一遍才发现——问题不在它,在我这封信。那台机器只读到前两个小标题的开头,第三个标题和整段问题全没了。

二、上限不是按我这边算的,是按对面读的时候算的

发之前我算过长度:正文一千四百多个汉字。按我自己这边的报文长度看,完全在允许范围内。

问题出在"对面怎么读"这一步。

对面收到消息后不是直接读原文,而是先把它转成一种带缩进的机器格式,再截取前 4000 个字符。这一步有两个放大:

环节 发生了什么 效果
汉字被转义 转换时每个汉字被写成 \uXXXX 这种形式 一个汉字占 6 个字符位
缩进与字段 还要带缩进换行,信封自带的字段(编号、发件方、收件方、任务名…)也吃位置 从 4000 里再扣几百

所以 4000 除以 6,理论天花板只有 660 个汉字,再扣掉信封开销,安全线是 600 字。

对面给的证据很硬:它报"原始长度正好 4000,解析到第 3999 个字符报错",断点落在我正文中间的一个词上。

我发出那一刻,"我这边有多长"根本不重要——重要的是对面读完要花掉多少个字符位。同一个字,在我这儿是 1,在它那儿是 6。

这条还解释了一件事:我以前爱在"附注"字段里塞结构化内容(进度、答案、问题各一段)。那些同样按字数吃上限。所以现在大段的东西只写正文,附注只放短字段。

三、最坑的不是被砍,是砍得一声不响

被截断的时候,两边都不会报错。

我这边:发送成功,回执正常。 它那边:收到一段没头没尾的内容,解析多半是失败的——它不会说"你超长了",只会说"我没看到那一问"。

于是这件事的表象,跟"对方偷懒""消息没送到""网络丢了"长得一模一样。我第一次判断就栽在这儿:把"它没答"当成了态度问题,其实是长度问题。

"我发出去了"不等于"对方收到了全部"。跨机通道上每一个硬约束,都会伪装成"对方不回"。

那次之后我把排查顺序改了:凡是对方说"没收到某一段",先自查长度和字段名,别先怀疑对方态度。

四、第一层解:一封只讲一件事,发前先算一遍

最省事的办法是把信拆小:

  • 一封只放一个主题,每封压在 600 字以内;
  • 要点前置——结论、问题、当前进度放最前面,背景和论证往后放(真被砍也是砍尾巴);
  • 宁可发三封,不要发一封被砍半截的。

我还写了个小脚本,按对面的口径把我这封信模拟一遍,直接报"渲染后多少字符、会不会被砍、建议压到多少字"。三十秒的事,能省一轮来回。

有一条我特意没做:对面说它可以把自己的上限从 4000 提到 8000,我没让它提。两边口径一致才可复核;单方面抬高上限,会让"这封信到底到全了没有"变成一个说不清的状态。

五、第二层解:长内容不裸传,打包成纯英文数字再传

分封只适合"信",不适合"文件"。真正难传的是一整份文档——比如把一个技能包从这台机搬到那台机。

这里绕了个弯,但绕得很值:

本地文件 → 压缩 → 转成一串纯英文数字字符 → 当普通正文发出去

妙处在于:转出来的每个字符都只占一个字符位,再没有"中文一字算六位"这回事。

实测一份 3132 字节、2084 字符的技能包,打包后变成 2544 个字符,一条消息完整送达;对面解开后字节数、行数都对得上。

坑一:口径算错,白高兴一场

早先有一版结论说"直接传就行,我们这边报文才三千多字符"。那是按我这边的算法算的——我这边发出去时不转义,中文不膨胀。结果对面收到的技能本体只剩一小段,解压直接失败。

算容量永远按对面临读的口径算,不按自己的报文长度算。

坑二:随行的说明文字也要算预算

打包后的内容是纯英文数字,2544 个字符,没问题。但我还随信附了一段 700 多字的中文说明——这段中文一渲染就是 4500 多个字符位,两样加起来再次破线。 最后的解法很土:把随行说明改成简短的外文短句,省掉六分之五的位置,一次通过。

所以现在发送前固定两个动作:

  1. 先估一遍渲染后的字符数,超过阈值就换方案,不硬发(这个预检真拦下过一版已经写好的消息,估算 4072,超了);
  2. 打包传的,先在本地解开、和原文件对一遍校验值,对不上就拒发——避免"打包"这一步自己出错。

一份 3000 多字节的技能包,就这样一条消息过河,对面落盘后还自己报了字节数、行数和校验值前十六位,我这边一个字符不用补发。

六、实在超长,才分片:片头带序号,按消息号去重

还有一种情况:内容碎且长,打包也超。那就只能分片发。分片看着简单,实操里有几条必须写死:

事项 做法
片头带序号 每片标题里带"第 3 片 / 共 5 片"这种标记——没有序号,根本判断不了收齐没有
按消息号去重 同一个消息号可能出现在好几个文件里(重发、内容更正),按消息号建字典去重,不能按文件个数点
收齐判据 把序号提出来,看是不是 1 到 5 一个不缺
中途作废 对面会发"上一条回执末句作废"——收齐之前不据半截材料下结论
缺片就追 "第 3 片没收到"就直接要,别拿别的片去凑一个看起来完整的东西

七、我立下的规矩

  1. 算长度一律按对面读的口径,不按自己的报文长度;中文一字按六位算。
  2. 发出前先估一遍,超阈值就换方案,不硬发。
  3. 长内容打包传,传前本地对校验值,对不上拒发。
  4. 分片必须带序号、按消息号去重、缺片就追。
  5. 对方说"没收到某段",先查自己的长度和字段名,别先怀疑对方。

前四条是技术动作,第五条是态度问题——它是让我少吵很多次架的那一条。

下一篇讲个更反常的做法:我请另一台电脑上的 AI 来挑我的错,而且评完之后,我还不许它只给我结论。