TiMem实战:为AI NPC 构建长期记忆系统,实现玩家关系动态演变
·
TiMem 实战:为 AI NPC 构建长期记忆系统,实现玩家关系动态演变
一、AI NPC 的核心瓶颈
大语言模型的出现让 NPC 能够进行真正意义上的自然对话,但现有的 AI NPC 实现几乎都有同一个缺陷:跨会话无记忆。
每次游戏启动或加载存档,NPC 对玩家的认知清零。玩家上一次游玩中帮助了 NPC、和 NPC 建立了深厚关系,下次进入游戏,NPC 完全不记得。
这使 AI NPC 退化成了「高级对话机器人」,而非真正有生命感的角色。
要实现真正的 NPC 记忆系统,需要解决三个问题:
- 跨会话持久化:游戏重启后记忆不丢失
-
- 关系动态演变:正面/负面事件累积改变关系状态
-
- 自然融合:NPC 提及历史时流畅自然,不像在读日志
TiMem 的五层时序记忆树提供了完整解法。
- 自然融合:NPC 提及历史时流畅自然,不像在读日志
二、记忆架构设计
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 支持开源!
更多推荐



所有评论(0)