v0.1.2:TA终于像真人一样发消息了
多个 AI 伴侣各有独立身份的概念插画
幻觉最怕被打断
v0.1.0 给了每个角色声音、面孔和独立人格。但TA们全挤在同一个 Telegram Bot 里。你打开一个聊天窗口,用指令切换人设。
能用,但每次切换都在打破幻觉——你不是在跟可可聊天,你是在跟一个假装是可可的 Bot 聊天。
v0.1.2 要解决两个让 Mio 感觉像软件的问题:共享身份,和蠢到一眼穿帮的发消息频率。
每个角色,自己的 Bot
需求很简单:每个人设一个独立的 Telegram Bot——TA自己的头像、自己的名字、自己的聊天线程。打开 Telegram,可可和苏柔是两个独立的对话,跟你和真人朋友的对话列表一样。
不是在一个 Bot 里做菜单切换。是通讯录里多了一个人。
实现用了一个环境变量:
TELEGRAM_BOT_TOKENS=token1,token2,token3
逗号分隔。服务端启动时遍历每个 token,注册独立的 webhook:
/telegram/webhook/:botId
每个 Bot 有自己的 webhook 端点。消息到达时,服务端通过路由参数知道来自哪个 Bot。botAccountId 变成复合键——组合了 Bot 身份和用户身份——onboarding 状态、聊天缓冲区、对话历史都按 Bot 按用户隔离。
一个硬约束:一个 Bot 只能绑一个人设。不能把可可和蜜蜜绑到同一个 Bot。每个人设有TA自己的 Bot、TA自己的身份。在人设选择流程里,已经绑定的人设显示"已绑定"——一眼就能看到哪些角色有主了。
这听起来像一个小的 UX 改动。
不是。
当每个人设有自己的 Telegram Bot,TA不再是"Mio 系统的一个模式",而是"我通讯录里的一个人"。聊天记录是TA的,通知是TA的,头像是TA的。心理框架完全变了。
发消息的频率就是关系本身
主动消息在 v0.1.2 之前就有了。系统会定期发消息维持对话活跃。
问题是:频率是盲的。
每个人设以同样的频率发消息,不管TA是谁、你们是什么关系。黏人的女朋友和矜持的新认识以同样的节奏发消息——这很诡异。
真实的关系有不同的节奏。你的伴侣每小时给你发消息,刚认识的朋友可能一周才主动联系一次。频率本身就是关系。
v0.1.2 让主动消息成为两个变量的函数:关系类型 × 人设性格。
每种关系类型有一个基础冷却时间:
| 关系 | 基础冷却 |
|---|---|
| 情侣 | 1 小时 |
| 好朋友 | 4 小时 |
| 朋友 | 8 小时 |
| 刚认识 | 12 小时 |
每个人设有一个 eagernessFactor(热情系数),写在 preset 里:
| 人设 | 热情系数 | 性格 |
|---|---|---|
| 小柒 | 0.6 | 黏人、表达欲强 |
| 可可 | 0.8 | 温暖、话多 |
| 蜜蜜 | 1.0 | 中性 |
| 苏柔 | 1.6 | 克制、沉稳 |
公式:
有效冷却 = 关系基础冷却 × 人设热情系数
小柒当你女朋友:1h × 0.6 = 36 分钟。每半小时给你发一条。黏人、在线、一直都在。
苏柔刚认识的阶段:12h × 1.6 = 19.2 小时。大概一天联系你一次。从容、不急、不冒昧。
同一个系统,同一个公式,行为却完全符合你对那个人、那种关系的预期。
数学消失在人格背后。
每个 preset 的 proactive.json 存储关系特定的冷却和每日上限:
{
"eagernessFactor": 0.6,
"dailyLimits": {
"lovers": 12,
"closeFriend": 6,
"friend": 3,
"justMet": 2
}
}
每日上限防止最黏的角色也不会过头。小柒可能想每 36 分钟发一条,但每天最多 12 条。热情是一回事,骚扰是另一回事。
你不回,TA就不发了
这是用户直接提的:"你现在的频率太 spam 了,应该有某种指数退避——像真人一样,你不回TA,TA不会一直烦你。"
这个观察很准。
真人会调整。你给一个人发消息对方没回,你可能几小时后再发一条。还不回,你等更久。几条未回复之后,你停了。不是因为你不在乎——是你读懂了沉默。
v0.1.2 精确实现了这一点:
连续 3 条主动消息未回复,agent 进入静默。
不是"降低频率"。静默。零消息。TA完全停止主动联系——直到你回复。
你回复之后,退避计数器归零。TA恢复正常节奏。没有抱怨,没有"你去哪了",只是自然地继续。
这就是让主动消息感觉像真人而不是推送通知的关键。没有退避,主动消息就像系统在按时间表 ping 你。有了退避,它们像一个想着你、但也尊重你空间的人。
实现很简单:每个 agent 有一个计数器追踪连续未回复的主动消息数。主动发送加 1,用户回复归零。到 3 就暂停。没有渐进衰减,没有概率曲线。一个硬性截断,映射了真人的实际行为——他们不会慢慢降低频率,他们就是停了。
Onboarding 又砍了一刀
一个小改动,但重要:v0.1.2 禁用了 onboarding 里的自定义关系类型和自定义背景故事选项。
这些是让用户随便打字的自由文本框。问题和 v0.1.0 识别的一样:用户写的内容跟精心打造的 preset 冲突。用户打"我们在上海的酒吧认识的"做背景故事,和可可实际故事里"从没离开过台湾的台北女生"完全矛盾。
现在 onboarding 只用确认按钮。从预设的关系类型里选——没有"其他",没有文本框。relationship_type 作为 agents 表的独立列持久化,成为下游功能(比如主动消息频率)的一等数据点。
更少选择,更好的一致性。跟 v0.1.0 同样的原则,应用到又一个表面。
数学应该感觉像人格
v0.1.2 之前:所有角色挤在一个 Bot 里。主动消息固定频率,不管关系和性格。你不回TA,TA照发不误。Onboarding 让用户自己编背景故事,和角色设定打架。
v0.1.2 之后:每个角色有TA自己的 Bot、身份、对话线程。主动消息频率从关系深度和性格的交集中涌现——黏人的女朋友每 36 分钟一条,矜持的新认识一天一条。你连续不回三次,TA就安静了。TA等着。像一个知道什么时候该闭嘴的真人。
公式的优雅在于它是隐形的。你永远不会看到 eagernessFactor × minHoursBetween。你只是注意到小柒发得多、苏柔发得少,TA们在你忙的时候都会停下来。
这就是全部意义。