Files
Echo/Assets/_Project/Docs/Intelligent_Chat_System_Documentation_v2.md
T
2026-07-08 20:42:51 +08:00

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): "" (空)

对话发生:

  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 阶段四:验证记忆 (最终效果)

  1. User: "我叫什么?以及我现在要做什么?"
  2. 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 如何配置新角色

  1. 在场景中找到挂载 DeepSeekService 的物体。
  2. 在 Inspector 中修改 System Prompt (例如 "你是地堡安保与引导 AI")。
  3. 注意: 即使开启记忆系统,AI 也会基于这个 Prompt 进行总结拼接,不会覆盖你的人设。

6.2 性能调优

  • Max Context Window: 建议 20-50。太小会导致 AI 说话逻辑不连贯,太大会增加 API 费用。
  • Summary Threshold: 默认自动设为 Window 的一半。手动修改需谨慎。

6.3 调试建议

  • 开启 DeepSeekServiceEnable Debug Key 可在运行时通过特定口令越权调试。
  • 查看 Console 中的 [Memory] 日志可监控总结任务的触发与完成。