当前位置: 首页 > news >正文

Zero-Mem:零Token消耗的LLM Agent记忆管理新方案

1. 核心能力速览

这次我们来看一个很有意思的 LLM Agent 方向,项目名称叫Zero-Mem: Zero-Token Memory Operations for LLM Agents。一句话概括:它想解决大模型 Agent 记忆功能里最痛的一个问题——读写记忆时消耗大量 token 的问题

在 Agent 场景中,记忆不是可选项。多轮工具调用、跨会话任务、长对话管理,都需要把历史信息存下来、再在合适的时机读回来。传统做法是让 LLM 在推理时把记忆内容作为上下文的一部分拼接进 prompt,于是每读写一次记忆,就要为记忆本身付出 token 成本。一次两次不明显,Agent 任务一旦密集起来,token 消耗会非常快,延迟和费用同步上升。

Zero-Mem 的思路很直接:能不能让记忆操作不占用 token 预算?从项目给出的方向来看,它把记忆的存储、更新和检索从 LLM 的 token 上下文里剥离出来,用额外的记忆管理层完成,并且设计成与 LLM 无关的记忆操作接口,让 LLM 只需要通过特定指令触发记忆能力,而不需要把记忆内容反复搬运进上下文。

能力项说明
项目定位LLM Agent 记忆管理机制,Zero-Token 记忆读写操作
核心特点降低记忆操作 token 消耗、减少上下文冗余、支持结构化记忆
适用对象研究 LLM Agent 记忆机制、多轮对话、任务型 Agent 的开发者
记忆类型长期记忆、短期记忆、会话摘要、实体关系记忆(按常见 Agent 记忆框架判断)
启动方式需要以代码库/论文复现方式运行,无 WebUI(按项目性质判断)
硬件门槛无独立模型推理部分,主要依赖宿主 LLM 的推理能力
是否支持 CPU与宿主 LLM 所在环境一致
是否支持 API可封装为 Agent 记忆服务接口
是否支持批量任务可支持,记忆操作可设计为批处理调用
适合场景Agent 长任务、多轮工具调用、会话历史管理、低成本记忆读写

从项目名称看,零 token 记忆操作是通过把记忆内容“外置”到独立存储层,而不是让 LLM 每次重新生成或重新读取整段历史。这样做如果能落地,收益非常明确:Agent 的上下文窗口可以更多地留给工具调用结果和当前任务,而不是被历史记录占用。

2. 适用场景与使用边界

2.1 适合谁

  • 在 Agent 框架里维护多轮对话状态的开发者。你不再需要自己手工拼接长长的历史消息列表。
  • 需要给 Agent 加长期记忆能力的开发者。比如让 Agent 记住用户偏好、记住任务进度、跨会话保持状态。
  • 关注 token 成本的团队。Agent 记忆操作如果占用大量 token,在规模化运行时会显著拉高成本。
  • 研究 RAG、Agent 记忆、prompt 压缩方向的算法工程师。Zero-Mem 提供了一种不把记忆塞进上下文的新思路。

2.2 能解决什么问题

  • 上下文膨胀:Agent 每轮对话都把历史记录塞进 prompt,Zero-Mem 可以降低这部分开销。
  • 记忆更新困难:传统做法要在上下文里写一整段更新后的记忆文本,Zero-Mem 通过结构化存储来避免重复搬运。
  • 记忆污染:记忆内容混在对话历史里,容易被后续指令干扰,独立记忆层可以避免这个问题。

2.3 不适合什么场景

  • 需要深入语义理解的任务,比如 Agent 要根据记忆内容进行复杂推理,这类场景记忆仍然需要进入 LLM 上下文。
  • 对解释性要求极高的场景,例如审计要求能看到 LLM 推理时使用的完整记忆内容。
  • 记忆内容本身很小、上下文窗口非常宽裕的场景,使用 Zero-Mem 带来的收益不明显。

2.4 版权、隐私与安全边界

记忆层会存储用户对话、业务数据甚至敏感信息。使用 Zero-Mem 时需要注意:

  • 记忆数据必须按隐私规范处理,必要时加密存储。
  • 涉及个人信息的记忆内容需要在用户授权范围内使用,不能跨场景滥用。
  • 如果 Agent 部署在公共服务中,要避免把隐私信息直接写入外置记忆库而不做脱敏。
  • 记忆的删除不能只做应用层删除,要考虑到底层存储是否已经被清理。

3. 环境准备与前置条件

从目前公开资料来看,Zero-Mem 还处于研究/早期发布阶段,大概率以论文仓库或代码库的形式提供,而不是成熟的 WebUI 项目。因此环境准备主要围绕复现实验和接入 Agent 框架来展开。

3.1 通用环境清单

环境项说明
操作系统Linux 首选,macOS / Windows 也可以,取决于宿主 LLM 环境
Python建议 3.10 及以上
LLM 服务本地 Ollama / vLLM / 云 API 均可
Agent 框架LangChain、LlamaIndex、AutoGen 或自建 Agent 调度环境
存储层SQLite、Redis、向量数据库均可(取决于记忆类型)
依赖管理pip / conda / poetry
磁盘空间取决于 LLM 模型和记忆库大小,一般预留 10GB 以上

3.2 LLM 环境准备

无论你是在本地跑一个小模型,还是接入云端 API,先把 LLM 服务跑通是关键一步。常见的本地启动方式:

# 使用 Ollama 启动本地 LLM 服务 ollama pull qwen2.5:7b ollama serve
# 使用 vLLM 启动 OpenAI 兼容服务 python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --port 8000

启动成功后,用 curl 验证服务:

curl http://127.0.0.1:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [{"role": "user", "content": "你好"}] }'

这一步的目的是确认 LLM 服务可访问。Zero-Mem 本身不负责推理,它只负责记忆的读写。

3.3 记忆存储层准备

Zero-Mem 如果使用外置记忆,底层存储可以选择:

  • SQLite:轻量,适合单机测试。
  • Redis:适合高频读写、状态缓存。
  • 向量数据库:适合语义检索类型的记忆,比如 milvus、chromadb、qdrant。

建议先用 SQLite 或内存存储跑通逻辑,再根据实际需要更换存储后端。

# 使用 sqlite3 作为记忆存储的通用示例 import sqlite3 conn = sqlite3.connect("agent_memory.db") cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS memory ( id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT UNIQUE, value TEXT, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """) conn.commit()

4. 部署启动与记忆操作流程

Zero-Mem 具体的使用方式需要以项目 README 为准。在没有完整源码前,可以按下面的通用流程把它接入 Agent 记忆框架,理解它的工作方式。

4.1 总体架构

用户输入 │ ▼ Agent 调度层 │ ├──► LLM 推理(上下文只保留当前任务和工具结果) │ └──► Zero-Mem 记忆层 ├── 写入记忆(不消耗 token) ├── 读取记忆(按需返回精简结果) └── 更新记忆(覆盖或合并旧记忆)

关键差异在于:传统 Agent 会把“历史对话 + 记忆摘要”全部拼进 prompt,Zero-Mem 模式下,LLM 的上下文里几乎只有当前轮次的任务信息,记忆通过外部操作完成。

4.2 记忆写入示例

# Zero-Mem 风格的记忆写入伪代码 def write_memory(key: str, value: str, overwrite: bool = True): """ 写入记忆到外部存储层。 这个过程不向 LLM 上下文添加任何 token。 """ if overwrite: cursor.execute( "INSERT INTO memory (key, value) VALUES (?, ?) " "ON CONFLICT(key) DO UPDATE SET value = excluded.value", (key, value) ) else: cursor.execute( "INSERT OR IGNORE INTO memory (key, value) VALUES (?, ?)", (key, value) ) conn.commit()

写记忆时,LLM 只需要生成一次“保存这个信息”的意图,后续的实际存储操作完全由代码层完成,不需要 LLM 再次生成或读取完整的记忆文本。

4.3 记忆读取示例

# Zero-Mem 风格的记忆读取伪代码 def read_memory(key: str) -> str | None: """ 从外部存储读取记忆。 读取结果只返回关键信息,不携带无关上下文。 """ cursor.execute("SELECT value FROM memory WHERE key = ?", (key,)) row = cursor.fetchone() return row[0] if row else None

读取时,返回给 LLM 的内容只包含与当前任务相关的记忆条目,而不是整段历史记录。这也是 Zero-Token 思路的落地表现。

4.4 Agent 调用流程整合

# 把 Zero-Mem 接入 Agent 工作流的通用示例 class AgentWithMemory: def __init__(self, llm_client, memory_store): self.llm = llm_client self.memory_store = memory_store def run(self, user_input: str) -> str: # 1. 从记忆库读取相关的记忆条目 relevant_memory = self.memory_store.read(user_input) # 2. 构建 prompt,只拼接当前输入和必要的记忆 prompt = self.build_prompt(user_input, relevant_memory) # 3. 调用 LLM response = self.llm.chat(prompt) # 4. 解析 LLM 是否有新的记忆保存需求 key, value = self.parse_memory_intent(response) if key: self.memory_store.write(key, value) return response def build_prompt(self, user_input, memory): # 记忆压缩后只占少量空间 if memory: return f"[相关记忆] {memory}\n[用户] {user_input}" return f"[用户] {user_input}"

这里需要注意:如果是真正实现 Zero-Token,连[相关记忆] {memory}这段内容也不应该出现在 prompt 里,记忆检索的结果应该交给外部逻辑或工具函数调度使用,而不是直接喂给 LLM。具体实现视项目最终设计而定。

5. 功能测试与效果验证

拿到项目之后,建议按下面的维度做功能测试,重点观察 token 消耗变化和记忆准确性。

5.1 基础记忆写入测试

测试项操作预期结果
记忆写入让 Agent 保存一条用户信息记忆库中存在对应 key-value
记忆覆盖再次写入相同 key 的新值旧值被替换,不产生重复记忆
记忆唯一性多次写入同一 key数据库没有重复条目
write_memory("user_preference", "喜欢简洁的回答风格") write_memory("user_preference", "喜欢详细的技术讲解") print(read_memory("user_preference")) # 预期输出:喜欢详细的技术讲解

5.2 多轮会话记忆测试

执行一个 10 轮以上的多轮对话,每轮都让 Agent 产生可记忆的信息,然后查看:

  • 经过 10 轮后,LLM 请求中的历史 token 占比是否明显低于传统方式。
  • 记忆读取是否能在后续轮次准确命中。
  • 记忆写入是否影响正常回答延迟。

判断标准:同样的任务,对比传统把历史记录全部塞进 prompt 的做法,Zero-Mem 方式下每轮请求 token 数应该显著降低,且回答准确率不下降。

5.3 token 消耗对比测试

在接入 Zero-Mem 前后,分别记录相同任务集的 token 消耗:

# 统计一次 Agent 运行的 token 消耗示例 def count_tokens(messages): total = 0 for message in messages: total += len(message.get("content", "")) return total

用同一组任务分别跑传统模式和 Zero-Mem 模式,记录每次调用的输入 token 数量,最后对比平均值。这是验证 Zero-Mem 效果最直接的手段。

5.4 记忆检索准确率测试

准备一组记忆条目,包含相似但不完全相同的语义信息:

  • 比如记忆 A:“用户喜欢用 Python 写数据处理”
  • 记忆 B:“用户更喜欢 Rust 开发 CLI 工具”

然后分别查询“用户喜欢什么语言做数据工作”和“用户最近学什么语言”,检查返回的记忆条目是否准确。

5.5 长任务稳定性测试

设计一个包含 20 步工具调用的复杂任务,让 Agent 在每一步之间都需要读写记忆。重点观察:

  • 长任务是否出现记忆丢失。
  • 是否出现记忆串扰(前一任务的记忆被错误加载到后一任务)。
  • 记忆操作在长时间运行后是否有性能下降。

6. 接口 API 与批量任务

Zero-Mem 作为一个记忆管理模块,如果封装成服务,可以给 Agent 团队提供一个统一的内存服务接口。

6.1 记忆服务接口设计建议

接口方法参数返回
/memory/writePOSTkey, value, namespace写入结果
/memory/readGETkey, namespace记忆内容
/memory/deleteDELETEkey, namespace删除结果
/memory/searchPOSTquery, namespace匹配记忆列表
# 记忆服务 API 示例(FastAPI) from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class MemoryItem(BaseModel): key: str value: str namespace: str = "default" class SearchQuery(BaseModel): query: str namespace: str = "default" @app.post("/memory/write") def write_memory(item: MemoryItem): # 写入逻辑 return {"status": "ok", "key": item.key} @app.get("/memory/read") def read_memory(key: str, namespace: str = "default"): # 读取逻辑 return {"key": key, "value": read_from_store(namespace, key)} @app.post("/memory/search") def search_memory(query: SearchQuery): # 语义搜索逻辑 return {"results": search_from_store(query.query, query.namespace)}

6.2 curl 调用示例

curl -X POST http://127.0.0.1:8610/memory/write \ -H "Content-Type: application/json" \ -d '{ "key": "user_goal", "value": "完成数据分析报告", "namespace": "project_x" }'
curl -X GET "http://127.0.0.1:8610/memory/read?key=user_goal&namespace=project_x"

6.3 批量记忆写入

批量导入历史会话数据时,可以直接调用批量接口:

import requests items = [ {"key": "user_1_pref", "value": "偏好表格输出"}, {"key": "user_2_pref", "value": "偏好代码示例"}, {"key": "project_deadline", "value": "2025-04-30"}, ] for item in items: response = requests.post( "http://127.0.0.1:8610/memory/write", json={**item, "namespace": "batch_import"} ) print(response.status_code)

批量写入建议加一个进度日志,方便中途失败时断点重跑。

# 批量导入日志示例 2025-01-20 10:00:01 [INFO] 写入 user_1_pref 成功 2025-01-20 10:00:02 [ERROR] 写入 user_2_pref 失败,连接超时 2025-01-20 10:00:03 [INFO] 写入 project_deadline 成功

对于失败的条目,记录到单独的错误文件,重试时只处理失败的 key。

7. 资源占用与性能观察

Zero-Mem 本身不做 LLM 推理,所以它的资源占用主要来自三个部分:

  • LLM 服务本身的显存/CPU/内存占用。
  • 记忆存储层的内存和磁盘占用。
  • Agent 调度层的进程开销。

7.1 观察指标

指标观察方式
LLM 显存占用nvidia-smi
记忆服务内存ps aux | grep memory
存储层占用df -h / sqlite 数据库文件大小
请求耗时API 调用时间统计
token 消耗LLM 服务日志返回的 usage 字段

以本地 7B 模型为例,显存占用通常比 13B 模型低很多,具体数值取决于量化方式和推理框架。如果你用的是 Ollama 默认 4bit 量化,通常比 16bit 占用低一倍左右。但这些数值请以本机实际测试为准,不同驱动、不同 CUDA 版本都会影响最终结果。

7.2 CPU 推理与 GPU 推理的差异

  • GPU 推理:延迟低,显存占用高,适合交互式 Agent 场景。
  • CPU 推理:无显存压力,延迟高,适合测试和离线批量任务。

Zero-Mem 的记忆读写操作本身不受 CPU/GPU 影响,但记忆检索如果是语义搜索,向量检索在 CPU 上也能跑,速度取决于数据量。

7.3 性能瓶颈分析

如果 Agent 任务响应变慢,优先排查:

  1. LLM 推理耗时是否增加。
  2. 记忆检索是否超时。
  3. 记忆存储层是否有锁冲突。
  4. 上下文中的记忆信息是否过多。

7.4 降低资源占用建议

  • 使用量化模型,减少显存占用。
  • 记忆存储使用索引,加速查询。
  • 定期清理过期记忆。
  • 将记忆服务与 LLM 服务拆开部署,方便独立扩容。

8. 常见问题与排查方法

问题现象可能原因排查方式解决方案
Agent 回答时记忆不生效记忆 key 不匹配检查记忆库中 key 和读取 key 是否一致统一命名规范,增加 key 规范化处理
记忆写入了,但读不到写入失败没有报错查看写入返回状态增加写入确认机制
token 消耗没有下降记忆仍然被拼接进 prompt检查 prompt 构建逻辑把记忆读取改为外部逻辑调用
显存不足模型量化位数过高nvidia-smi 查看显存占用使用更低精度量化
API 调用超时记忆服务未启动或网络不通curl 测试记忆服务检查服务状态和端口
批量任务卡住存储层锁冲突查看数据库锁状态使用队列串行写入
记忆内容串扰namespace 使用混乱检查调用时 namespace 参数强制每个任务使用独立命名空间
长任务记忆丢失记忆更新逻辑有误查看日志中写入记录增加关键步骤写入断点
启动后服务立即退出依赖缺失或端口占用查看启动日志安装依赖或更换端口
Agent 回答质量下降记忆内容不完整或缺失检查记忆库内容补充完整记忆或调整检索策略

8.1 依赖安装失败

pip install -r requirements.txt

如果网络环境安装失败,可以换源:

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

8.2 CUDA 版本问题

本地跑 LLM 时,CUDA 版本和 PyTorch 版本不匹配是常见问题。

python -c "import torch; print(torch.cuda.is_available())"

如果输出False,需要重新安装与 CUDA 匹配的 PyTorch 版本。

8.3 端口冲突

lsof -i :8610

如果有进程占用,可以换端口:

uvicorn memory_server:app --host 127.0.0.1 --port 8611

8.4 进程残留

杀掉残留的 Python 进程需要谨慎,不要误杀其他服务:

ps aux | grep memory_server kill <PID>

9. 最佳实践与使用建议

9.1 第一次先小规模验证

不要一上来就跑大规模批量任务。先写几个测试 key,验证读写正常,再扩展数据量。

# 冒烟测试示例 assert read_memory("user_preference") == "喜欢详细的技术讲解" assert read_memory("non_exist_key") is None print("冒烟测试通过")

9.2 保留一套最小可运行配置

把以下内容固定下来,方便重复实验:

  • LLM 模型名称和启动命令。
  • 记忆库路径。
  • API 端口和访问地址。
  • 测试任务集。

建议写成一个config.yaml

llm: provider: openai_compatible base_url: http://127.0.0.1:8000/v1 model: Qwen/Qwen2.5-7B-Instruct memory: backend: sqlite database: ./agent_memory.db namespace: agent_test server: host: 127.0.0.1 port: 8610

9.3 模型文件、输入素材、输出结果分目录管理

project/ ├── config.yaml ├── models/ # 模型文件 ├── inputs/ # 测试输入 ├── outputs/ # 实验结果 ├── memory/ │ └── agent_memory.db └── logs/ └── agent.log

9.4 批量任务要加日志和失败重试

import time from loguru import logger def batch_write_with_retry(items, max_retries=3): for item in items: for attempt in range(max_retries): try: write_memory(item["key"], item["value"]) logger.info(f"写入成功: {item['key']}") break except Exception as e: logger.warning(f"第 {attempt+1} 次写入失败: {e}") time.sleep(1) else: logger.error(f"写入失败,重试耗尽: {item['key']}")

9.5 接口服务要限制访问范围

如果记忆服务部署在服务器上,不要直接暴露在公网:

# 只监听本地 uvicorn memory_server:app --host 127.0.0.1 --port 8610 # 如果必须远程访问,建议加 Token 鉴权
# 增加简单的 API Token 鉴权 from fastapi import Header, HTTPException API_TOKEN = "your-secret-token" def verify_token(authorization: str = Header(None)): if authorization != f"Bearer {API_TOKEN}": raise HTTPException(status_code=401, detail="Invalid token")

9.6 记忆内容要设计好 key 命名规范

推荐格式:

{namespace}:{entity}:{attribute}

示例:

  • project_x:user:preference
  • project_x:task:deadline
  • project_x:file:location

这样可以在不增加复杂结构的情况下,快速定位和过滤记忆。

9.7 涉及人脸、声音、版权素材时必须确认授权

虽然 Zero-Mem 不是人脸/声音项目,但 Agent 可能会记录包含敏感信息的交互内容。如果 Agent 被用在涉及肖像、声音、版权数据的场景,要确保:

  • 数据来源合法。
  • 用户知情同意。
  • 存储和传输加密。
  • 支持删除和遗忘。

9.8 发布或商用前要做效果复核

Agent 的记忆内容如果被错误读取,可能导致回答偏差。发布前需要做一个全流程的测试用例复核,覆盖高频场景和异常场景。

10. 总结与下一步

Zero-Mem 这个方向解决的是 Agent 记忆操作中的 token 浪费问题。传统做法把记忆越攒越多、每次都要重读,Zero-Mem 的思路是把记忆操作从 token 上下文中剥离出来,用外部存储和调度逻辑实现记忆读写。最值得尝试的点是:在同一个 Agent 任务集上,对比传统记忆拼接与 Zero-Token 记忆操作的 token 消耗差异,这个数字会直接说明问题。

最先应该验证的功能是基础记忆写入和读取。先确认记忆能存、能取、能覆盖,然后观察 token 变化,再进入长任务稳定性测试。

最容易踩的坑有两个:

  1. 记忆 key 命名不统一。写的时候用user_preference,读的时候用UserPreference,结果永远读不到。
  2. 记忆还是被塞进了 prompt。表面上是 Zero-Mem 架构,实际构建 prompt 时又把历史记忆全部拼接回去了,token 消耗没有变化。

后续可以继续扩展的方向:

  • 用向量检索代替精确 key 匹配,让 Agent 记忆支持语义查询。
  • 增加记忆过期和遗忘机制,避免存储无限膨胀。
  • 结合 RAG,让 Agent 能从外部知识库读取事实信息。
  • 设计更完善的记忆合并策略,同类记忆自动去重更新。

建议收藏备用。如果你也在做 LLM Agent 的记忆管理,欢迎按本文的测试流程跑一遍,用数据判断 Zero-Mem 值不值得引入你的项目。

http://www.cnnetsun.cn/news/4257933.html

相关文章:

  • 面向非技术团队的 AI 落地实践:从试点、权限到反馈闭环的全流程指南
  • DeepSeek API涨价应对指南:成本估算与工程优化策略
  • 世界模型实战:从概念到千人联机状态同步原型
  • Lustre云上实践:ZFS OST基于对象存储的架构与部署
  • BERT文本情感分析实战:从原理到工业级部署
  • AI智能体产品化:从核心概念到Dify实战的工程指南
  • AI应用出海:从功能Demo到稳定留存的产品化之路
  • 电工杯数学建模B题解析:从工业优化到MILP模型实战
  • C++模板编程核心:函数模板与类模板的区别及实战应用
  • 提示词驱动软件:用自然语言改变程序行为的设计与实现
  • Matplotlib直方图实战:从数据分布到建模应用
  • 本地模型建筑足迹提取横向对比:YOLOv8与SAM实战指南
  • 希望存在的软件:如何把工作流缺口变成可执行需求
  • Lefts:用声明式DSL简化创意机器学习模型构建与实验
  • 电子信息与通信工程保研考研复试:联系导师策略与邮件撰写全指南
  • Run With Zombies:用浏览器GPS定位实现真实世界的僵尸追逐游戏
  • 感知先行:利用反事实盲区实现自包含视觉蒸馏
  • Autoformer时间序列预测:周期与趋势显式建模实战
  • 超市缺货检测数据集实战指南:从标注校验到零售AI落地
  • MATLAB GUI平行泊车仿真:从车辆运动学建模到路径规划控制
  • C++笔试核心考点解析:内存管理、STL与多线程实战
  • 2027地图学考研全套复习资料|现代地图学教程+真汇编+专项习+高分笔记(电子版)
  • 单片机智能物料分拣系统设计:从传感器到状态机的嵌入式综合实践
  • 750 token/秒成为常态,AI开发者的Token工程实战指南
  • YOLOv5车牌识别实战:从数据集标注到模型部署的完整指南
  • 本地部署RWKV:AI长篇小说生成与写作实战指南
  • 数学建模四大核心模型:优化、分类、评价与预测的MATLAB实战指南
  • LSTM图像描述实战:从CNN特征提取到Beam Search解码全流程解析
  • LatticeDB:嵌入式属性图数据库,融合向量与全文索引,简化混合检索架构
  • C++ std::addressof:获取对象真实地址的标准方法