☰
AI Agent 记忆方案怎么选:Mem0、Zep、LangMem 在 Hermes 里的配置踩坑与 TaoToken 接入
2026/9/26 9:20:49 网站建设 项目流程

1. Hermes 里接记忆方案,我踩过的那些坑

Hermes 是一个支持多模型、多工具链的 Agent 运行时,你可以把它理解成一个「调度中枢」:它负责把用户输入分发给 LLM、调用工具、维护会话状态。但 Hermes 本身不内置长期记忆——它只维护当前会话的 context window,聊完就丢。这就是为什么同一个用户隔天回来,Agent 又像第一次见面一样从头问起。

Mem0、Zep、LangMem 是目前在 Hermes 这类 Agent 框架里接入最多的三种记忆方案。它们解决的是同一个问题:跨会话保存用户偏好、历史事实、实体关系,并在新一轮对话时把相关记忆检索出来注入 system prompt。但三者的配置方式、依赖组件、报错模式完全不同。Mem0 靠 Qdrant 做向量存储、LLM 做自动提取;Zep 靠 Graphiti 引擎做时间知识图谱;LangMem 则深度绑定 LangGraph 生态,在 Hermes 里属于「能接但别扭」的那一类。

这篇文章聚焦的是配置层面的差异和踩坑:settings.json / config.toml 怎么写、TaoToken 的统一 Key 怎么接进去、记忆读写到底有没有生效怎么验证。适合已经在用 Hermes、准备给 Agent 加长期记忆的开发者。如果你还在选型阶段,可以先看配置骨架再决定用哪个。

2. 前置:TaoToken 统一 Key 与 Hermes 的模型接入

在配记忆方案之前,先把模型接入层理顺。Mem0 和 Zep 都需要一个 LLM 来做记忆提取(把对话里的关键事实抽出来),也需要一个 embedding 模型来做向量化。Hermes 本身调 LLM 也需要 Key。如果每个组件各配一套 Key,管理起来很乱。

TaoToken 提供的是 OpenAI 兼容的统一接入方式,一个 Key 可以同时给 Hermes 主推理、Mem0 提取、embedding 三处用。接入地址是https://taotoken.net/api,兼容 OpenAI SDK 的base_url参数。

你需要在 TaoToken 控制台创建一个 API Key,然后把它写进环境变量,避免硬编码进配置文件:

export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"

Hermes 的模型配置里,把 provider 指向这个 base_url。如果你用的是 OpenAI SDK 风格的调用,改base_url和api_key两个字段就够了。Mem0 的 config 里同理,llm.config和embedder.config都加上openai_base_url指向 TaoToken。

注意:TaoToken 的 API 地址不带 UTM 参数,直接写https://taotoken.net/api即可。控制台和 Key 管理在https://taotoken.net/console,模型对话调试在https://taotoken.net/model-chat。

这一步做完,后面三个记忆方案的配置都复用同一个 Key,不用来回切换。

3. 三套可复制的配置骨架

3.1 Mem0 + Qdrant 的 config.toml 骨架

Mem0 的配置核心是vector_store、llm、embedder三块。Hermes 里我把它放在config/memory.toml,启动时读进来转成 dict 传给Memory.from_config()。

[vector_store] provider = "qdrant" [vector_store.config] host = "localhost" port = 6333 collection_name = "hermes_mem0" [llm] provider = "openai" [llm.config] model = "gpt-4o-mini" openai_base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}" [embedder] provider = "openai" [embedder.config] model = "text-embedding-3-small" openai_base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}"

Qdrant 用 Docker 起一个就够:

docker run -d --name qdrant \ -p 6333:6333 -p 6334:6334 \ --memory=1g \ qdrant/qdrant:latest

Mem0 的坑集中在 Qdrant 版本和 collection 初始化。如果 Qdrant 低于 1.7,Mem0 写入时会报Collection not found,因为新版 API 路径变了。直接 pull latest 重来。

3.2 Zep + Graphiti 的 settings.json 骨架

Zep 的接入方式和 Mem0 差别很大。它不依赖外部向量库,Graphiti 引擎自带存储层(默认用 Neo4j 或 FalkorDB)。Hermes 里我把它放在config/zep.settings.json:

{ "zep": { "api_url": "http://localhost:8000", "api_key": "${ZEP_API_KEY}" }, "graphiti": { "llm": { "provider": "openai", "model": "gpt-4o-mini", "base_url": "https://taotoken.net/api", "api_key": "${TAOTOKEN_API_KEY}" }, "embedder": { "provider": "openai", "model": "text-embedding-3-small", "base_url": "https://taotoken.net/api", "api_key": "${TAOTOKEN_API_KEY}" }, "store": { "type": "neo4j", "uri": "bolt://localhost:7687", "user": "neo4j", "password": "hermes_zep" } } }

Zep 自托管需要先起 Neo4j:

docker run -d --name neo4j \ -p 7687:7687 -p 7474:7474 \ -e NEO4J_AUTH=neo4j/hermes_zep \ neo4j:5

Zep 的配置复杂度明显高于 Mem0,主要成本在 Neo4j 的运维。如果你只是想要「记住用户偏好」,Zep 有点重。但如果你需要「用户周二说讨厌理论、周四说可以加点背景」这种时间冲突处理,Zep 的 Graphiti 是目前唯一能优雅处理的。

3.3 LangMem 在 Hermes 里的适配层

LangMem 是 LangGraph 的原生插件,Hermes 不是 LangGraph 架构,所以不能直接pip install就用。我的做法是写一个适配层,把 LangMem 的create_memory_store_manager包一层,让 Hermes 的 memory 接口能调它。

from langmem import create_memory_store_manager from langgraph.store.memory import InMemoryStore store = InMemoryStore() manager = create_memory_store_manager( "openai:gpt-4o-mini", store=store, base_url="https://taotoken.net/api", api_key=os.getenv("TAOTOKEN_API_KEY"), ) class HermesLangMemAdapter: def add(self, messages, user_id): manager.invoke({"messages": messages, "user_id": user_id}) def search(self, query, user_id): return manager.search(query, user_id=user_id)

这个适配层能跑,但 LangMem 的存储后端默认是 InMemoryStore,重启就丢。要持久化得换成 Postgres 或 Redis 的 store。而且 LangMem 的记忆提取是半自动的,需要你手动定义 schema,不像 Mem0 那样扔进去就自动抽。在 Hermes 里用 LangMem,适配成本比前两个高一个量级。

4. 验证记忆读写是否生效

配完不算完,得验证记忆真的写进去了、真的能检索出来。三个方案验证方式不同,但核心动作一样:写入一段带用户偏好的对话,然后换一个 query 检索,看能不能命中。

Mem0 的验证最直接:

from mem0 import Memory memory = Memory.from_config(config) user_id = "test_user_001" conversation = [ {"role": "user", "content": "我是做量化的,用 Python 写策略。"}, {"role": "assistant", "content": "明白。"}, {"role": "user", "content": "别给我讲理论,直接上代码。"}, ] memory.add(conversation, user_id=user_id) all_mem = memory.get_all(user_id=user_id) for item in all_mem["results"]: print("提取到:", item["memory"]) hits = memory.search("推荐个回测框架", user_id=user_id) for h in hits["results"]: print("检索到:", h["memory"], "score:", h["score"])

预期输出是提取到「用户做量化、用 Python、不要理论」三条记忆,检索「回测框架」时能命中「用 Python 写策略」这条。如果get_all返回空,说明提取层没工作——大概率是 LLM 的 base_url 或 Key 配错了。

Zep 的验证用它的 Python SDK:

from zep_cloud.client import Zep client = Zep(base_url="http://localhost:8000", api_key="...") client.memory.add(session_id="s1", messages=conversation) results = client.memory.search(session_id="s1", query="回测框架") print(results)

Zep 的坑在于 session_id 和 user_id 是两个概念。session 是一次对话,user 是跨会话的实体。如果你只传 session_id 不传 user_id,记忆不会跨会话保留。这是我在 Hermes 里踩过的坑——配了半天发现记忆只在单次会话内有效。

LangMem 的验证要看 store 里有没有数据:

items = store.search(("memories", user_id), query="回测框架") print(items)

如果 store 是 InMemoryStore,重启 Hermes 后search返回空是正常的,得换持久化后端。

5. 本篇常见报错排查

报错一:QdrantError: Collection not found: hermes_mem0

Qdrant 版本低于 1.7,或者 collection 没初始化。先docker rm -f qdrant删掉旧容器,docker pull qdrant/qdrant:latest重新拉,再起。Mem0 首次add时会自动建 collection,不用手动建。

报错二:openai.AuthenticationError: Incorrect API key

Mem0 的 config 里api_key没读到环境变量。TOML 里写${TAOTOKEN_API_KEY}只是占位,实际读取时要用os.path.expandvars展开,或者直接在 Python 里os.getenv后塞进 config dict。别把 Key 硬编码进 TOML。

报错三:Zep 检索返回空,但add没报错

检查add时有没有传user_id。Zep 的memory.add如果只传session_id,记忆只在该 session 内可见。跨会话检索必须传user_id,且search时也要传同一个user_id。

报错四:LangMem 的store.search返回空列表

InMemoryStore 不持久化,重启即丢。换成PostgresStore或RedisStore,并在 Hermes 启动时初始化 store 连接。另外 LangMem 的 namespace 要对齐——add和search用的 namespace tuple 必须一致,否则查不到。

报错五:记忆提取出英文,中文检索命中率低

Mem0 用 gpt-4o-mini 提取中文对话时,偶尔会把「我做量化的」抽成英文User works in quantitative finance。后续中文 query 的 embedding 和英文记忆的 embedding 距离远,检索不到。解决办法是换 gpt-4o 做提取,或者用本地 Qwen2.5 做提取模型。TaoToken 的模型对话页面可以快速测不同模型的提取效果。

6. 接入方式与后续调试

三个方案的配置骨架和验证动作都跑通之后,日常调试主要靠日志。Mem0 有memory.history()可以追溯每次 add 和 search 的调用记录,排查「为什么这次没命中」很管用。Zep 的 Graphiti 有内置的图谱可视化,Neo4j 的 browser 界面(localhost:7474)能直接看实体关系。LangMem 的调试最麻烦,得自己在适配层加日志。

如果你在配 Key 或接入过程中遇到报错,可以先到 TaoToken 的接入文档对照参数,或者用 API Keys 页面重新生成一个 Key 测试。模型对话页面适合快速验证提取模型的效果——同一个对话换不同模型跑一遍,看提取结果差异。长期跑编码类 Agent 的话,Coding Plan 的额度比按量计费更划算。

记忆方案的选择没有标准答案。Mem0 上手最快、社区最大,适合大多数通用 Agent;Zep 的时间图谱独一无二,适合需要追踪状态变化的场景;LangMem 只推荐给已经在用 LangGraph 的项目。在 Hermes 里,我的建议是先用 Mem0 跑通,验证记忆确实能提升体验之后,再根据需求决定要不要换 Zep。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询