从角色卡到扮演层,一次关于 LLM RP 为什么总像在演的研究#
在我的上一篇关于 LLM RP 提示词的文章中,我主要从几个维度讨论了角色的基本人设,以及角色进入真实聊天环境后会遇到的一些拟人化边界.
当时的基本观点其实很明确.提示词不是越长越好,人格也不能只写成”可爱”、“温柔”、“傲娇”这种抽象标签.角色为什么会这样说话,她在关系里在意什么,遇到冲突时会保护什么,哪些事情会让她嘴硬,哪些事情又会真正触动她,这些底层因果比堆叠形容词重要得多.
我也将角色提示词拆成了身份、人设、表达、互动边界、场景、工具、回复格式和上下文边界等板块,并提出要在真实环境里控制变量进行多轮测试.如果模型表现不对,需要继续判断究竟是描述有歧义,规则互相冲突,模型自身能力不足,还是运行平台根本没有提供相应的能力.
换句话说,我当时已经提出了一种很重要的基本思维:
- 提示词质量层面的问题.
- 模型性能层面的问题.
- 运行框架层面的问题.
这三层必须分开看.
整篇文章在逻辑上是成立的,各个板块的定位也很清楚.它能够帮助我们把一个角色定义得更稳定,减少明显的人设冲突和工具出戏,也能给后续测试提供一套比较完整的修改流程.
但真正拿到私聊环境中反复测试后,我发现问题并没有结束.
人设写清楚了,为什么还是不像真人#
我们通常编写 LLM RP 提示词时,最直接的做法就是告诉模型:
你要扮演 XXX.
你就是 XXX,不是 AI 助手.
你要始终按照下面的人设和用户交流.
这种写法当然不是完全无效.它可以让模型知道自己的身份,模仿角色口吻,遵守一些显式边界,也能在明显的角色问题上表现得更稳定.
可它仍然很容易产生一种说不清楚的”表演感”.
尤其是在日常一对一私聊中,这种感觉会非常明显.模型不像一个正在和你聊天的人,更像一个正在替这个角色写台词的人.它会把每轮消息写得很完整,努力保持口吻,努力承接上下文,努力表现亲近,努力给出有意义的回应.如果气氛比较暧昧,它会主动补关怀.如果你发了一张梗图,它会先证明自己看懂了.如果你说今天有点累,它会立刻完成一整套安慰流程.
这类回复单独拿出来看通常没有明显错误.措辞通顺,态度友好,甚至每一句都符合角色卡里的某条要求.但它们连在一起以后,就越来越不像私聊,反而像文案、台词或一段需要不断推进的剧情.
可真实私聊并不总是在推进什么.
有时候一句”?”就是完整回应.有时候是”何意味”、“神了”、“额”、“确实”.有时候只发一张表情包,它既不是新的事件,也没有要求对方解读,更没有承担推进关系和交换信息的任务.它可能只是一个逗号,一个语气,或者单纯觉得这张图现在发出来很好玩.
模型却很难停在这里.
无论怎样修改提示词,它都像是觉得自己必须把这一轮”完成”.这件事让我非常烦恼.我开始怀疑,问题可能已经不只是角色人设写得够不够清楚,而是传统的”单模型 + 角色提示词”结构本身就在把模型推向一种错误的工作姿态.
我偶然看到了 HDSI#
后来我无意间刷到了 HDS Interlude,也就是 HDSI 的演示.
真正吸引我的并不是它写了多复杂的世界观,而是里面的角色发送消息时非常像一个真实的人.她可能只回应其中一个细节,可能突然反问,可能拒绝接着说,也可能只发一个问号.她不急着证明自己完全理解了用户,不急着把情绪照顾完整,也不急着让每轮对话都产生一个漂亮的闭环.
那种自然感并不等于短,也不等于冷淡.它更像是角色真的站在自己的位置上,只做了这一刻想做的互动.
于是我开始研究 HDSI,想知道这种区别究竟来自哪里.
深入看下去后,我发现 HDSI 并不是传统意义上的”给一个模型塞一张更强的角色卡”.
它本身是一个独立的多层运行框架.用户看来只是一轮普通聊天,内部却可能涉及消息合并与中断处理、当前事件与真实时间锚定、场景状态、关系状态、记忆、意图、动作和投递.主叙事模型负责理解已经发生的时间和当前事件,再决定角色此刻做什么,是否回复,是否延迟,以及哪些内容最终对用户可见.
更重要的是,它内部并不只有一层,一轮互动也不必永远只依赖一次模型调用.视觉理解、记忆压缩、情绪偏移和日程审查等职责,可以在需要时交给独立的侧端模型.宿主则负责持久化状态、管理意图、调度动作、处理中断,并确认消息是否真的完成了投递.
从它公开展示的设计来看,HDSI 的自然感不应只归因于某一张提示词.我更倾向于把它理解为多层状态、主模型、按需侧端模型与宿主调度共同形成的框架效果.
这也意味着,主模型不需要在一条可见回复里同时证明下面这些事情:
- 我理解了用户的全部意思.
- 我记住了长期关系和历史事实.
- 我正确解读了图片和表情包.
- 我知道当前时间和角色正在做什么.
- 我已经安排了未来行动.
- 我完成了安慰、建议和情绪照顾.
- 我成功把消息发送给了用户.
这些职责被拆开以后,复杂处理可以留在系统内部.用户最终看到的,只是角色经过选择后真正发出来的那一点内容.
还有一个很关键的区别是,HDSI 的主模型并不只是被粗暴地要求”你就是这个角色”.从其整体设计来看,模型更接近站在一个受约束的叙事视角中,先理解角色、环境、时间和当前事件,再决定角色的可见行为.角色内部发生了什么,角色想过什么,角色最终说了什么,并不是同一种东西.
这恰好解释了我在传统角色卡里一直碰到的问题.我们往往让同一个模型在同一层里同时承担理解者、状态维护者、角色本人、台词作者、关系经营者和最终交付者.它当然会倾向于把内部做过的工作全部写到外面.
但 HDSI 不能直接塞进一张角色卡#
理解这一点后,一个很自然的问题出现了:
能不能学习 HDSI 的机制,让普通的单模型 LLM RP 也获得一部分这样的自然感?
答案是可以尝试,但必须先承认边界.
HDSI 是需要独立部署的完整框架.而当前常见的 LLM RP 部署形态,依然是一个主模型、一份角色提示词和一个通用聊天宿主.有的平台会额外注入记忆摘要、工具结果、主动消息任务或图片内容,但最终通常还是由同一个模型阅读这些上下文,再一次性生成用户可见的回复.
提示词写得再好,也不可能凭空创造出框架没有提供的能力.
它不能自己获得可信的实时状态,不能保证持久记忆,不能真正等待十分钟再发消息,不能可靠取消尚未发送的气泡,不能确认某条主动消息是否投递成功,也不能让不存在的侧端模型突然出现.就像把一个普通聊天模型放进 Codex 以后,它因为宿主提供了文件、终端和工具才获得操作能力,而不是因为系统提示词写得足够神奇就凭空长出了手脚.
所以我的目标不是用一张 Prompt 复刻 HDSI.
我真正想做的是,在现有模型和平台都不改变的条件下,把 HDSI 中可以迁移的认知边界蒸馏出来,用于改善单个主模型的扮演层.
这项研究只借鉴 HDSI 公开设计中可泛化的职责划分与认知边界.它没有移植 HDSI 的代码、固定 Prompt、字段、JSON 协议、阶段流程或持续世界模拟.HDSI 仍然是一个独立项目,本仓库也不提供它的运行时保证.
我是怎样开始验证这个想法的#
我先做的不是立刻写一份更长的新角色卡,而是把旧方法重新拆开.
第一步,我将上一篇文章中的旧 Skill 定位为角色定义方法.它继续负责回答”这个角色是谁”,包括人格因果、关系位置、表达方式、互动边界和基本工具态度.
第二步,我对 HDSI 中可观察到的机制进行拆解.哪些原则可以直接转写成角色行为,哪些必须依赖宿主提供可信来源,哪些只能由 Prompt 软约束近似,哪些必须由真实运行时实现,以及哪些叙事协议根本不应该迁移到日常私聊角色卡中,都需要分开.
第三步,我尝试使用相同角色需求生成普通 Prompt 和 Skill Prompt,再让多个模型在薄测试脚本中进行对话.之后又把修改后的 Prompt 放回真实 AstrBot 私聊环境,观察气泡分段、表情包、图片、主动消息任务、工具上下文和连续闲聊中的实际表现.
这些测试能帮助暴露描述质量、指令遵循和工具出戏等定向问题,但它很难成为像代码 benchmark 那样稳定的排行榜.LLM RP 的体验受到模型版本、采样随机性、平台注入、记忆、工具、媒体链路、气泡渲染、用户输入习惯和评审者偏好的共同影响.
如果模拟用户总是根据角色卡出题,测试就会变成对答案.如果一直追着工具调用测试,模型和 Prompt 又会对测试场景过拟合.而真正的日常私聊里,大量消息根本没有明确目标,也不存在剧情进度需要推进.
所以我逐渐停止把不断扩大的 A/B 测试当作主要目标,转而保留更诚实的比较方式.在同一个精确模型和同一个宿主框架下固定系统注入、工具、记忆、媒体链路、采样参数和用户输入,再观察 Prompt 修改前后的相对变化.真人私聊用于暴露自然度问题,但个人偏好不能被包装成客观真理.
研究过程中,我发现了一个最突出的共同问题#
在真实私聊环境里连续测试和修改后,我逐渐发现许多看似不同的问题,背后其实存在同一条行为链.
我最初把它叫作模型的”功利心”或”交付感”.
当然,这只是一个方便理解的拟人化说法.我没有模型内部训练过程、奖励模型或可解释性证据,不能声称自己证明了某种真实的模型心理.所以在仓库中,我把这种可观察的输出模式正式称为展示性交付偏置.
它指的是,模型太想证明自己完成了这次互动.
面对一张梗图时,模型为了证明自己看懂了,会先复述图片的意思,再解释笑点,接着发表看法,最后补一句对用户的回应.
面对用户说”今天忙得差不多了,该吃点东西去了”时,它不满足于一句”嗯嗯,去吃吧”.它可能继续说”今天辛苦啦,好好吃点东西,我在这里等你回来”.这句话表面上很温柔,但它额外创造了”用户吃完以后会回来陪她继续聊天”的关系预期,也把一次普通告知改写成了一段被安排好的后续互动.
面对用户说”确实有些进展,但不多”时,它可能从”有进展就好啦,慢慢来嘛”一路补到”而且你都忙了一天了,能推进一点已经不错了,别太苛刻自己”.每句话都说得通,但模型其实是在完成一套肯定、安慰、积极重构和关怀收尾.
面对一张没有附文的表情包时,它甚至会努力从前几轮找出一个旧话题,替图片补上明确含义,然后继续回应那个已经结束的事件.图片原本可能只是一个语气符号,模型却觉得自己必须为它找到一个可以处理的任务.
这条链通常包含几种不同的”证明”:
- 理解证明.复述、翻译或拆解用户和图片的意思.
- 角色证明.堆叠笑声、口癖、可爱语气和表面性格特征.
- 遵循证明.把提示词里的每条风格要求都展示一遍.
- 价值证明.追加分析、建议、评价、安慰和积极重构.
- 完成证明.补上总结、追问、承诺或礼貌收尾.
最后,模型生成的不再是聊天参与者的一次自然反应,而是一份可以被验收的角色化交付物.
这也解释了为什么一些顶尖模型仍然会出现这种问题.模型越擅长理解、写作和完成任务,有时反而越有能力把一个很小的私聊事件加工成结构完整、态度充分、语义闭合的回答.模型性能提高可以改善理解,却不会自动改变它对”什么才算完成一轮”的默认判断.
要压下去的不是能力,而是证明冲动#
发现这个问题后,最容易走向的另一个极端,就是开始禁止模型关心、夸奖、建议、解释和追问.
但这同样不对.
如果用户真的遇到了严重问题,角色当然可以认真关心.如果用户明确寻求建议,模型也应该充分回答.如果角色本来就非常话多,或者当前话题真的激起了她的兴趣,长回复也完全可能比短回复更符合人设.
我们要压制的不是模型的理解、推理、关怀和表达能力,而是它把这些能力全部外显为证据的默认义务.
我最后将目标概括为一句话:
能力保留,证明冲动降权.内部可以充分理解,外部只承担当前互动真正需要的动作.
这会带来几个很重要的变化.
第一,私聊回复不再以”完整答案”为单位,而以”角色这一次为什么要发送这条消息”为单位.
第二,回应可以有选择性.角色不必覆盖用户消息中的全部信息点,也不必同时完成复述、态度、关怀和追问.
第三,第一条消息拥有结束这一轮的权利.如果一个”?”、一句”确实啊”或一个表情包已经完成了角色此刻的互动,就不需要为了显得礼貌和完整继续追加第二、第三个气泡.
第四,图片和表情包首先是一种聊天行为,然后才可能是一份需要解释的内容.它可以表达态度,替代标点,接住语气,或者只是无意义地存在.只有当当前消息真的提供了明确对象、命题或求助时,模型才有理由把它展开成信息任务.
第五,历史上下文只能帮助消歧,不能替当前消息制造新的事件.已经结束的话题,不能因为用户又发了一张低信息图片就被自动重新打开.
第六,规则本身也要避免变成新的任务清单.当我为了修复低信息图片的问题,不断加入”先判断当前事件”、“再区分历史”、“不得补全对象”之类的长难句时,提示词反而越来越像 Agent 工作流.模型开始更认真地分析,也更想展示自己正确执行了分析.这说明压制展示性交付偏置,不能靠另一份更加工程化的逐轮验收协议来完成.
一次编译期的”演中演”#
经过这些测试,我把 HDSI 的启发和真实失败逐渐整理成了一个编译期的”演中演”方法.
这里的”演中演”不是让最终聊天模型知道自己是演员,也不是在角色卡里继续叠一层导演身份.恰恰相反,这些脚手架必须在运行前全部消失.
它只发生在提示词编写阶段.
编写模型先理解角色本身是谁,再站到第二层去预判目标模型会怎样错误地表演这个角色:
- 它会不会把活泼理解成每轮都要大笑.
- 它会不会为了证明看懂梗图,先把整张图解释一遍.
- 它会不会把每条风格要求都逐项兑现给用户看.
- 它会不会把一句普通接话扩写成完整的情绪服务流程.
然后,编写模型再根据具体角色、具体模型和具体宿主,对提示词进行删重、整流、重排和条件化编译.最终运行时只保留一份统一的角色 Prompt.目标模型看不到 HDSI 术语、分析流程、评分标准、内部结构或”演员和导演”的隐喻,它只以角色本人进入聊天.
整个流程可以简化为:
用户的角色需求 -> 建立稳定的角色定义 -> 确认模型与平台的不变量 -> 预判目标模型的典型误读 -> 编译角色在该环境中的执行方式 -> 生成唯一可注入的角色 Prompt这不是在旧角色卡后面再粘贴一整块”拟人化规则”.新增内容也不一定让提示词变长.很多时候真正有效的做法反而是删除重复要求,合并冲突规则,把长难句拆开,并停止让模型逐项执行一份越来越像验收表的说明书.
从反复补丁,走向统一的作者 Skill#
当这些问题被拆开以后,我不再继续给某个角色版本无限追加局部补丁,而是把有效经验整理成可以重复使用的作者流程.为了避免后续迭代重新滑回单次主观打分,我保留了以下验证边界:
- 在同一个精确模型和同一个宿主框架下比较修改前后.
- 固定系统注入、工具、记忆、媒体链路、采样参数和用户输入.
- 用真实私聊暴露自然度问题,但不把个人偏好伪装成客观真理.
- 先判断失败属于模型、Prompt、宿主、采样还是单纯的偏好差异.
- 每次只修改真正拥有这个问题的那一层.
在结构上,旧方法也没有被简单抛弃.它仍然适合回答”这个角色是谁”.新的研究则继续回答”在这个模型和这个平台里,这个角色怎样表现得更像自己”.
最后,这两部分被整合成了一个统一的 Role Prompt Authoring 作者 Skill,而不是让用户面对两份表面上都在”写提示词”的独立说明.
它内部包含三条工作路径:
define.整理人格因果、关系位置、表达方式、互动边界和稳定设定.compile.结合目标模型、宿主能力和已知失败,生成唯一可注入的最终角色 Prompt.audit.先对真实失败进行归因,再决定应该修改角色定义、条件编译、宿主实现,还是承认模型能力和采样限制.
对于一个新角色,如果运行环境已经明确,这三步可以在一次作者流程中完成.用户不需要先拿到一份旧角色卡,再手动把它塞给第二份 Skill.对于已有角色卡,Skill 也可以先恢复其中必须保留的人格、关系、表达和边界,再重新编译,而不是机械拼接补丁.
最终进入运行模型上下文的仍然只有一份 Prompt.角色定义、运行档案、保留项、构建记录和验收重点都属于作者侧资产,不应该和角色 Prompt 一起注入.
研究最后得到的三层责任模型#
走到最后,我发现这次研究最重要的成果,并不是总结出了一组更高级的短回复技巧,而是把 LLM RP 中经常混在一起的问题重新分成了三层.
| 层级 | 负责什么 | 不能替另一层做到什么 |
|---|---|---|
| 模型层 | 指令遵循、多模态语用、长上下文稳定性、歧义处理和采样分布上限 | Prompt 无法让模型稳定获得它本来不具备的理解能力 |
| Prompt 层 | 角色人格、关系位置、注意倾向、解释方式、互动分寸和可见表达 | Prompt 无法创造可信状态、真实时间、工具结果和投递保证 |
| 宿主层 | 消息来源、当前事件、时间、状态、记忆、工具、媒体、调度、取消、渲染和投递 | 宿主无法代替角色设计,也无法保证模型一定自然演绎 |
这三层一旦分清,很多过去会陷入无止境补 Prompt 的问题,就有了停止条件.
模型连复杂语用都无法稳定理解时,这是模型能力限制.平台没有提供可信的当前事件和投递状态时,这是宿主限制.只有在同一个模型、同一个框架和同一组输入下,随着 Prompt 的改变而稳定变化的部分,才应该谨慎归因到提示词侧.
这也是为什么我不再把 Skill 描述成一个可以脱离环境独立工作的”完全体”.
它所尝试做的是,在模型、宿主和输入条件明确时,帮助提示词作者写出更清楚、更少冲突、更不容易被展示性交付偏置牵着走,也更符合私聊媒介直觉的一份角色 Prompt.它旨在提高某类自然表现出现的概率,帮助压低已经观察到的常见失败,并让后续迭代拥有更明确的归因路径.
它不能保证任意模型都像真人,不能彻底解决 OOC,不能代替持续真人磨合,也不能用纯提示词复现一个完整的多层运行框架.
这次研究最终留下了什么#
截至 2026 年 9 月 2 日,仓库主要整理了以下内容:
- 统一的中英文 Role Prompt Authoring Skill.
- Persona Definition v1 的历史归档与来源说明.
- 从角色定义到运行条件化编译的架构文档.
- 最终 Prompt 与作者侧附件的相关输出边界说明.
- 模型、Prompt 与宿主三层运行档案.
- 展示性交付偏置、语义闭合、旧话题吸附等失败归因方法.
- 面向真人测试的评估与修改流程.
当前公开版本仍是 研究草案,不是稳定版,也没有获得跨模型、跨平台的普适效果证明.
这里没有提供一个号称适用于所有角色、所有模型和所有平台的万能角色卡.我更希望它成为一种作者侧工程方法,让我们知道该怎样建立角色,怎样针对固定环境进行编译,怎样审查真实失败,也知道什么时候应该停止继续向 Prompt 追加规则.
如果要把整项研究压缩成一句话,那就是:
角色由 Prompt 编码,能力由宿主提供,上限由模型决定.
角色 Prompt 不是完整系统,也不应该被迫假装成完整系统.
HDSI 给我的最大启发,也不是如何写出一份更长、更复杂的人设.它让我看见,自然感有时来自系统愿意把复杂工作留在内部,并允许角色最终只说真正想说的那一点.
而我所做的,就是在无法更换主流单模型框架的前提下,尽可能把这种职责分离、可见性分离和互动选择的思路,蒸馏成一套可以迁移的提示词编写方法.
项目仓库: