AI 对话系统的核心工作 = 为每次对话组装最合适的上下文。本文以幽灵公主艾琳娜为线索,展示从传统预设对话到完整 AI 对话系统的八个演进阶段。
为 Unity 游戏构建了一套完整的 AI NPC 对话系统,让 NPC 能够根据世界观、角色人设、游戏状态进行智能对话。本文以一个具体案例为线索,展示系统从”传统预设对话”到”完整 AI 对话系统”的演进过程,最后揭示所有模块如何拼装成一个完整的上下文。
案例导入:玩家与幽灵的对话
全文将以这个案例为线索,展示系统从”传统预设对话”到”完整 AI 对话系统”的演进过程。
场景设定:
- 地点:废弃的古堡地下室
- NPC:艾琳娜(300 年前被囚禁于此的贵族幽灵)
- 背景:艾琳娜生前是王国公主,因被诬陷通敌而被囚禁,死后化为幽灵,徘徊在古堡中寻找证明清白的证据
体验演进:从传统对话树到 AI 对话系统
阶段一:传统预设对话
传统的做法是写一棵对话树——每个问题对应一个固定的回答,玩家只能从预设选项中选。当玩家问”你知道关于黑龙战争的事吗?“,NPC 只能回答”抱歉,我不明白你在说什么”,因为策划没有预设这个问题的答案。
传统对话树的三大痛点:
- 无法处理开放问题 — 玩家只能从预设选项中选
- 缺乏记忆和连贯性 — 每次对话都是全新开始
- 内容创作成本高 — 每个 NPC 需要大量对话分支
阶段二:引入 AI 大模型
接入大语言模型后,NPC 可以回应开放问题了:
玩家:你知道关于黑龙战争的事吗?
AI:「黑龙战争?那是一场可怕的战争,发生在很久以前…」
但新问题出现了——AI 太自由,会胡编乱造:“黑龙战争死了一百万人,国王亲自出征”——这些全是 AI 编的,游戏里不是这样设定的。
关键洞察:AI 太自由了,我们需要约束 AI 只说应该说的内容——这就是世界书要做的事。
阶段三:世界书——约束知识边界
解决方案:创建一个”知识库”,当玩家提到某个话题时,把相关知识注入给 AI。
// 世界书条目示例
{
"title": "黑龙战争",
"keywords": ["黑龙战争", "黑龙", "尼德霍格"],
"content": "黑龙战争发生在280年前,持续三年。黑龙'尼德霍格'袭击王国北境。
最终被银月骑士团击退,但王国北部十城化为废墟。
艾琳娜的兄长阿尔贝特王子在此战中阵亡。"
}
**触发机制:**玩家说”你知道黑龙战争吗?” → 关键词匹配 → 注入对应知识到 Prompt
效果:「黑龙战争发生在 280 年前,我的兄长阿尔贝特就是在那场战争中阵亡的…那头叫尼德霍格的黑龙,我至今还记得。」——知识准确了,与游戏设定一致。
但表达方式还是很机械——像在念百科全书,没有情感。
关键洞察:世界书解决了”说什么”的问题,但没解决”怎么说”的问题。我们需要给 NPC 注入性格和灵魂。
阶段四:角色卡——激活性格
为每个 NPC 写一张角色卡,定义它的性格、语气和情感表达:
你是艾琳娜,300年前因被诬陷通敌而被囚禁于此的公主幽灵。
## 性格特点
- 高贵但不傲慢,对善意的人友好
- 带着深深的悲伤和执念
- 对"背叛"这个词极其敏感
- 渴望被理解和帮助
## 说话风格
- 使用古典优雅的措辞
- 常用"......"表示沉默或回忆
- 提到过去时会变得忧伤
效果:
| 玩家提问 | 有角色卡的回答 |
|---|---|
| 你是怎么死的? | 「…我被关在这里三年,最后病死在这冰冷的牢房里。那一天,是我 22 岁生日…时间太久了,我有时会忘记…」 |
| 你恨陷害你的人吗? | 「恨?…也许曾经恨过。但 300 年的时间,足够让恨意消散。现在我只想…证明我的清白,然后安息。」 |
世界书和角色卡的分工:
| 模块 | 解决的问题 | 内容类型 | 共享性 |
|---|---|---|---|
| 世界书 | 说什么(知识) | 事件、地点、物品、历史 | 所有 NPC 共享 |
| 角色卡 | 怎么说(性格) | 语气、措辞、情感、态度 | 每个 NPC 独有 |
为什么要分开?黑龙战争是世界的客观事实,艾琳娜和酒馆老板都可能知道。但艾琳娜提到战争时会悲伤(因为兄长阵亡),酒馆老板则可能只是感慨。分开后可以复用:新增 NPC 只需写角色卡,关联现有世界书即可。
阶段五:认知限制——NPC 不该全知全能
通过角色卡中的关联字段,指定每个 NPC 能够访问哪些世界书条目:
{
"npcName": "艾琳娜",
"worldBooks": [
"wb_dragon_war", // 公共知识:黑龙战争
"wb_ghost_castle", // 公共知识:古堡历史
"wb_elina_secret_letter" // 私有知识:只有艾琳娜知道信件位置
]
}
| 角色 | 问”信件藏在哪” |
|---|---|
| 艾琳娜(有私有知识) | 「…信件就藏在东塔的密室里。那是我临死前托侍女莉莉丝藏起来的…」 |
| 酒馆老板(无此知识) | 「信件?什么信件?你说的是那个古堡里的幽灵公主吗?我只听说过那个传说…」 |
阶段六:记忆系统——维持连贯性
对话历史会越来越长,超出 AI 的上下文窗口后就会被裁剪。三级记忆架构解决这个问题:
- L1 短期记忆:最近 10 轮对话,直接作为消息发给 AI
- L2 对话摘要:压缩早期对话为摘要,保留关键信息(5-10x 压缩)
- L3 长期记忆:重要事实存储为结构化数据,跨会话保留
| 场景 | NPC 回答 |
|---|---|
| 第 20 轮:“你还记得我叫什么吗?” | 「艾德里安…当然记得。你是唯一一个说要帮我的人。」 |
| 跨会话(第二天登录):“我回来了。” | 「艾德里安!你真的回来了…我还以为你会像其他人一样,离开后就忘记我。」 |
阶段七:作者注释——运行时引导
作者注释是一种运行时动态注入的引导信息,告诉 AI”当前应该注意什么”。它像一个隐形的导演在幕后提词:
{
"authorNoteContent": "当前情境:玩家刚获得东塔钥匙。你应该:
1.表现出惊喜和希望 2.主动提到信件的事 3.引导玩家前往东塔"
}
| 无作者注释 | 有作者注释 |
|---|---|
| 「你想聊什么?」 | 「艾德里安!你手里拿的是…东塔的钥匙?!300 年了,终于有人能打开那扇门了…」 |
常见应用场景:玩家首次见面时引导自我介绍、任务完成后表现感激、玩家长时间未行动时委婉提醒、剧情高潮点时加强情绪。
阶段八:动态权重——聚焦话题
当系统注入了大量上下文,AI 可能会被不相关的信息干扰——玩家问”东塔钥匙在哪”,AI 却开始讲黑龙战争。解决方案是匹配权重加成:
最终权重 = 基础优先级 × 匹配权重 × 新鲜度权重
效果(玩家问"东塔钥匙在哪"):
├── 东塔钥匙:50 × 1.5 = 75 ← 精确匹配,权重最高
├── 黑龙战争:70 × 0.8 = 56 ← 无匹配,降权
└── 古堡历史:60 × 0.8 = 48 ← 无匹配,降权
另外还有新鲜度衰减防复读——刚使用的信息降到 0.2x,让 NPC 不会反复说同样的话。
至此,八个阶段的演进完成。 能回应开放问题(AI 大模型)、知识准确不胡编(世界书)、有独特性格(角色卡)、认知有边界(私有记忆)、能记住对话(记忆系统)、能引导玩法(作者注释)、回答聚焦不跑题(动态权重)。但这一切的背后,本质上是在做一件事——拼装上下文。
全景:上下文的完整拼图
前面八个阶段,每个阶段解决一个具体问题,引入一个新模块。但读完之后你可能会问:这些模块最终是怎么组合在一起的?
答案很简单——它们全部被拼装成一段文本(Prompt),在每次对话时发送给 AI。AI 只是一个”补全器”,你给它什么上下文,它就基于什么来回答。给它一句”你是艾琳娜,一个幽灵”,回答冷冰冰的;给它完整的角色卡 + 世界知识 + 记忆 + 场景引导,回答就有血有肉。
所以,AI 对话系统的核心工作 = 为每次对话组装最合适的上下文。 这就是标题说的 Context is All You Need。
构建 AI 世界需要哪些材料
把前面八个阶段引入的所有模块整理成一张清单——这就是构建一个可控的 AI 世界所需要的完整材料:
| 材料 | 解决什么 | 内容举例 | 共享性 |
|---|---|---|---|
| 世界书 | 世界的客观事实 | 黑龙战争的历史、古堡的地理、王国的政治 | 所有 NPC 共享 |
| 角色卡 | NPC 的性格和说话方式 | 艾琳娜的性格特点、说话风格、情感倾向 | 每个 NPC 独有 |
| 认知关联 | NPC 知道什么、不知道什么 | 艾琳娜知道密信位置,酒馆老板不知道 | 每个 NPC 独有 |
| 记忆 | NPC 记住了什么 | 对话摘要 + 长期记忆(跨会话) | 每个 NPC 独有 |
| 作者注释 | 当前场景应该怎么表现 | “玩家刚获得钥匙,表现惊喜” | 按场景动态生成 |
| 游戏状态 | 当前世界的实时状态 | 时间、地点、天气、任务进度 | 全局共享 |
这六种材料对应了现实世界中”人”对话时依赖的六种信息:
| 现实世界 | 系统设计 |
|---|---|
| 世界客观存在的事实 | 世界书 |
| 每个人独特的性格 | 角色卡 |
| 每个人知道的不一样 | 认知关联 |
| 每个人有自己的记忆 | 记忆系统 |
| 对话时会根据情境调整 | 作者注释 |
| 注意力集中在关键话题 | 动态权重 |
这些材料是怎么拼装的
每次玩家发送一条消息,系统按以下流程把这些材料拼装成一个完整的 Prompt:
展开完整代码 · 27 行
玩家发送消息
│
▼ ① 加载角色卡
│ PersonaManager 获取当前 NPC 的人设
│
▼ ② 匹配世界书
│ 根据玩家消息中的关键词,从世界书中查找相关条目
│ 同时根据认知关联过滤——只加载这个 NPC 有权访问的条目
│
▼ ③ 检索记忆
│ 查找对话摘要 + 长期记忆
│
▼ ④ 注入作者注释
│ 检查当前场景是否有运行时引导
│
▼ ⑤ 读取游戏状态
│ 时间、地点、天气、任务进度
│
▼ ⑥ 上下文编排
│ 收集以上所有片段,按动态权重排序
│ 在 Token 预算内裁剪(低权重的优先丢弃)
│
▼ ⑦ 组装 Prompt
│ 拼装为 SystemPrompt + Messages
│
▼ ⑧ 发送给 AI
流式返回,打字机效果展示关键在第 ⑥ 步:不是把所有材料都塞进去,而是按权重排序后在预算内裁剪。 和当前话题相关的信息权重高、排在前面;不相关的信息权重低,预算不够时优先丢弃。这就是为什么需要动态权重——它决定了有限的 Token 预算分配给哪些信息。
一个真实的 Prompt 长什么样
当玩家问”你知道黑龙战争吗?“时,系统最终拼装出的 Prompt:
展开完整代码 · 31 行
# SystemPrompt(实际发送给 AI 的内容)
## 角色设定
你是艾琳娜,300年前因被诬陷通敌而被囚禁于此的公主幽灵。
性格特点:高贵但不傲慢,带着深深的悲伤和执念......
[来自角色卡,~500 tokens]
## 作者注释
当前场景氛围:神秘、悲伤。引导玩家探索古堡秘密。
[来自作者注释,~50 tokens]
## 世界知识
[黑龙战争]
黑龙战争发生在280年前,持续三年......艾琳娜的兄长阵亡。
[来自世界书,关键词"黑龙战争"命中,~200 tokens]
[王子阿尔贝特]
艾尔文王国王子,艾琳娜的兄长。在黑龙战争中英勇战死......
[来自世界书,由"黑龙战争"条目递归触发,~150 tokens]
## 对话摘要
玩家自称艾德里安,是冒险者,表示愿意帮助艾琳娜证明清白。
[来自记忆系统,~100 tokens]
## 当前状态
- 游戏时间:夜晚
- 地点:古堡地下室
[来自游戏状态,~30 tokens]
---
总计:~1030 tokens(预算 1500 内)这就是”上下文工程”的全貌——六种材料,按权重排序,在 Token 预算内裁剪,拼装成一段 Prompt 发给 AI。AI 收到什么就基于什么回答,所以 Prompt 拼得好不好,直接决定了 NPC 的回答质量。
性能优化
上下文编排不是没有成本的。如果每次对话都遍历所有世界书条目做关键词匹配,性能会成为瓶颈。几个关键的优化策略:
| 策略 | 实现方式 | 效果 |
|---|---|---|
| 上下文编排 | 只注入相关片段,不是全部 | Token 减少 50-70% |
| 倒排索引 | 关键词 → 条目的映射表,O(1) 查找 | 查询性能 250x-1000x 提升 |
| 正则缓存 | 预编译正则表达式 | 匹配性能 1000x 提升 |
| Token 熔断 | 硬性 maxTokens 限制 | 防止超限 |
| 对话摘要 | 早期对话压缩为摘要 | 5-10x 压缩 |
优化后的实际数据:单次对话 Token 从 ~12,500 降到 ~1,500(节省 88%);本地处理耗时(世界书查询 ~0.2ms + 上下文编排 ~8ms)几乎无感知,用户感知的等待时间主要是 API 请求本身(~1 秒)。
内容创作方面,策划只需要写剧本(场景描述、角色设定、对话示例),后续由工具链自动拆分为角色卡和世界书条目,一键导入游戏。策划专注创意,工程交给工具。
总结
从传统对话树到完整 AI 对话系统,本质上是在解决一个问题:怎么在有限的 Token 预算内,给 AI 组装最合适的上下文。
八个阶段,每个阶段引入一种新的”材料”:
- AI 大模型 — 能回应开放问题,但会胡编
- 世界书 — 约束知识边界,让回答准确
- 角色卡 — 注入性格,让回答有灵魂
- 认知限制 — 每个 NPC 只知道该知道的
- 记忆系统 — 跨轮次、跨会话的连贯性
- 作者注释 — 运行时动态引导
- 动态权重 — 确保回答聚焦当前话题
这些材料最终被拼装成一段 Prompt——世界书提供事实、角色卡提供性格、认知关联控制边界、记忆维持连贯、作者注释引导方向、动态权重聚焦话题。AI 收到这段精心编排的上下文,输出的就是一个知道世界观、有自己性格、记得和你说过什么的 NPC。
Context is all you need.