Versu: Agents and Utility AI¶
这是对交互式故事角色 AI 引擎 Versu 工作原理的简要介绍,主要是 代理/角色(Agents) 和 基于效用的决策系统(Utility-Based Decision-Making) 部分。
内容从小组讨论会的会议材料修改而来,材料被 LLM 润色过(修改了分段和措辞,为了“更快更方便阅读”),与以往的博客语气会不太一样。
Versu 没有公开过具体实现,我所有的分析均来自 Richard Evans 和 Emily Short 的论文以及 Emily Short 博客上的零散文章,可能有不少错误。
前言¶
Versu 是 Richard Evans(《模拟人生》AI 架构师)、Graham Nelson(Inform 语言设计者)和 Emily Short(交互式小说领域最具影响力的设计师之一)于 2013 年开发的社交模拟系统,用于作品《Blood & Laurels》。
Emily Short 的作品获得过交互式小说等领域的许多奖,总之是偷谱榜榜首。她还以顾问身份参与了 Failbetter Games 的 Storylet/QBN 架构(《Fallen London》《Sunless Sea》)。
这两套系统解决不同层面的问题:Storylet 处理内容选择,Versu 处理角色行为。两者可独立使用,也可结合。
本文就只专注于 Versu 的核心机制。
核心概念¶
展示概念需要一个示例故事,下面用了大家熟悉的《三顾茅庐》。由于我对剧情印象没有非常深刻,同时示例需要一些微小的改编,要是觉得和原著差别太大,就当“新新三国”来看吧。
设计目标¶
让角色 自主决策,而非按剧本行动。
传统做法:为每种情况编写反应
如果 张飞等待超过1小时 且 诸葛亮在睡觉:
张飞.发怒()
如果 刘备在场:
刘备.劝阻()
Versu 做法:定义角色的欲望和性格,行为从中涌现
张飞 = { 欲望: [快速解决问题, 服从大哥], 性格: 暴躁 }
刘备 = { 欲望: [请出诸葛亮, 安抚兄弟], 性格: 隐忍 }
世界状态:事实数据库¶
Versu 用 逻辑事实 表示世界状态。
zhang_fei.location!longzhong // 张飞在隆中
zhang_fei.emotional_state!irritated // 张飞烦躁
liu_bei.relationship.zhuge_liang.respect!high // 刘备敬重诸葛亮
zhuge_liang.status!sleeping // 诸葛亮在睡觉
! 表示排他性:设置 zhang_fei.location!garden 会自动移除 zhang_fei.location!longzhong。
角色模型¶
每个角色由以下属性构成(全部存储为事实):
| 属性 | 说明 | 示例 |
|---|---|---|
| Wants(欲望) | 想达成的目标 + 效用值 | 「请出诸葛亮」-> +40 |
| Traits(性格) | 稳定特质,影响欲望的效用值 | 暴躁、隐忍、谨慎 |
| Relationships(关系) | 对他人的多维评价 | 对诸葛亮:作为谋士 -20,作为学者 +10 |
| Emotional State(情绪) | 短期状态 | 烦躁、平静、愤怒 |
| Beliefs(信念) | 角色相信的事(可能为假) | 「诸葛亮在装睡」 |
情境与行动:Social Practice 和 Affordance¶
Social Practice(社会实践):角色所处的社交场景容器
- 提供行动选项的来源
- 多个 Practice 并发运行(拜访 + 等待 + 观察同时进行)
- 定义了什么行为在此情境下可用
Affordance(可用行动):Practice 提供给参与者的具体行为选项
- Practice「正式拜访」提供 affordances:
- 耐心等待
- 小声抱怨
- 发怒咆哮
- 告辞离开
- Practice「观察试探」提供 affordances:
- 继续装睡
- 醒来相见
- 让童子打发客人
效用计算(决策机制)¶
核心原则:一切归于 Want 检查。
性格、关系、社交压力 不是 独立评分系统,它们通过影响 Want 来参与决策。
| 概念 | 如何影响决策 |
|---|---|
| 性格 | 修饰 want 的效用值(如:「暴躁」性格让「发泄情绪」的 want 权重更高) |
| 关系 | 作为 want 的触发条件(如:只对喜欢的人才想「留下好印象」) |
| 社交规范 | 通过「不想违规」的 want 实现(行动后果标记违规 -> 触发惩罚) |
计算流程:
对于每个可用行动:
- 执行该行动的后果(真的修改数据库)
- 检查:哪些 want 被满足了?
- 累加被满足的 want 的效用值 -> 该行动的得分
- 撤销修改(恢复数据库)
选择得分最高的行动。
Versu 看的是真实后果,不是简化估计,避免了《模拟人生》中「角色反复尝试被占用的厕所」之类的问题。
案例:三顾茅庐¶
角色定义¶
刘备
| Want | 效用值 | 说明 |
|---|---|---|
| 请出诸葛亮 | +40 | 最重要的目标 |
| 维护仁义形象 | +30 | 不能失礼于贤者 |
| 安抚兄弟情绪 | +20 | 关心手足 |
| 遵守社交规范 | +25 | 礼贤下士的体现 |
| 性格特质 | 效果 |
|---|---|
| 隐忍 | 忍耐类行动效用 ×1.3 |
| 重情义 | 涉及兄弟的 want 效用 ×1.2 |
张飞
| Want | 效用值 | 说明 |
|---|---|---|
| 保护大哥尊严 | +35 | 不能让大哥受辱 |
| 快速解决问题 | +25 | 不喜欢拖延 |
| 服从大哥命令 | +30 | 听大哥的话 |
| 遵守社交规范 | +10 | 不太在乎 |
| 性格特质 | 效果 |
|---|---|
| 暴躁 | 「发泄情绪」类行动效用 ×1.4 |
| 忠诚 | 「服从大哥」的 want 效用 ×1.2 |
| 关系 | 评价 |
|---|---|
| 对诸葛亮 | 作为谋士:-20(不耐烦,摆什么架子) |
| 对刘备 | 作为兄长:+50(绝对忠诚) |
诸葛亮
| Want | 效用值 | 说明 |
|---|---|---|
| 试探来者是否明主 | +35 | 需要验证 |
| 不轻易出山 | +25 | 保持身价 |
| 展示才华 | +20 | 有机会就想表现 |
| 遵守社交规范 | +20 | 有分寸 |
| 性格特质 | 效果 |
|---|---|
| 谨慎 | 「观察等待」类行动效用 ×1.3 |
| 傲气 | 「不轻易出山」的 want 效用 ×1.2 |
场景设定¶
- 地点: 隆中草庐
- 时间: 第三次拜访
- 状态: 诸葛亮午睡(实际在暗中观察),刘备张飞已等待两个时辰
当前活跃的 Practices:
- 「正式拜访」(刘备、张飞参与)
- 「观察试探」(诸葛亮参与)
回合 1:张飞决策¶
情境:等待两个时辰,诸葛亮仍在「午睡」
可用 Affordances(来自「正式拜访」 Practice):
选项 A:发怒咆哮¶
行动后果(Postconditions):
add zhang_fei.venting_anger!true
add zhang_fei.voice_volume!loud
add norm_violated.respect_guest_etiquette.zhang_fei
add might_wake.zhuge_liang
Want 检查:
| Want | 是否满足 | 得分 |
|---|---|---|
| 保护大哥尊严(大哥被怠慢,要出头) | 满足 | +35 |
| 快速解决问题(能把人吵醒) | 满足 | +25 |
| 服从大哥命令(大哥说要等) | 违背 | 0 |
| 遵守社交规范 | 违背 | 0 |
性格修正:「暴躁」×1.4 应用于发泄情绪相关得分
总分:(35 + 25) × 1.4 = 84
选项 B:忍耐等待¶
行动后果:
add zhang_fei.waiting!true
add zhang_fei.emotional_state!suppressed
Want 检查:
| Want | 是否满足 | 得分 |
|---|---|---|
| 保护大哥尊严 | 无关 | 0 |
| 快速解决问题 | 违背 | 0 |
| 服从大哥命令 | 满足 | +30 |
| 遵守社交规范 | 满足 | +10 |
性格修正:「暴躁」对压抑类行动无加成
总分:30 + 10 = 40
选项 C:小声抱怨¶
行动后果:
add zhang_fei.mumbling!true
add zhang_fei.emotional_state!slightly_venting
Want 检查:
| Want | 是否满足 | 得分 |
|---|---|---|
| 保护大哥尊严 | 部分(表达不满但不激烈) | +15 |
| 快速解决问题 | 无关 | 0 |
| 服从大哥命令 | 部分违背 | +10 |
| 遵守社交规范 | 基本满足 | +10 |
总分:15 + 10 + 10 = 35
决策结果¶
| 选项 | 总分 |
|---|---|
| A. 发怒咆哮 | 84 |
| B. 忍耐等待 | 40 |
| C. 小声抱怨 | 35 |
张飞选择:发怒咆哮
“这村夫好大的架子!待俺去屋后放一把火,看他起是不起!”
回合 2:刘备决策(响应张飞咆哮)¶
情境:张飞爆发,可能破坏求贤大计
可用 Affordances:
选项 A:严厉呵斥¶
行动后果:
add liu_bei.reprimanding.zhang_fei!harshly
add zhang_fei.emotional_state!chastened
add norm_violated.brotherly_bond.liu_bei
| Want | 是否满足 | 得分 |
|---|---|---|
| 请出诸葛亮(控制局面) | 满足 | +40 |
| 维护仁义形象 | 满足 | +30 |
| 安抚兄弟情绪 | 违背(伤了张飞面子) | 0 |
| 遵守社交规范 | 违背(兄弟失和) | 0 |
性格修正:「重情义」×1.2 但此行动伤害兄弟关系,无加成
总分:40 + 30 = 70
选项 B:温和劝阻¶
行动后果:
add liu_bei.persuading.zhang_fei!gently
add zhang_fei.emotional_state!calming
| Want | 是否满足 | 得分 |
|---|---|---|
| 请出诸葛亮 | 满足(稳住局面) | +40 |
| 维护仁义形象 | 满足 | +30 |
| 安抚兄弟情绪 | 满足 | +20 |
| 遵守社交规范 | 满足 | +25 |
性格修正:「隐忍」×1.3 应用于温和处理,「重情义」×1.2 应用于安抚兄弟
总分:40 + 30 + (20 × 1.2) + 25 = 119
选项 C:放任不管¶
行动后果:
add liu_bei.ignoring.zhang_fei_outburst
add zhuge_liang.impression.liu_bei!negative
| Want | 是否满足 | 得分 |
|---|---|---|
| 请出诸葛亮 | 违背(印象变差) | 0 |
| 维护仁义形象 | 违背 | 0 |
| 安抚兄弟情绪 | 无关 | 0 |
| 遵守社交规范 | 违背 | 0 |
总分:0
决策结果¶
| 选项 | 总分 |
|---|---|
| A. 严厉呵斥 | 70 |
| B. 温和劝阻 | 119 |
| C. 放任不管 | 0 |
刘备选择:温和劝阻
“三弟不可无礼。孔明先生乃当世大贤,我等理当诚心等候。”
回合 3:张飞决策(响应刘备劝阻)¶
情境变化:刘备已开口劝阻
新增事实:
liu_bei.gave_direct_order.zhang_fei!calm_down
这改变了 want 检查的结果:
选项 A:继续发怒¶
| Want | 是否满足 | 得分 |
|---|---|---|
| 保护大哥尊严 | 大哥已表态,继续闹反而让大哥难堪 | 0 |
| 服从大哥命令 | 直接违背(大哥刚下令) | 0 |
| 遵守社交规范 | 违背 | 0 |
性格修正:「忠诚」×1.2 对违背大哥有惩罚效果
总分:接近 0,甚至为负
选项 B:不情愿地闭嘴¶
| Want | 是否满足 | 得分 |
|---|---|---|
| 服从大哥命令 | 满足 | +30 |
| 遵守社交规范 | 满足 | +10 |
性格修正:「忠诚」×1.2
总分:(30 × 1.2) + 10 = 46
决策结果¶
张飞选择:不情愿地闭嘴
张飞虽然不情愿,但还是退到一旁,脸色铁青。
回合 4:诸葛亮决策¶
情境:诸葛亮暗中观察到——
- 刘备等待两个时辰不失态
- 张飞爆发时刘备温和但坚定地控制住局面
- 三顾之诚已充分体现
可用 Affordances(来自「观察试探」Practice):
选项 A:继续装睡¶
行动后果:
add zhuge_liang.still_testing!true
| Want | 是否满足 | 得分 |
|---|---|---|
| 试探明主 | 已完成,继续无额外收益 | 0 |
| 不轻易出山 | 满足 | +25 |
| 展示才华 | 无法展示 | 0 |
| 遵守社交规范 | 继续装下去开始显得失礼 | +10 |
总分:25 + 10 = 35
选项 B:醒来相见¶
行动后果:
add zhuge_liang.meeting.liu_bei
add conversation_started!true
add opportunity_to_discuss_tianxia!true
| Want | 是否满足 | 得分 |
|---|---|---|
| 试探明主 | 已满足,可进入下一阶段 | +35 |
| 不轻易出山 | 三顾已足够体面 | +15 |
| 展示才华 | 可以开始谈天下大势 | +20 |
| 遵守社交规范 | 满足 | +20 |
性格修正:「谨慎」已满足(观察够了)
总分:35 + 15 + 20 + 20 = 90
选项 C:让童子再打发¶
行动后果:
add zhuge_liang.dismissing_again!true
add risk_losing_opportunity!true
| Want | 是否满足 | 得分 |
|---|---|---|
| 试探明主 | 已完成,继续无意义 | 0 |
| 不轻易出山 | 满足 | +25 |
| 展示才华 | 无法展示 | 0 |
| 遵守社交规范 | 四次拒绝过分了 | 0 |
总分:25
决策结果¶
| 选项 | 总分 |
|---|---|
| A. 继续装睡 | 35 |
| B. 醒来相见 | 90 |
| C. 让童子打发 | 25 |
诸葛亮选择:醒来相见
诸葛亮翻身而起:“有客来此,何不早报?”(早就报了,诸葛标志)
涌现¶
这段剧情中,以下行为是涌现的,没有显式编程:
| 涌现行为 | 来源 |
|---|---|
| 张飞先爆发 | 暴躁性格 + 低社交规范权重 |
| 刘备选温和而非严厉 | 重情义性格 + 安抚兄弟的 want |
| 张飞被刘备压住 | 忠诚性格 + 服从大哥的 want 在直接命令后激活 |
| 诸葛亮此刻出山 | 试探明主 want 已满足 + 继续拖延的收益递减 |
如果把张飞换成关羽(性格:沉稳、傲气),关羽可能根本不会爆发,诸葛亮需要等更久才能观察到“明主如何驾驭部下”。
变体:改变初始条件¶
假设出发前发生了以下事件:
| 改变 | 原值 | 新值 | 原因 |
|---|---|---|---|
| 张飞对诸葛亮的评价 | -20 | +10 | 路遇司马徽,闻“卧龙之才十倍于我” |
| 服从大哥的 want | +30 | +45 | 刘备出发前叮嘱“此行万万不可失礼” |
| 新增 want | 「不在二哥面前丢人」 +20 | 关羽也在场 |
回合 1 重算:张飞决策¶
选项 A:发怒咆哮¶
| Want | 是否满足 | 得分 |
|---|---|---|
| 保护大哥尊严 | 满足 | +35 |
| 快速解决问题 | 满足 | +25 |
| 服从大哥命令 | 违背 | 0 |
| 不在二哥面前丢人 | 违背(失态) | 0 |
| 遵守社交规范 | 违背 | 0 |
关系修正:对诸葛亮评价变正,减少攻击冲动
总分:\<= 60(比原来的 84 低很多)
选项 B:忍耐等待¶
| Want | 是否满足 | 得分 |
|---|---|---|
| 服从大哥命令 | 满足 | +45(提高了) |
| 不在二哥面前丢人 | 满足 | +20 |
| 遵守社交规范 | 满足 | +10 |
总分:45 + 20 + 10 = 75
决策结果¶
| 选项 | 原版得分 | 变体得分 |
|---|---|---|
| A. 发怒咆哮 | 84 | 50 |
| B. 忍耐等待 | 40 | 75 |
变体中张飞选择:忍耐等待
同一个角色,因为初始条件不同,做出完全相反的选择。
总结¶
| 传统状态机 | Versu Utility AI |
|---|---|
| 枚举所有情况 | 定义角色属性 |
| 添加新情况需要新代码 | 改变属性即可产生新行为 |
| 角色行为可预测 | 角色行为会涌现 |
| 复杂度随情况数爆炸,呈指数级增长 | 复杂度随角色数线性增长 |
类似将 Utility AI 应用于叙事对话的游戏还有:《矮人要塞》、《十字军之王 3》等。