教 LLM 什么时候该闭嘴
AI学会适时沉默的概念插画
问题出在哪
LLM 被训练成"有帮助"的。而"有帮助"在训练数据里基本等于"详细"。
你发"嗯",真人朋友回"干嘛"——两个字。LLM 呢?回你一整段:先问你今天怎么样,再分享 TA 自己在做什么,最后来个走心提问收尾。
做客服助手,没问题。做伴侣?不行。
我拉了数据。Mio 5 个人设在控制前的回复/输入长度比:realistic 模式下平均 5.02x——回复是用户输入的 5 倍长。短消息场景(用户只发一个字)比率飙到 6.60x。
这不是对话。这是独白。
走过的弯路
第一反应是暴力截断。设 max_tokens 上限,硬砍输出长度。
问题立刻暴露:截在句子中间比话多更糟。"我在想你昨天说的那——",这种断尾巴的回复比长文还让人难受。用户会以为 App 出 bug 了。
第二次尝试是纯提示词控制。系统提示里写死"回复要简短,不超过 X 个字"。有点用,但极不稳定。LLM 把长度指令当建议,不当硬约束。话多的人设(小柒,大学生小奶狗性格)照样写小作文。安静的人设(苏柔,文艺编辑)本来就简短,提示词是多余的。
两条路都是死胡同。
想明白了:这不是一个问题,是一个矩阵
退一步看,回复长度不应该是一个固定值。它应该在三个维度上变化:
- 模式:realistic(短信风格,模拟真人节奏)vs companion(更表达性,允许更长回复)
- 关系亲密度:distant(刚认识)→ neutral(普通朋友)→ close(情侣)。参考 v0.1.4 的关系演化系统
- 人设话多程度:quiet(苏柔、陈哥)vs neutral(可可、蜜蜜)vs chatty(小柒)
一个安静人设、刚认识的关系、回复短消息——应该是 2 到 4 个字。一个话多人设、情侣关系、聊深度话题——可以到 12 到 18 个字。
不能用同一把尺子量。
方案:两层混合系统
想清楚维度之后,方案分两层。
第一层:提示词级别的每轮长度合约
每次生成时,动态注入系统提示,指定三个参数:
- 字符上限(根据模式 + 关系 + 人设话多程度计算)
- 气泡数上限(companion 模式允许多气泡模拟连续发消息,realistic 通常只有 1 个)
- 通用原则:简短、温暖、留空间给用户回复
几个 realistic 模式下的预算例子:
| 场景 | 字符上限 | 气泡数 |
|---|---|---|
| distant + 短消息 | 4 字 | 1 |
| neutral + 日常聊天 | 8 字 | 1 |
| close + 深度话题 | 84 字 | 3 |
话多人设(小柒)在以上基础加 15% 到 40%。安静人设(苏柔)减 10%。
第二层:确定性后处理裁剪器
关键设计决策:不调第二次 LLM。
写了一个纯代码函数 normalizeAssistantReplyLength(),做确定性裁剪:
- 按句子边界切分(中英文标点检测,支持句号、问号、感叹号、省略号)
- 裁剪到字符预算和气泡预算内
- 保留完整句子——绝不切半句话
- 在持久化和发送之前执行,数据库里存的和用户看到的是同一份文本
为什么不用第二次 LLM 来"帮我缩短这段话"?
成本和延迟。每条消息已经有一笔 LLM 调用开销,加一轮缩写成本直接翻倍,延迟多 500ms 以上。聊天 App 里响应速度就是体验。用户发完消息等 2 秒和等 3 秒,感受完全不同。
确定性函数零成本、零延迟、行为完全可预测。代价是它不理解语义——只会按句子切,不会"智能缩写"。但实测下来,切掉多余的句子比试图压缩每句话效果更好。LLM 生成的回复通常前两句是核心,后面是展开和补充。砍掉后半段,留下的反而更像真人。
矫枉过正了
第一轮调参把 realistic + distant 的回复压得太狠。
用户问"在干嘛",LLM 回"嗯。"
技术上确实短。实际上是废话——根本没回答问题。
修复方案:加了一个活动类问题检测的确定性守卫。检查用户是不是在问"你在做什么"、"在忙吗"这类需要实际内容的问题。如果是,设回复下限——必须实际回答。
"在忙。"——又短又回答了问题。合格。
"嗯。"——短但没回答。不合格。
这个守卫很简单,几行正则匹配。但它避免了"为了短而短"的陷阱。
简短是手段,不是目的。目的是像真人。
最终平衡:短且温暖
调了几轮之后,最核心的体会是:简短和温暖不是对立的。
真人简短,但不冷漠。区别在语气和上下文意识。
拿"嗯"这个最短的输入举例。可可人设,realistic 模式:
- distant(刚认识):"嗯。"——2 字。正确:陌生人之间的礼貌回应,不热情也不冷淡。
- neutral(普通朋友):"幹嘛啦。"——4 字。正确:朋友间的随意反问,带一点好奇。
- close(情侣):"幹嘛,句點我喔?"——8 字。正确:情侣间的撒娇吐槽,短但有情绪。
同一个字的输入,三个完全不同的能量。字数在变,但每个长度都是对的。
这才是目标——不是统一压短,是让每个长度都恰到好处。
数据
上线两层系统后,跑了一轮完整的 A/B 测试。所有数字都是回复/输入长度比:
| 场景 | 控制前 | 控制后 | 变化 |
|---|---|---|---|
| 总体 realistic | 5.02 | 2.78 | -45% |
| 短消息 realistic | 6.60 | 5.00 | -24% |
| 日常聊天 realistic | 1.95 | 0.70 | -64% |
| 深度话题 realistic | 6.49 | 2.63 | -59% |
| Distant 平均 | 3.83 | 1.83 | -52% |
| Neutral 平均 | 3.97 | 2.28 | -43% |
短消息场景改善最小(-24%),因为用户只发了 1 到 2 个字,回复再短也得有内容。日常聊天改善最大(-64%),因为控制前 LLM 在这类场景最爱展开——"你今天吃了什么?我今天......",现在被裁剪器干净利落砍掉了后半段。
Distant 关系比率从 3.83 降到 1.83,接近真人水平。刚认识的人之间,回复和输入差不多长,甚至更短。对了。
回头看
话痨问题在 AI 伴侣领域被严重低估了。
大部分产品优化的是 engagement——回复越长,用户停留越久,指标越好看。但真实关系里有沉默。
真人不会把脑子里想的全部倒出来。你和亲密的人待在一起,很多时候什么都不说,那个沉默本身就是舒适的。
最难的不是让 LLM 变短。变短很容易,砍 token 就行。
最难的是让 TA 短得恰到好处——让简短读起来像舒适的沉默,而不是冷漠的敷衍。
这需要理解上下文、关系状态、人设性格,然后在这些维度的交叉点上找到那个精确的长度。
不是一个数字。是一个矩阵。
更多关于 Mio 的设计哲学,见 Mio 宣言。