8.5 KiB
8.5 KiB
智能对话系统完整技术文档 (v2.1)
1. 核心架构概述
本系统采用 “三层记忆结构” 来解决 LLM 在游戏中的长对话、API 成本控制与数据持久化问题。
1.1 三层记忆模型
| 层级 | 名称 | 职责 | 存储位置 | 关键特性 |
|---|---|---|---|---|
| L1 | 工作记忆 (Working Memory) | 维持 API 短期对话上下文 | DeepSeekService / DoubaoService |
滚动修剪 (Rolling Window),限制 Token 消耗 |
| L2 | 全局存档 (Full Chat Log) | 永久记录所有原始对话 | LLMChatManager |
只增不减,用于 UI 历史回看和存盘 |
| L3 | 语义记忆 (Semantic Memory) | 提炼关键信息,对抗遗忘 | ContextMemoryManager |
定期调用 AI 总结,动态注入 System Prompt |
2. 详细实现案例分析 (Case Study)
为了更直观地理解系统运作,我们以一个更适合技术展示的场景为例:对话内容尽量“业务化”,突出 L1/L2/L3 的分工、成本控制与抗遗忘效果。
场景设定:
- 角色: NPC “ECHO-7”(地堡安保与引导 AI)。
- 玩家: “Alex”。
- 参数配置:
Max Context Window(L1): 4 条 (极小值,用于演示滚动遗忘)。Summary Threshold(L3): 2 条 (每 2 句对话触发一次总结)。
2.1 阶段一:初次相遇 (初始化)
系统状态:
- System Prompt:
"你是地堡安保与引导 AI(ECHO-7)。语气专业简洁;优先给出可执行的下一步建议;不要编造不存在的系统状态。" - L1 (Working Memory):
[System] - L3 (Summary):
""(空)
对话发生:
- User: "你好,我是 Alex。现在要去修复供电系统。"
- AI: "已记录。建议先前往配电室,确认主断路器状态;如果你能提供当前所在区域,我可以给出更短路线。"
此时内部数据:
fullChatLog(L2): 包含上述 2 条消息。messagesSinceLastSummary: 2 (达到阈值,触发总结任务)。
2.2 阶段二:触发语义总结 (L3 介入)
后台处理 (用户无感知):
ContextMemoryManager抓取最近 2 条对话。- 发送无状态请求 (Stateless Request) 给 LLM:
- Prompt: "请将以下对话提炼为可用于后续对话的关键信息,要求:用第三人称、尽量短、只保留稳定事实与当前目标。对话:User: 你好,我是 Alex... AI: 已记录... 建议先前往配电室..."
- LLM 返回总结:
"玩家名为 Alex;当前目标是修复供电系统;已建议前往配电室检查主断路器,并可在提供所在区域后给出更短路线。" - 动态更新 System Prompt:
- 新 Prompt:
"你是地堡安保与引导 AI(ECHO-7)。语气专业简洁;优先给出可执行的下一步建议;不要编造不存在的系统状态。\n\n[前情提要]: 玩家名为 Alex;当前目标是修复供电系统;已建议前往配电室检查主断路器,并可在提供所在区域后给出更短路线。"
- 新 Prompt:
2.3 阶段三:对话继续与滚动遗忘 (L1 介入)
对话继续: 3. User: "我现在在仓储区。" 4. AI: "从仓储区出门右转进入维护走廊,沿主干道前进到第二个分岔口左转即可到配电室。到达后先确认主断路器与备用电源指示灯。"
此时 L1 (Working Memory) 状态:
- 总消息数: 1(System) + 2(Round 1) + 2(Round 2) = 5 条。
- 触发滚动压缩 (Max=4):
- 最早的
User: "你好,我是 Alex。现在要去修复供电系统。"被移除。 - 次早的
AI: "已记录。建议先前往配电室..."被保留 (或是移除,取决于具体修剪逻辑)。
- 最早的
关键点: 虽然 L1 里的“自我介绍 + 目标”原始消息被删除了,但 System Prompt 里已经注入了 “玩家名 + 当前目标 + 已给建议” 的语义记忆。
2.4 阶段四:验证记忆 (最终效果)
- User: "我叫什么?以及我现在要做什么?"
- AI: "你是 Alex。你当前的目标是修复供电系统;我建议你前往配电室检查主断路器,并根据指示灯确认是否需要切换到备用电源。"
-> 成功! AI 通过 L3 的语义记忆(System Prompt)回答了 L1 工作记忆中已经丢失的问题。
3. 逻辑流程图 (Mermaid)
3.1 完整消息处理管线
此图展示了一条用户消息如何穿过三层系统,并触发存档和总结。
sequenceDiagram
participant U as User (UI)
participant M as LLMChatManager (L2)
participant S as LLM Service (L1)
participant Mem as ContextMemory (L3)
participant API as DeepSeek API
participant Disk as SaveManager
Note over U, Disk: 阶段一:处理用户消息
U->>M: Send("我现在在仓储区")
M->>M: Add to fullChatLog
M->>Disk: SaveGame()
M->>Mem: OnMessageAdded()
M->>S: SendMessage("我现在在仓储区")
Note over S, API: 阶段二:L1 滚动压缩
S->>S: Add to History
S->>S: TrimHistory (若 > MaxWindow)
S->>API: POST Request (带 History)
API-->>S: Reply ("给出到配电室的路线与检查步骤")
Note over M, Disk: 阶段三:处理 AI 回复
S-->>M: Callback("给出到配电室的路线与检查步骤")
M->>M: Add to fullChatLog
M->>Disk: SaveGame()
M->>Mem: OnMessageAdded()
M-->>U: Update UI
Note over Mem, S: 阶段四:L3 异步总结 (若达到阈值)
Mem->>Mem: Check Threshold
Mem->>S: SendStatelessMessage(SummaryPrompt)
S->>API: POST Request (无历史,仅总结)
API-->>S: Summary Text
S-->>Mem: Return Summary
Mem->>Mem: Update currentSummary
Mem->>Disk: SaveGame()
Mem->>S: UpdateSystemPrompt(NewPrompt)
Note right of S: System Prompt 更新为:<br/>[原设] + [新总结]
4. 模块与接口详解
4.1 服务层 (DeepSeekService / DoubaoService)
负责与 LLM API 直接交互,维护 L1 工作记忆。
- 滚动压缩逻辑:
- 参数:
maxContextWindow(例如 20 条)。 - 机制: 每次发送前,若历史记录超限,则移除最早的对话(Index 1+),但始终保留 System Prompt (Index 0)。
- 参数:
- Prompt 动态更新:
UpdateSystemPrompt(string): 允许外部(L3 层)动态修改当前运行时的系统提示词。
- 无状态请求:
SendStatelessMessage(...): 发送不带历史记录的一次性请求,专用于 L3 层的总结任务,避免污染 L1 上下文。
4.2 管理层 (LLMChatManager)
作为中央枢纽,维护 L2 全局存档。
- 存档同步:
- 在游戏启动 (
RestoreState) 时,恢复fullChatLog,并调用activeService.SetHistory(),让 AI 瞬间“想起”最近的对话。
- 在游戏启动 (
4.3 记忆层 (ContextMemoryManager)
系统的“海马体”,维护 L3 语义记忆。
- 自动阈值同步:
Start()时读取maxContextWindow,将总结阈值 (summaryThreshold) 设为其一半。- 目的: 确保在 L1 层发生滚动遗忘之前,L3 层已经完成了关键信息的固化。
5. 存档数据结构示例
存档文件 savegame.json 中的实际内容示例:
{
"keys": [
"ChatSystem",
"ContextMemory"
],
"values": [
// L2: 完整的对话流水账
"{\"logs\":[{\"role\":\"user\",\"content\":\"你好,我是Alex。现在要去修复供电系统。\"}, {\"role\":\"assistant\",\"content\":\"已记录。建议先前往配电室检查主断路器;如提供所在区域可给出更短路线。\"}]}",
// L3: 提炼后的语义总结
"{\"summary\":\"玩家名为Alex;当前目标是修复供电系统;已建议前往配电室检查主断路器,并可在提供所在区域后给出更短路线。\",\"counter\":2}"
]
}
6. 配置指南
6.1 如何配置新角色
- 在场景中找到挂载
DeepSeekService的物体。 - 在 Inspector 中修改 System Prompt (例如 "你是地堡安保与引导 AI")。
- 注意: 即使开启记忆系统,AI 也会基于这个 Prompt 进行总结拼接,不会覆盖你的人设。
6.2 性能调优
- Max Context Window: 建议 20-50。太小会导致 AI 说话逻辑不连贯,太大会增加 API 费用。
- Summary Threshold: 默认自动设为 Window 的一半。手动修改需谨慎。
6.3 调试建议
- 开启
DeepSeekService的Enable Debug Key可在运行时通过特定口令越权调试。 - 查看 Console 中的
[Memory]日志可监控总结任务的触发与完成。