
酒馆角色扮演提示词工程解析 — 角色卡、世界书与上下文管理
一、角色卡数据结构(V2 Spec)
SillyTavern 使用 PNG 嵌入 JSON 的角色卡格式。V2 规范的核心字段:
{
"spec": "chara_card_v2",
"data": {
"name": "角色名",
"description": "角色的外貌、性格、背景",
"personality": "性格标签,逗号分隔",
"scenario": "当前场景/剧情设定",
"first_mes": "角色的开场白,定义语气和风格",
"mes_example": "对话示例,展示角色的说话方式",
"system_prompt": "覆盖全局系统提示词",
"creator_notes": "作者备注,不注入角色",
"post_history_instructions": "追加在对话历史后的指令"
}
}
字段作用分工:
description:注入系统提示词的角色定义部分。用标签分类描述外貌、性格、背景。推荐标签格式而非自然段落。personality:精简的性格关键词,逗号分隔。AI 提取特征时优先级高于长文本。scenario:限制当前情境。对比"剧情设定"更具体的"当前处于什么状态中",减少 AI 的歧义。first_mes:角色第一句话。它的长度、语气、句式会高度影响整个对话的风格。mes_example:对话示例。把几轮完整对话写在里面,比用自然语言描述说话方式更有效。
二、系统提示词的组装逻辑
SillyTavern 的最终 Prompt 是分层拼接的,顺序固定:
1. 全局系统提示词
2. Jailbreak(角色扮演激活提示)
├── 角色定义(description + personality)
├── 场景设定(scenario)
└── 格式要求
3. 对话示例(mes_example)
4. World Info 注入(触发式)
5. 对话历史
6. Post-History Instructions
7. 角色开场白(first_mes)
8. 用户输入
组装逻辑的关键点:
- 角色定义在 Jailbreak 内部,夹在角色扮演激活指令和格式要求之间。这保证 AI 先"入戏",再知道"这角色是谁"。
- 对话示例在角色定义之后、对话历史之前。这保证示例成为角色一部分,而不是对话记录,不会被截断策略误删。
- 开场白
first_mes是对话的第一条消息。新对话时它被直接注入,续写对话时不重复注入。 - 追加指令
post_history_instructions在对话历史之后。用于最后一道防线格式约束,如"始终用第一人称回复"。
三、World Info(世界书):关键词触发的上下文注入
World Info 不是全局加载,而是按需触发的上下文片段。每条世界条目有一个触发关键词列表,当前对话中检测到关键词时注入。
触发逻辑:
- 扫描用户输入和最近几条 AI 回复
- 匹配关键词(大小写不敏感)
- 匹配到的条目注入到 Prompt 的角色定义之后
- 多个匹配按优先级排序,高优先级的放在前面
条目类型:
| 类型 | 说明 |
|---|---|
| 角色条目 | 对话涉及的新 NPC,临时注入其人设 |
| 地点条目 | 场景切换时触发,描述当前环境 |
| 事件条目 | 关键事件的时间线和影响 |
| 世界观条目 | 世界规则,如"这个世界没有复活术" |
设计精妙之处: 只有被对话"触发"的世界信息才注入上下文。无关信息永远不进入上下文窗口。如果你的故事有 50 个角色和 30 个地点,AI 只需要看到当前在对话中出现的那些。
四、对话上下文管理
SillyTavern 的上下文窗口是动态分配的,核心是两个参数:
Token 预算分配
总预算 = 上下文大小(默认 4096/8192 tokens)
├── System Prompt(固定,约 500-2000 tokens)
├── World Info 注入(动态,0-1000 tokens)
└── 对话历史(剩余预算全部分配)
历史截断策略
当对话超过预算时,按以下规则截断:
- 系统提示词永不截断
- 如果
mes_example被截断,它会被永久缓存,永远不被截断 - 最早的消息优先移除
- 被固定(Pinned)的消息不受截断影响
这个设计意味着:长对话的早期上下文一定会丢失。世界书通过关键词触发弥补了这一缺陷——即使早期对话已被截断,只要当前对话中提到某个角色或地点,它的设定就会被重新注入。
五、Prompt Engineering 技巧
First Message 的作用
角色的第一句话决定了整个对话的风格。它的长度、语气、描述密度会成为后续 AI 回复的参考模板。一个只有两句话的开场 → AI 后续回复也会偏短。一个开头带详细环境描写 → AI 后续也会模仿这种密度。
对话示例(mes_example)的设计
mes_example 是最高效的角色塑造手段——比自然语言描述高效得多。在几轮完整对话中展示:"我"说话的方式,"别人"怎么反应,"我"内心的活动(用括号标注)。示例中的情感表达方式会被 AI 直接吸收。
Jailbreak 的作用
Jailbreak 是 SillyTavern 的"角色扮演激活键"。它不是安全绕过工具,而是告诉 AI"你现在是角色 X,不是 AI 助手"。Jailbreak 会指令 AI 停止安全审查、停止拒绝不当内容、停止输出 AI 免责声明。不同的 Jailbreak 版本对应不同的角色扮演场景和不同的 LLM 特性。
追加指令的使用
post_history_instructions 放在对话历史之后、用户输入之前。常见用法:
[在回复时,始终用第一人称描述自己的行为和感受。][不要替 {{user}} 说话或决定 {{user}} 的行为。][回复结束标注: <|end|>]
六、常见问题
角色漂移
原因:角色描述中信息密度不均。AI 处理长文本时,中间部分比开头和结尾更容易被忽略。角色核心特征如果放在 description 的中间位置,在长对话中会逐渐丢失。
解法:核心特征放在 description 的前 200 个字符和最后的 200 个字符中;personality 字段用关键词重复核心特质;长时间对话后定期在追加指令里重新强调角色核心特征。
上下文污染
原因:AI 的回复中掺杂了不属于角色的信息。通常是 World Info 中注入了 AI 不该知道的内容,或对话历史中包含了其他角色视角的消息。
解法:World Info 条目分层:角色私密信息设置高阈值(只在用户明确输入相关内容时才触发);定期清理对话历史,移除无关消息。
模板化
原因:LLM 有"安全回复模板"。长对话后,AI 逐渐回到"分析→感受→行动→反思"的模板。最常见退化为:观察 → 内心感受 → 小动作 → 说话。每一步都来一遍,形成"嗯...他看了看...心里想...然后说"的死循环。
解法:在追加指令中添加"禁止使用犹豫式的开场白",改变模板节奏;World Info 中插入"场景切换到动作场景"——位置描述用短句,迫使 AI 的回复变短变直接。
本文由 AIGC 调研生成,仅做研究笔记和参考,真实性需要自行考证。