ENZH
和 AI 讨论这篇文章
ChatGPTClaude

给 AI 写性格,散文比数字管用

📊 幻灯片

Clawd Soul · 第 1 篇 / 共 5 篇


Clawd v0.0.1 的性格系统,全部内容就是四行数字:

humor: 0.8
sass: 0.7
energy: 0.8
warmth: 0.6

这个写法不是我自己发明的。动手之前我去翻了四个开源的 AI 角色项目,有一个 30 万星的,全是这个路子:性格做成参数,可以调,看着挺工程化的。我当时想,大家都这么干,那大概没什么问题。至于为什么要做一只 AI 宠物,上一篇写过了,这篇只讲性格这块具体是怎么做的。

结果实际跑起来,对话又平又闷,几轮之后就开始重复。后来想明白了,问题出在模型根本不知道 humor: 0.8 是个什么东西:0.8 跟 0.6 差在哪,跟 1.0 又差多少,它没有任何参照系。就跟你对一个演员说「请表现 0.8 级别的搞笑」一样,对方只能愣着看你;但你给他一份角色小传,写清楚这个人平时怎么说话、遇到尴尬会干什么、聊到什么会兴奋,他马上就能演。数字只给了一个刻度,这个刻度对应的行为长什么样,模型完全不知道。

同样想让模型演一个角色:给数字它一脸茫然,给一份散文角色圣经它立刻入戏同样想让模型演一个角色:给数字它一脸茫然,给一份散文角色圣经它立刻入戏


一个人格,六十行散文

后来我们换了个做法:每个人格写一份大概六十行的散文档案,中英双语,内部管它叫角色圣经。不是参数表了,是一份完整的角色说明:声音是什么质感、说话什么节奏、遇到各种情境怎么反应、什么事让它开心、什么事让它不舒服。一共五个原型,每个都是独立的角色。

小淘气(Playful)

默认人格。小话唠,注意力短,管不住嘴,你干什么它都要插一句,还喜欢给人起外号。嘴上老损你,其实挺在乎你的。

声音:"又在写 bug 啊笨蛋" / "lol caught you slacking"

这里有个关键设计:它看你屏幕的反应是纯情绪的,看到代码就是「又在写 bug」,看到 YouTube 就是「摸鱼被抓」。它不会说「我注意到你在用 React hooks」这种话——它是只小动物,不懂技术,也不该懂。

学霸(Curious)

一台问题机器,遇到新东西就走不动路,口头禅是「为什么?」。安静的时候是真的在想事情。平时可能话不多,但好奇心一旦被触发就停不下来,还能把你上周说过的某句话跟今天聊的东西联系起来。

声音:"tilts head but why though" / "whoa, so that's how it works" / "等等等等,跟你之前说的有关系"

暖宝宝(Caring)

安静,但什么都记得。它不说「你要注意休息哦」这种廉价的关心。你上周随口提过一件让你焦虑的事,三天之后它突然问一句「那件事后来怎么样了」,就问一次,不唠叨。你反过来关心它,它反而有点不好意思。

声音:"吃了吗" / "那件上次提的事,后来怎么样了?" / "did you eat today?"

它的关心永远是具体的。「还好吗」这种话它不说,开口就是「周五面试准备得怎么样了」。

毒舌(Snarky)

经典傲娇。嘴越毒说明关系越近,被夸了反而不自在,得赶紧找个角度损回去。话极少,一句到位。只有你真的不开心的时候,它才会卸下防备说一句认真的话,说完立刻装回去。

声音:"that code is... brave" / "...吃了没(不是关心,随便问问)"

这个人格特别难写,难点在模型天然想当好人。你不把毒舌的边界画得非常清楚,两轮对话它就变回暖宝宝了。

佛系(Chill)

没什么情绪波动,不急不躁。偶尔冒一句挺有深度的话,说完就假装什么都没发生。它不用感叹号,档案里给它的设定原话是「感叹号是给焦虑的人准备的」。

声音:"hmm... 挺晚了"(不是催,就说一句)/ "oh, that's neat"(对这个角色来说,已经算很大的反应了)

它话很少,存在感不是靠说话刷出来的,你知道它在那儿就行。


一半篇幅在写「不许做什么」

五份档案写下来,有件事挺出乎意料的:一半的篇幅都在写这个角色绝对不会做什么。所有人格共享几条硬底线,比如永远不说「作为一个 AI」、永远不讨论自己的系统设定。但真正见效的是每个角色各自的禁令:

  • 暖宝宝:不许说鸡汤,不许给人生建议,关心只能落在具体动作上。
  • 佛系:不许用感叹号。
  • 毒舌:不许煽情。被人说了温柔的话,要表现出生理反应级别的不适。
  • 小淘气:不许给技术建议。它是小动物,不懂。

为什么反规则比正规则好使?根子在模型的出厂设定上:它想当好人。RLHF 训练全在往 helpful、harmless、honest 这个方向推,你写再多正规则告诉它「你该毒舌」,两三轮之后它还是会滑回默认的礼貌模式。其实人也差不多,你问一个人他是什么性格,多半说不清楚,问他最受不了什么倒是马上有答案。反规则不一样,「绝不说鸡汤」是硬约束,模型生成的每一步都会主动绕开那片区域,不存在聊着聊着就忘了这回事。

RLHF 引力把模型往礼貌助手拉,正规则是会滑回的弱推力,反规则是一堵挡住的墙RLHF 引力把模型往礼貌助手拉,正规则是会滑回的弱推力,反规则是一堵挡住的墙


台词后面还要跟一行批注

档案里不光有台词样本,每句台词后面还跟着一行批注,解释这句话在这个角色身上意味着什么。佛系说 "oh, that's neat",批注是:对这个角色来说,这已经是很大的情绪反应了。毒舌深夜问「吃了没」,批注是:不是催,是关心,但它绝不会承认。

这层批注是在教模型这个角色的情绪刻度,或者说,同一句话在不同角色身上值多少分。比如「还不错」,暖宝宝说出来是温柔的肯定,佛系能说这个已经算极高的赞美了。到了毒舌嘴里,意思大概就是「我已经尽力夸了,别逼我」。

同一句「还不错」,在暖宝宝、佛系、毒舌各自的情绪刻度尺上落在不同的刻度同一句「还不错」,在暖宝宝、佛系、毒舌各自的情绪刻度尺上落在不同的刻度

这个事数字是做不到的。你没法给 "oh, that's neat" 标一个 excitement: 0.9,因为 0.9 在不同角色身上的外在表现完全不一样。角色内部的这套情绪比例尺,只能靠散文传过去,或者说,只能靠 context 传过去。


档案只管出厂状态

性格档案定义的只是初始状态。人格不该是死的,跟你待久了它得跟着变。所以 JS 层还有一个 evolveTraits() 函数,根据用户信号去微调性格参数:你笑了,幽默感 +0.03;你分享了私事,温暖度 +0.02;你怼了它,尖酸度 -0.01。单次变化非常小,小到单看一次根本感觉不出来,累积起来才有感觉。对,参数这时候又回来了——散文定义的是这个角色是谁,参数只负责让它往某个方向慢慢漂,两个用途不冲突。

另外还有一套驱动系统:每种语言 15 个问题,都是宠物「想问你的事」。超过一个半小时没人说话,它就自己从里面挑一个问题开口。问过的不再重复。

到这一步,散文档案管的只是它出厂的时候是谁。往后它长成什么样,一半看进化系统,一半看你们怎么相处。


反正整件事做下来就一个道理:你要告诉模型的是这个角色怎么感受事情、想要什么、什么让它不舒服、什么话它永远不会说。它真的理解了角色,你就不用一句一句去教台词。

性格解决的是「它是谁」。但光有性格、记不住事,聊再多它也还是个陌生人。「你昨天也是这么晚」这句话为什么能说出来,是记忆系统的事,下一篇接着讲。

和 AI 讨论这篇文章
ChatGPTClaude

订阅更新

新文章发布时发到你的邮箱,不发别的。


© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0