让 NPC 拥有人格:我的第一次对话实验
我在研究游戏 NPC 对话时,一直想知道:如果给角色不同的性格设定,它们能不能在交谈中表现出区别?
为了观察这个问题,我做了第一篇论文的 NPC 对话实验。五位角色在游戏世界的酒馆里,围绕“你有喜欢的人吗”这个话题交流。没有玩家参与,程序让 NPC 轮流发言,把生成的内容继续传给后面的角色。
这次实验已经完成一百回,每回十五次发言,保存了一百份日志,共一千五百次由程序标记角色的模型输出。它是我的第一回实验;后续还有第二回实验,这篇先记录第一次的过程。
为什么从日常话题开始
“你有喜欢的人吗”是一个容易展开、也容许不同回应的话题。有人可以直接分享,有人可能谨慎地保持距离,有人关心朋友的感受,也有人先分析这件事。
这种场景给不同的性格留下了表达空间。我的重点是观察角色如何参与、如何接话,以及此前的发言会怎样影响后面的生成。
五名 NPC,各自带着不同设定
第一次最终实验使用了五名角色,提示词中的设定如下:
角色 | 性格描述 |
Aki | 外向、情感表达直接、乐观 |
Mika | 内向、谨慎、慢热 |
Yui | 温柔、共情能力强 |
Rina | 理性、独立、思考型 |
Kana | 害羞、不安 |
研究围绕 TIPI 所对应的人格框架展开,Demo 中也保留了数值人格和计分转换的探索。不过,这批一百回最终实验传给模型的是上表中的文字描述,不能把其他版本的五维参数直接写成这批实验的输入。
TIPI-J 是简短的人格量表,十个题项分别对应 Big Five 的五个维度。把相关框架用于生成角色,需要进一步检验生成行为,不能仅凭设定就认为人格已经准确表达。TIPI-J 原始论文
一百回实验是怎样跑的
最终脚本调用 DeepSeek 的
deepseek-chat,temperature 为 0.7。每回实验重新初始化酒馆场景,按 Aki、Mika、Yui、Rina、Kana 的顺序循环发言。每次调用之前,程序加入当前角色的名字、性格与话题要求;得到回复后,将它追加到共享对话历史,再让下一个角色继续。
初始化酒馆场景 ↓ 加入当前角色与性格要求 ↓ 调用 DeepSeek,生成回复 ↓ 追加回复到本回历史 ↓ 切换角色,直到完成十五次发言 ↓ 保存本回日志,开始下一回
这里的“十五次”指一回里五名 NPC 合计发言十五次,每人被程序调用三次。它不等于五个人各自发言十五轮。
最终版本保留本回此前的消息;每回结束后清空历史,重新开始。早期 Demo 里还有滑动窗口版本,但不能把它混写成最终脚本的配置。
日志让我看见了什么
第一回日志开头,Aki 兴奋地分享自己的好感对象,Mika 小声说自己欣赏吟游诗人的音乐,Yui 接着回应 Mika,Rina 则从时间和效率的角度谈恋爱,Kana 表达对铁匠铺学徒的好感与不安。
这几个开场提供了具体的观察材料:同一个话题下,角色的表达方式确实可以不同。
不过,继续读日志,会发现生成控制还有值得研究的地方。在第一回中,一次调用原本只指定一个 NPC,回复却可能续写多个人的动作和对话。文件中标在回复前面的名字,表示程序这次指定的角色,不保证正文始终只有它一个人在说话。
因此,“一千五百条输出”也不等于一千五百句严格独立、单角色的台词。要评价人格或统计行为,需要同时读输出内容,处理这种角色边界问题。
这是实际记录里很值得保留的一点:流畅的对话和可控的角色输出,需要分别检查。
跑完实验,还需要怎样读结果
保存日志,让每次生成有了可以回看的依据。但完成一百回,并不自动说明人格稳定,也不能据此推断不同模型谁更好。
这一批实验使用的是 DeepSeek。公开 GitHub 仓库里的多模型入口和避难所示例,属于另一套项目展示,不能替代第一篇论文的实际实验条件。
我更愿意从日志中挑出具体例子:角色怎样回应别人,是否沿着原本的性格表达,什么时候开始续写其他角色,以及后续话题怎样变化。对这些现象的解释,要和论文采用的方法及统计口径保持一致。
第一次实验给我留下的问题
这次实验把角色设定、模型调用、多轮历史和结果保存连接起来,也留下了一批真实对话材料。
接下来值得追问的是:性格描述怎样影响输出?一段回复“听起来像角色”,和整个互动过程保持角色特点,有什么区别?怎样限制模型只生成当前角色的回应?
第二回实验有自己的条件与材料,应该单独介绍。先把第一次说清楚,再比较两次研究的变化,才能让读者看见这个项目是怎样逐步推进的。