拿真实聊天记录校准角色多久回消息,第一版把一年多的数据混在一起算,结论正好反了。修好口径之后,又发现系统缺了中间一整档。
Autarkia 的角色在 QQ 和 App 上回消息。早期的规则很简单:除了睡觉和忙碌时延后处理,其余每条消息都立刻回。功能上没问题,体感上像一个客服,永远秒回、每条都接。
于是加了「已读不回」:低信息量的消息(应答、收尾、单个表情)可以直接略过;轻分享类的进一个回头补回的队列,过一阵再回;问句、求助和长消息必须回。第一版参数是拍的:略过 0.45,补回 0.2,补回延迟 10 到 90 分钟。
01第一次校准
拍的参数要对齐真实节奏。我拿了一份时间跨度一年多的真实聊天记录,只用时间戳和消息类型,不看内容,按「对方连发的一组消息 → 之后第一条回复」统计间隔。结果是中位 8 秒,超过 10 分钟才回的只有 3.5%。结论很明确:秒回为主,已读不回是少数情况。参数随之下调:略过 0.15,补回 0.10。
这个结论是错的。一年多的记录被当成了一个样本,而节奏是会变的。按月份分段重算:最早那个月中位 5 秒、超过 10 分钟才回 0.7%;三个月后中位 16 秒、10.5%;到最近一个月,中位 21 秒,问句发出去一分钟内没动静的占 40%。「中位 8 秒」描述的是最早那段时间,它的数据量把后面拉平了。
现在的规矩是先分段,再决定哪一段代表「现在」,然后只用那一段。行为参数尤其要这样,一个人的回复习惯一年里能变很多。
还有一个量根本观测不到:「始终没回」。没回就没有消息,记录里不会留下任何东西。我只能拿「很久才回」的比例当它的上限,保守取值。回头补回的延迟上限放到 12 小时,按对数均匀分布采样,短端密,长尾稀;采样出来 10 到 30 分钟占 26%、30 到 60 分钟 16%、1 到 3 小时 26%、3 到 12 小时 32%,实测是 34%、19%、19%、28%。
02缺了中间一档
口径修好之后,体感还是不对:要么秒回,要么半天不理。把最近一个月的分布拆成三段就看出来了。真实节奏是 1 分钟内回 55%,1 到 10 分钟回 35%,10 分钟以上或者第二天回 9.5%。系统只有两档:立刻回,或者进补回队列,而补回最早也要 10 分钟。中间那 35%,「人不在手机边,几分钟后才看到」,完全没有。
补上的这一档叫空闲短延迟:角色空闲时,按 0.35 的概率等 60 到 180 秒再回。等待期间对方再发的消息并进同一批,只回一次,这和真实记录里「对方平均连发 2.7 条、只收到 1.7 条回复」的节奏一致。
用最近一个月的 1535 条真实消息跑 200 次蒙特卡洛:改之前是立刻回 90.9%、1 到 10 分钟 0%、10 分钟以上 5.3%、不回 3.8%;改之后是 59.1%、31.9%、5.2%、3.8%;真实是 55.1%、35.4%、9.5%、0%。
03几个刻意的取舍
- 短延迟上限压在 180 秒。再长,客户端那边看起来就像掉线了;10 分钟以上的长尾交给补回队列。
- 「到点了还是不想回」的概率默认是 0。它调到 0.2、0.3、0.5,「始终没回」会升到 4.9%、5.4%、6.5%,离真实的 0 更远。
- 原来「到点不想回」是交给模型输出一个跳过标记来决定的,24 次采样一次都没触发。模型几乎不会主动选择沉默,这件事得放在系统层执行。
- 延迟之后给模型的提示只写状态事实,比如「人不在手机边」,不写「刚看到」「刚在忙」这种借口,不然它每次都会先解释一遍。
没对上的部分也还在:10 分钟以上那档模拟是 5.2%,真实是 9.5%;「始终没回」模拟是 3.8%,真实是 0。后者来自那个观测不到的量,我目前没有更好的办法去校准它。