给 AI 装上长期记忆:Zep Cloud 初探与上手教程
在构建智能对话系统时,记忆 是一个至关重要的能力。一个 AI 助手如果每次都从零开始对话,而无法记住用户的历史偏好、兴趣和上下文,就很难被认为是「智能」的。
Zep 正是为了解决这一问题的工具,它提供了长期记忆(long-term memory) 的能力,让 AI 可以像人类一样,在多轮交互中逐渐形成对用户的理解。
这篇文章会结合一些示例代码,带大家对 Zep 的长期记忆 有一个初步的认识。
1. 环境准备
使用 Zep 之前,需要先获取 API Key,Zep – AI Memory for Applications
并通过环境变量配置:
from dotenv import load_dotenv
import os
# 加载 .env 文件
load_dotenv(override=True)
# 获取 ZEP API Key
ZEP_API_KEY = os.getenv("ZEP_API_KEY")
安装依赖:
pip install python-dotenv zep-cloud
然后通过 Zep 客户端与 Zep 服务交互:
from zep_cloud.client import Zep
client = Zep(api_key=ZEP_API_KEY)
2. 用户的管理
在长期记忆中,用户(User) 是最核心的对象。Zep 提供了用户的增删改查功能,比如:
-
添加用户:
def add_user(user_id, email, first_name, last_name):
"""添加一个新用户"""
user = client.user.add(
user_id=user_id,
email=email,
first_name=first_name,
last_name=last_name,
)
print(f"✅ 用户 {user_id} 已创建:", user)
return user
-
获取用户信息:
def get_user(user_id):
"""获取用户信息"""
user = client.user.get(user_id)
print("ℹ️ 用户信息:", user)
return user
通过这些接口,Zep 可以为每个用户维护独立的记忆空间,避免不同用户之间的干扰。
3. 会话与线程(Thread)
Thread 可以理解为某个用户与 AI 的对话会话,它是记忆的载体。
我们可以为用户创建一个新的对话线程:
import uuid
def create_thread(user_id):
"""为用户创建新的对话线程"""
thread_id = uuid.uuid4().hex
client.thread.create(thread_id=thread_id, user_id=user_id)
print("🆕 新建线程:", thread_id)
return thread_id
在这个会话中,用户和 AI 的消息都会被存储,逐渐形成长期记忆。
4. 向 Zep 添加记忆
当用户和 AI 进行对话时,我们可以把消息存储到 Zep 中。例如:
def add_memory(user_id, bot_id, thread_id, user_message, bot_message):
"""将用户和 AI 的对话存入记忆"""
messages = [
Message(name=user_id, role="user", content=user_message),
Message(name=bot_id, role="assistant", content=bot_message),
]
client.thread.add_messages(thread_id, messages=messages)
print(f"💾 已存入记忆: {user_message} -> {bot_message}")
比如,用户说「我想学习 Python」,AI 回复「好的,我来教你一些基础代码」,这段信息就会被 Zep 存储起来。
5. 从 Zep 中检索记忆
Zep 的强大之处在于,它不只是单纯的对话存档,而是提供了结构化的长期记忆检索能力。
例如,我们可以通过以下方式获取某个对话线程的上下文摘要:
def get_user_context(thread_id, mode="summary"):
"""获取用户上下文(支持 summary/basic 两种模式)"""
memory = client.thread.get_user_context(thread_id=thread_id, mode=mode)
print(f"📌 用户上下文({mode}):n", memory.context)
return memory.context
Zep 会自动对历史对话进行摘要,提取用户的偏好和事实,从而在后续对话中帮助 AI 更好地理解用户。
同时,Zep 还支持基于 知识图谱(graph) 的检索,可以通过 search_in_graph 或 get_relevant_fact 找到和用户相关的事实和关系。这使得 AI 不仅能记住对话,还能推理出用户的兴趣、习惯和事实网络。
6. 一个简单的完整的例子
import os
import uuid
from dotenv import load_dotenv
from zep_cloud.client import Zep
from zep_cloud import Message
# ======================
# 1. 初始化 Zep 客户端
# ======================
load_dotenv(override=True)
ZEP_API_KEY = os.getenv("ZEP_API_KEY")
client = Zep(api_key=ZEP_API_KEY)
# ======================
# 2. 用户管理
# ======================
def add_user(user_id, email, first_name, last_name):
"""添加一个新用户"""
user = client.user.add(
user_id=user_id,
email=email,
first_name=first_name,
last_name=last_name,
)
print(f"✅ 用户 {user_id} 已创建:", user)
return user
def get_user(user_id):
"""获取用户信息"""
user = client.user.get(user_id)
print("ℹ️ 用户信息:", user)
return user
# ======================
# 3. 会话管理(Thread)
# ======================
def create_thread(user_id):
"""为用户创建新的对话线程"""
thread_id = uuid.uuid4().hex
client.thread.create(thread_id=thread_id, user_id=user_id)
print("🆕 新建线程:", thread_id)
return thread_id
# ======================
# 4. 添加记忆
# ======================
def add_memory(user_id, bot_id, thread_id, user_message, bot_message):
"""将用户和 AI 的对话存入记忆"""
messages = [
Message(name=user_id, role="user", content=user_message),
Message(name=bot_id, role="assistant", content=bot_message),
]
client.thread.add_messages(thread_id, messages=messages)
print(f"💾 已存入记忆: {user_message} -> {bot_message}")
# ======================
# 5. 获取长期记忆摘要
# ======================
def get_user_context(thread_id, mode="summary"):
"""获取用户上下文(支持 summary/basic 两种模式)"""
memory = client.thread.get_user_context(thread_id=thread_id, mode=mode)
print(f"📌 用户上下文({mode}):n", memory.context)
return memory.context
# ======================
# 6. 演示流程
# ======================
if __name__ == "__main__":
# 定义两个用户:human user 和 bot
user_id = "harry_user"
bot_id = "ai_bot"
# 创建用户
add_user(user_id, "harry@example.com", "Harry", "Liu")
add_user(bot_id, "bot@example.com", "AI", "Assistant")
get_user(user_id)
get_user(bot_id)
# 创建对话线程(以 human user 为主)
thread_id = create_thread(user_id)
# 模拟一次对话
user_msg = "Hi, my name is Harry. I love watching movies and learning Python."
bot_msg = "Nice to meet you Harry! 🎬🐍 Movies and Python are both great choices!"
add_memory(user_id, bot_id, thread_id, user_msg, bot_msg)
# 再来一次对话
user_msg2 = "I want to learn Python basics, please teach me."
bot_msg2 = "Sure! Let's start with printing text:n```pythonnprint('Hello, Harry!')n```"
add_memory(user_id, bot_id, thread_id, user_msg2, bot_msg2)
# 获取用户记忆摘要
get_user_context(thread_id, "summary")
get_user_context(thread_id, "basic")
执行结果
✅ 用户 harry_user 已创建: created_at='2025-08-23T03:25:14.843616Z' deleted_at=None email='harry@example.com' fact_rating_instruction=None first_name='Harry' id=35 last_name='Liu' metadata=None project_uuid='ff41087d-e0f6-496d-8cea-e2e05be96d20' session_count=None updated_at='2025-08-23T03:25:14.843616Z' user_id='harry_user' uuid_='19a1bc52-102c-4610-8941-63bda6979204'
✅ 用户 ai_bot 已创建: created_at='2025-08-23T03:25:15.208405Z' deleted_at=None email='bot@example.com' fact_rating_instruction=None first_name='AI' id=36 last_name='Assistant' metadata=None project_uuid='ff41087d-e0f6-496d-8cea-e2e05be96d20' session_count=None updated_at='2025-08-23T03:25:15.208405Z' user_id='ai_bot' uuid_='9d915a28-0b54-4b09-b6f6-eebd1c5fc3d7'
ℹ️ 用户信息: created_at='2025-08-23T03:25:14.843616Z' deleted_at=None email='harry@example.com' fact_rating_instruction=None first_name='Harry' id=35 last_name='Liu' metadata=None project_uuid='ff41087d-e0f6-496d-8cea-e2e05be96d20' session_count=None updated_at='2025-08-23T03:25:14.843616Z' user_id='harry_user' uuid_='19a1bc52-102c-4610-8941-63bda6979204'
ℹ️ 用户信息: created_at='2025-08-23T03:25:15.208405Z' deleted_at=None email='bot@example.com' fact_rating_instruction=None first_name='AI' id=36 last_name='Assistant' metadata=None project_uuid='ff41087d-e0f6-496d-8cea-e2e05be96d20' session_count=None updated_at='2025-08-23T03:25:15.208405Z' user_id='ai_bot' uuid_='9d915a28-0b54-4b09-b6f6-eebd1c5fc3d7'
🆕 新建线程: b4cfdfa942f34c768e2b4348c31d32d9
💾 已存入记忆: Hi, my name is Harry. I love watching movies and learning Python. -> Nice to meet you Harry! 🎬🐍 Movies and Python are both great choices!
💾 已存入记忆: I want to learn Python basics, please teach me. -> Sure! Let's start with printing text:
```python
print('Hello, Harry!')
```
📌 用户上下文(summary):
• Harry Liu introduced himself as someone who loves watching movies and learning Python (2024-12-19 - 2024-12-19)
• Harry Liu requested to learn Python basics (2024-12-19 - 2024-12-19)
• AI bot provided first Python instruction: print('Hello, Harry!') (2024-12-19 - 2024-12-19)
• Harry Liu's user profile includes email harry@example.com and user_id harry_user (2024-12-19 - 2024-12-19)
📌 用户上下文(basic):
FACTS and ENTITIES represent relevant context to the current conversation.
# These are the most relevant facts and their valid date ranges
# format: FACT (Date range: from - to)
<FACTS>
- ai_bot is teaching Harry Python basics. (2025-08-23 03:25:17 - present)
- Harry wants to learn Python basics. (2025-08-23 03:25:17 - present)
- Harry Liu loves learning Python (2025-08-23 03:25:17 - present)
- ai_bot thinks Python are great choices (2025-08-23 03:25:17 - present)
- Harry Liu loves watching movies (2025-08-23 03:25:17 - present)
</FACTS>
# These are the most relevant entities
# Name: ENTITY_NAME
# Label: entity_label (if present)
# Attributes: (if present)
# attr_name: attr_value
# Summary: entity summary
<ENTITIES>
- Name: Python basics
Label: Topic
Attributes:
domain: Python
expertise_level: basics
Summary: Harry wants to learn Python basics.
</ENTITIES>
7. 知识图谱搜索(Graph Search)
在前面的例子里,我们通过 user_context 可以快速拿到用户的摘要信息。但在更复杂的 RAG 问答 场景下,仅靠摘要可能不够精确。这时候,Zep 提供的 知识图谱搜索(Graph Search)就派上用场了。
为什么需要知识图谱?
-
精确检索用户事实:比如用户喜欢的编程语言、职业、同事关系等。
-
关系推理:例如“Harry 和谁是同事?”、“他在哪家公司工作?”。
-
复杂问题处理:多个实体、多关系组合的问题。
图搜索代码示例
def search_in_graph(user_id, query_text, center_node_uuid=None):
"""
在 Zep 知识图谱中搜索与 query_text 相关的节点或事实
"""
client = Zep(api_key=ZEP_API_KEY)
if center_node_uuid:
results = client.graph.search(
user_id=user_id,
query=query_text,
reranker="node_distance",
center_node_uuid=center_node_uuid # 可选,指定搜索中心
)
else:
results = client.graph.search(
user_id=user_id,
query=query_text
)
relevant_nodes = results.nodes
relevant_edges = results.edges
print("=== 节点 ===")
if relevant_nodes:
for node in relevant_nodes:
print(node)
print("=== 相关事实 ===")
if relevant_edges:
for edge in relevant_edges:
print(edge.fact)
if __name__ == "__main__":
search_in_graph(user_id, "what does harry like?")
执行结果
=== 节点 ===
=== 相关事实 ===
Harry Liu loves watching movies
Harry Liu loves learning Python
Harry wants to learn Python basics.
ai_bot is teaching Harry Python basics.
Harry Liu wants to learn Python basics.
ai_bot thinks movies are great choices
ai_bot thinks Python are great choices
随机问题时怎么办?
在实际 RAG 场景里,用户的问题往往是随机的,我们并不能提前知道要以哪个节点作为中心。这里有两种策略:
1. 全局搜索(不指定中心节点)
search_in_graph(user_id, query_text)
Zep 会在整个知识图谱里检索与问题相关的节点和事实。
适合范围比较宽泛、问题不确定的场景。
2. 自动推断中心节点
我们可以先对用户问题做 关键词/实体抽取,再去匹配知识图谱节点。如果找到对应节点,就用它作为搜索中心;找不到,则 fallback 到全局搜索。
示例代码:
def auto_graph_search(user_id, query_text):
client = Zep(api_key=ZEP_API_KEY)
# 先尝试列出用户所有节点
nodes = client.graph.node.get_by_user_id(user_id=user_id)
# 简单关键词匹配(可以换成更智能的 NER 模型)
center_node_uuid = None
for node in nodes:
if node.label.lower() in query_text.lower():
center_node_uuid = node.uuid
break
# 如果找到中心节点,就指定搜索,否则全局搜索
return search_in_graph(user_id, query_text, center_node_uuid)
3. 搜索图的范围有三种 (edges, nodes , episodes)
query = "What projects is Jane working on?"
# Search for edges in a graph
edge_results = client.graph.search(
graph_id=graph_id,
query=query,
scope="edges", # Default is "edges"
limit=5
)
# Search for nodes in a graph
node_results = client.graph.search(
graph_id=graph_id,
query=query,
scope="nodes",
limit=5
)
# Search for episodes in a graph
episode_results = client.graph.search(
graph_id=graph_id,
query=query,
scope="episodes",
limit=5
)
# search for perferences
search_results = client.graph.search(
user_id=user_id,
query="the user's music preferences",
scope="nodes",
search_filters={
"node_labels": ["Preference"]
}
)
for i, node in enumerate(search_results.nodes):
preference = node.attributes
print(f"Preference {i+1}:{preference}")
8. 初步认识与思考
从上面的例子可以看到,Zep 提供了以下几个层次的记忆能力:
-
对话存储:保留用户与 AI 的消息。
-
上下文总结:自动生成用户画像和对话摘要。
-
图谱搜索:以结构化的方式组织知识,方便 AI 检索和推理。
这让 AI 不仅能「记住你说过的话」,还可以「理解你是谁」、「你关心什么」、「你曾经提过的事实」——这就是长期记忆的价值。
总结
传统的聊天机器人往往是「短期记忆」:只记住本轮对话内容。而 Zep 则进一步赋予 AI 「长期记忆」:它能管理用户信息、保存对话线程、抽取知识图谱,并支持高效的检索和推理。
对于想要打造真正个性化 AI 助手的开发者来说,Zep 提供了一套非常实用的工具。未来我们还可以基于这些记忆能力,构建更加智能、持久且个性化的 AI 应用。
参考资料
https://github.com/getzep/zep
https://github.com/getzep/graphiti
Context Engineering Platform for AI Agents – Zep
其它
Zep 知识图谱结构

Zep 的知识图谱是围绕 用户个性化事实 自动构建的。
当用户和 bot 的对话中出现了新的事实(比如职业、爱好、关系等),Zep 会把这些事实提取出来,构造成 节点(Node) 和 边(Edge),存放到图数据库里。
1. 节点(Node)

节点通常表示 实体,比如:
-
人物:
Harry、小明、AI bot -
组织:
百度、OpenAI -
事物:
Python、篮球、纽约 -
概念:
爱好、职业
每个节点包含信息:
-
uuid:节点唯一 ID
-
labels:标签名称,比如
"User", "Entity" -
summary:关于这个实体的总结描述(可能是从多条对话中生成的)
2. 边(Edge)

边表示 事实或关系,连接两个节点。
-
uuid:节点唯一 ID
-
fact:这条边表达的事实,例如:
-
"Harry 在百度工作" -
"Harry 的同事是小明" -
"Harry 喜欢 Python"
-
边不仅仅是“连接”,它们包含了 关系语义,是知识图谱的核心价值。


3. 图的构建方式
Zep 会自动从对话中抽取事实,比如:
用户说:
我在百度工作,我的同事是小明。我喜欢 Python。
知识图谱中会自动生成:
-
节点:
-
Harry
-
百度
-
小明
-
Python
-
-
边:
-
(Harry) —— [职业] ——> (百度)
-
(Harry) —— [同事] ——> (小明)
-
(Harry) —— [爱好] ——> (Python)
-
4. 知识图谱与 user_context 的区别
-
user_context:是 Zep 给出的一个 文本总结/提取块,方便直接放进 prompt,让 LLM 拿到用户背景。
-
比如
Harry 是 25 岁的程序员,在百度工作,喜欢 Python 和篮球。
-
-
knowledge graph:是一个结构化的 实体-关系图,方便做事实检索和推理。
-
比如能回答:
-
Harry 的同事是谁?
-
Harry 的爱好和职业之间有没有联系?
-
和 Harry 相关的所有实体节点有哪些?
-
-
小结:
-
节点(Node) 存放用户相关的实体。
-
边(Edge) 存放事实和关系,带有自然语言描述。
-
知识图谱 适合做结构化检索和推理(特别是关系类问题)。
-
user_context 更适合当作 RAG 的输入上下文,直接提供背景信息给 LLM。