TiMem 实战:为 AI NPC 构建长期记忆系统,实现玩家关系动态演变

一、AI NPC 的核心瓶颈

大语言模型的出现让 NPC 能够进行真正意义上的自然对话,但现有的 AI NPC 实现几乎都有同一个缺陷:跨会话无记忆

每次游戏启动或加载存档,NPC 对玩家的认知清零。玩家上一次游玩中帮助了 NPC、和 NPC 建立了深厚关系,下次进入游戏,NPC 完全不记得。

这使 AI NPC 退化成了「高级对话机器人」,而非真正有生命感的角色。

要实现真正的 NPC 记忆系统,需要解决三个问题:

  1. 跨会话持久化:游戏重启后记忆不丢失
    1. 关系动态演变:正面/负面事件累积改变关系状态
    1. 自然融合:NPC 提及历史时流畅自然,不像在读日志
      TiMem 的五层时序记忆树提供了完整解法。

二、记忆架构设计

2.1 记忆空间设计

每个 NPC 对每个玩家都维护独立的记忆空间:

Memory Key = {npc_id}_{player_id}

这样同一个 NPC 对不同玩家有不同的关系状态,不同 NPC 之间的记忆完全隔离。

2.2 五层记忆树在 NPC 场景的映射

L1 原始对话片段    ← 每次互动的原文
     ↓
     L2 互动摘要        ← 这次见面发生了什么
          ↓
          L3 阶段总结        ← 这一章节/游戏天的互动模式
               ↓
               L4 关系模式归纳    ← 玩家的行为风格、关系趋势
                    ↓
                    L5 玩家画像        ← 信任度、历史关键事件、长期印象
                    ```
### 2.3 事件类型划分

| 事件类型 | 示例 | 记忆权重 |
|---------|------|----------|
| 正面大事件 | 救了 NPC 的家人 | 高,长期保留 |
| 正面小事件 | 完成了 NPC 的委托 | 中,逐渐归纳 |
| 负面大事件 | 攻击/背叛 NPC | 高,长期保留 |
| 普通对话 | 日常交谈 | 低,自动摘要 |

---

## 三、完整实现代码

### 3.1 初始化

```bash
pip install timem-client openai
import os
import uuid
from timem_client import TiMemClient
from openai import OpenAI

timem = TiMemClient(api_key=os.environ["TIMEM_API_KEY"])
llm = OpenAI()

3.2 NPC 核心类

class NPC:
    def __init__(self, npc_id: str, name: str, role: str, personality: str):
            self.npc_id = npc_id
                    self.name = name
                            self.role = role
                                    self.personality = personality
    def memory_key(self, player_id: str) -> str:
            return f"{self.npc_id}_{player_id}"
    def talk(self, player_id: str, player_input: str, session_id: str) -> str:
            key = self.memory_key(player_id)
        # 检索历史记忆
                memories = timem.search(
                            query=player_input,
                                        user_id=key,
                                                    session_id=session_id,
                                                                top_k=5
                                                                        )
        memory_ctx = ""
                if memories:
                            lines = [f"- {m['content']}" for m in memories]
                                        memory_ctx = "你对这位玩家的记忆:\n" + "\n".join(lines)
        system_prompt = (
                    f"你是游戏中的 NPC,名叫{self.name},身份是{self.role}。\n"
                                f"性格:{self.personality}\n\n"
                                            "规则:\n"
                                                        "1. 根据历史关系调整语气(感激/中立/警惕/敌意)\n"
                                                                    "2. 自然提及过去的事件,不要像在背日志\n"
                                                                                "3. 保持角色身份一致\n\n"
                                                                                            + memory_ctx
                                                                                            +         )
        response = llm.chat.completions.create(
                    model="gpt-4o",
                                messages=[
                                                {"role": "system", "content": system_prompt},
                                                                {"role": "user", "content": player_input}
                                                                            ]
                                                                                    )
                                                                                            reply = response.choices[0].message.content
        # 存入记忆
                timem.add(
                            messages=[
                                            {"role": "user", "content": f"[玩家] {player_input}"},
                                                            {"role": "assistant", "content": f"[{self.name}] {reply}"}
                                                                        ],
                                                                                    user_id=key,
                                                                                                session_id=session_id
                                                                                                        )
                                                                                                                return reply
    def record_event(self, player_id: str, event: str, event_type: str):
            """记录关键游戏事件"""
                    tags = {
                                "positive": "[正面事件]",
                                            "negative": "[负面事件]",
                                                        "neutral": "[中性事件]"
                                                                }
                                                                        tag = tags.get(event_type, "[事件]")
                                                                                timem.add(
                                                                                            messages=[{"role": "system", "content": f"{tag} {event}"}],
                                                                                                        user_id=self.memory_key(player_id)
                                                                                                                )
    def get_relationship(self, player_id: str) -> str:
            """查询当前关系状态"""
                    memories = timem.search(
                                query="玩家行为 关系 事件",
                                            user_id=self.memory_key(player_id),
                                                        top_k=8
                                                                )
                                                                        if not memories:
                                                                                    return "陌生人"
        lines = [f"- {m['content']}" for m in memories]
                response = llm.chat.completions.create(
                            model="gpt-4o",
                                        messages=[{
                                                        "role": "user",
                                                                        "content": (
                                                                                            f"基于{self.name}对玩家的以下记忆,"
                                                                                                                "用一句话描述关系状态和原因:\n\n"
                                                                                                                                    + "\n".join(lines)
                                                                                                                                    +                 )
                                                                                                                                    +             }]
                                                                                                                                    +         )
                                                                                                                                    +         return response.choices[0].message.content
                                                                                                                                    + ```
### 3.3 NPC 社交网络(信息传播)

```python
def spread_rumor(source: NPC, target: NPC, player_id: str, content: str):
    """
        NPC 之间传递关于玩家的信息。
            实现「路人甲知道玩家在城东做了什么」的效果。
                """
                    timem.add(
                            messages=[{
                                        "role": "system",
                                                    "content": f"[传言,来自{source.name}] {content}"
                                                            }],
                                                                    user_id=target.memory_key(player_id)
                                                                        )
                                                                        ```
### 3.4 端到端示例

```python
if __name__ == "__main__":
    # 创建两个 NPC
        innkeeper = NPC(
                "npc_inn_01", "老托马斯", "酒馆老板",
                        "沧桑、话不多,对帮过他的人讲义气"
                            )
                                blacksmith = NPC(
                                        "npc_smith_01", "铁匠约翰", "铁匠",
                                                "实在、直接,喜欢有本事的人"
                                                    )
    PLAYER_A = "player_hero"
        PLAYER_B = "player_villain"
            session = str(uuid.uuid4())
    # 记录关键事件
        innkeeper.record_event(
                PLAYER_A,
                        "玩家击退歹徒,救了老托马斯的女儿",
                                "positive"
                                    )
                                        innkeeper.record_event(
                                                PLAYER_B,
                                                        "玩家趁夜偷走了酒馆的备用钱箱",
                                                                "negative"
                                                                    )
    # 老托马斯向铁匠约翰传递消息
        spread_rumor(
                innkeeper, blacksmith, PLAYER_A,
                        "那个旅行者帮我赶走了歹徒,是个值得信任的人"
                            )
    # 玩家A 与老托马斯对话
        r = innkeeper.talk(PLAYER_A, "老板,给我来杯酒。", session)
            print(f"老托马斯(对英雄):{r}\n")
    # 玩家B 与老托马斯对话
        r = innkeeper.talk(PLAYER_B, "老板,给我来杯酒。", session)
            print(f"老托马斯(对小偷):{r}\n")
    # 玩家A 与铁匠对话(铁匠听说了玩家的好事)
        r = blacksmith.talk(PLAYER_A, "师傅,帮我磨一下剑。", session)
            print(f"铁匠约翰:{r}\n")
    # 查询关系状态
        print("关系状态:", innkeeper.get_relationship(PLAYER_A))
            print("关系状态:", innkeeper.get_relationship(PLAYER_B))
            ```
---

## 四、性能与成本考量

**记忆存储**:TiMem 云端托管,无需自建向量数据库。

**Token 效率**:TiMem 复杂度感知召回比全量 context 减少 52% token 消耗。大型开放世界游戏中,NPC 数量可能达到数百个,token 节省效果显著。

**扩展性**:每个 NPC × 每个玩家独立记忆空间,支持水平扩展。

**延迟**:记忆写入异步处理,不阻塞对话响应;检索延迟通常在 100-300ms 内。

---

## 五、总结

本文实现了一个基于 TiMem 的 AI NPC 长期记忆系统,核心能力:

1. **跨会话持久化**:游戏重启后记忆保留
2. 2. **关系动态演变**:事件驱动的关系状态更新
3. 3. **NPC 社交网络**:信息在 NPC 间自然传播
4. 4. **低成本实现**:核心代码 < 100 行,token 消耗减少 52%
GitHub:https://github.com/TiMEM-AI/timem
在线体验:https://playground.timem.cloud
技术文档:https://docs.timem.cloud

给个 Star 支持开源!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐