Files
Echo/Assets/_Project/Docs/Intelligent_Chat_System_Documentation_v2.md
T

189 lines
8.5 KiB
Markdown
Raw Normal View History

2026-07-08 19:53:15 +08:00
# 智能对话系统完整技术文档 (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)**: `""` (空)
**对话发生**:
1. **User**: "你好,我是 Alex。现在要去修复供电系统。"
2. **AI**: "已记录。建议先前往配电室,确认主断路器状态;如果你能提供当前所在区域,我可以给出更短路线。"
**此时内部数据**:
* `fullChatLog` (L2): 包含上述 2 条消息。
* `messagesSinceLastSummary`: 2 (达到阈值,触发总结任务)。
### 2.2 阶段二:触发语义总结 (L3 介入)
**后台处理 (用户无感知)**:
1. `ContextMemoryManager` 抓取最近 2 条对话。
2. **发送无状态请求 (Stateless Request)** 给 LLM:
* *Prompt*: "请将以下对话提炼为可用于后续对话的关键信息,要求:用第三人称、尽量短、只保留稳定事实与当前目标。对话:User: 你好,我是 Alex... AI: 已记录... 建议先前往配电室..."
3. **LLM 返回总结**: `"玩家名为 Alex;当前目标是修复供电系统;已建议前往配电室检查主断路器,并可在提供所在区域后给出更短路线。"`
4. **动态更新 System Prompt**:
* 新 Prompt: `"你是地堡安保与引导 AI(ECHO-7)。语气专业简洁;优先给出可执行的下一步建议;不要编造不存在的系统状态。\n\n[前情提要]: 玩家名为 Alex;当前目标是修复供电系统;已建议前往配电室检查主断路器,并可在提供所在区域后给出更短路线。"`
### 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 阶段四:验证记忆 (最终效果)
5. **User**: "我叫什么?以及我现在要做什么?"
6. **AI**: "你是 Alex。你当前的目标是修复供电系统;我建议你前往配电室检查主断路器,并根据指示灯确认是否需要切换到备用电源。"
-> **成功!** AI 通过 L3 的语义记忆(System Prompt)回答了 L1 工作记忆中已经丢失的问题。
---
## 3. 逻辑流程图 (Mermaid)
### 3.1 完整消息处理管线
此图展示了一条用户消息如何穿过三层系统,并触发存档和总结。
```mermaid
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` 中的实际内容示例:
```json
{
"keys": [
"ChatSystem",
"ContextMemory"
],
"values": [
// L2: 完整的对话流水账
"{\"logs\":[{\"role\":\"user\",\"content\":\"你好,我是Alex。现在要去修复供电系统。\"}, {\"role\":\"assistant\",\"content\":\"已记录。建议先前往配电室检查主断路器;如提供所在区域可给出更短路线。\"}]}",
// L3: 提炼后的语义总结
"{\"summary\":\"玩家名为Alex;当前目标是修复供电系统;已建议前往配电室检查主断路器,并可在提供所在区域后给出更短路线。\",\"counter\":2}"
]
}
```
---
## 6. 配置指南
### 6.1 如何配置新角色
1. 在场景中找到挂载 `DeepSeekService` 的物体。
2. 在 Inspector 中修改 **System Prompt** (例如 "你是地堡安保与引导 AI")。
3. **注意**: 即使开启记忆系统,AI 也会基于这个 Prompt 进行总结拼接,不会覆盖你的人设。
### 6.2 性能调优
* **Max Context Window**: 建议 **20-50**。太小会导致 AI 说话逻辑不连贯,太大会增加 API 费用。
* **Summary Threshold**: 默认自动设为 Window 的一半。手动修改需谨慎。
### 6.3 调试建议
* 开启 `DeepSeekService``Enable Debug Key` 可在运行时通过特定口令越权调试。
* 查看 Console 中的 `[Memory]` 日志可监控总结任务的触发与完成。