ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

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 每轮对话都把历史记录塞进 promptZero-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 会把“历史对话 记忆摘要”全部拼进 promptZero-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?keyuser_goalnamespaceproject_x6.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 任务响应变慢优先排查LLM 推理耗时是否增加。记忆检索是否超时。记忆存储层是否有锁冲突。上下文中的记忆信息是否过多。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/simple8.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 86118.4 进程残留杀掉残留的 Python 进程需要谨慎不要误杀其他服务ps aux | grep memory_server kill PID9. 最佳实践与使用建议9.1 第一次先小规模验证不要一上来就跑大规模批量任务。先写几个测试 key验证读写正常再扩展数据量。# 冒烟测试示例 assert read_memory(user_preference) 喜欢详细的技术讲解 assert read_memory(non_exist_key) is None print(冒烟测试通过)9.2 保留一套最小可运行配置把以下内容固定下来方便重复实验LLM 模型名称和启动命令。记忆库路径。API 端口和访问地址。测试任务集。建议写成一个config.yamlllm: 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: 86109.3 模型文件、输入素材、输出结果分目录管理project/ ├── config.yaml ├── models/ # 模型文件 ├── inputs/ # 测试输入 ├── outputs/ # 实验结果 ├── memory/ │ └── agent_memory.db └── logs/ └── agent.log9.4 批量任务要加日志和失败重试import time from loguru import logger def batch_write_with_retry(items, max_retries3): 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第 {attempt1} 次写入失败: {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 ! fBearer {API_TOKEN}: raise HTTPException(status_code401, detailInvalid token)9.6 记忆内容要设计好 key 命名规范推荐格式{namespace}:{entity}:{attribute}示例project_x:user:preferenceproject_x:task:deadlineproject_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 变化再进入长任务稳定性测试。最容易踩的坑有两个记忆 key 命名不统一。写的时候用user_preference读的时候用UserPreference结果永远读不到。记忆还是被塞进了 prompt。表面上是 Zero-Mem 架构实际构建 prompt 时又把历史记忆全部拼接回去了token 消耗没有变化。后续可以继续扩展的方向用向量检索代替精确 key 匹配让 Agent 记忆支持语义查询。增加记忆过期和遗忘机制避免存储无限膨胀。结合 RAG让 Agent 能从外部知识库读取事实信息。设计更完善的记忆合并策略同类记忆自动去重更新。建议收藏备用。如果你也在做 LLM Agent 的记忆管理欢迎按本文的测试流程跑一遍用数据判断 Zero-Mem 值不值得引入你的项目。
返回列表