AI 纪元 追踪人工智能最新进展,深度解读前沿技术

连续干跑7小时不崩,智能体长期记忆怎么写进向量库最省Token

针对长程Worker任务上下文超限难题,本文拆解冷热分层+状态机+向量库的三级外挂记忆架构。基于Mem0等开源框架,给出读写分离的代码片段与Token账本,帮助开发者在千万Token预算内扛住全周Agent运行。

0 次阅读 约 3398 字 7 分钟 AI 生成

7小时压测里那台机器到底烧掉多少Token

交付那台排障Agent的第二天下午,运维同事把监控截图甩到群里:一段连续任务跑了7小时14分,单次会话累计上下文达到了940万Token。

模型没崩,但账单先崩了。GPT-5.5的输入单价涨到每百万Token 3.5美元之后(《架构师发来警告,单靠堆Token已经带不动业务线了》一文里那张曲线已经爬到危险区),按这个体量倒推,一个中等规模的运维Agent每周光“喂历史”就要吃掉1700美元。问题不在模型,是在线记忆根本没分层——所有日志、报错、临时变量一股脑堆进上下文窗口,Prompt像滚雪球一样越来越胖。

更扎心的是:雪球里真正有信息量的内容不到8%。剩下的全是重复错误码、过期参数、回滚记录。它们不是“记忆”,是噪声。

这篇想做的事很具体:在不引入重型中间件的前提下,用Mem0这类轻量记忆层把Agent的上下文真正压回千万Token预算以内,并提供一份能直接拷进项目的冷热分层代码和成本核算模板。

别让上下文窗口背“记忆”的锅

先纠正一个常见误解:长期记忆 ≠ 把所有历史塞进Prompt。

上下文窗口(Context Window)只负责“眼前的会话”,状态机(State Machine)负责“任务进度”,向量库(Vector Database)负责“稳定知识”。三者混用,Agent就会丢步骤、召回废弃信息。这条边界在《别让Agent像鱼一样只有7秒记忆,2026年长短期记忆分层实操》里拆过,本文不重复。

现在的问题是:当一个排障Agent连续值守3天,它需要同时记住三类东西——

  • 热数据:当前会话状态、上一步工具返回值、下一步跳转条件。秒级读取、随时覆写。
  • 温数据:最近4小时的报错流、对话小结、相似案例索引。分钟级回收,靠向量库兜底。
  • 冷数据:项目文档、历史故障报告、用户偏好基线。天级刷新,几乎只读。

把这三类数据塞进同一个KV里,Token燃烧速度就是现在的样子。

为什么选Mem0做底座

2026年的开源记忆框架里,Mem0是少有把“写入即压缩”做成默认行为的。它通过semantic understanding做事件抽取,每次新增记忆前先做重要性打分与去重,再以分层摘要的形式持久化。这意味着同样的7小时会话,Mem0写入的Token量是线性增长,而原始上下文是二次方增长。

更关键的特性是它对工具调用有原生适配:返回的工具结果、错误码、参数快照会自动注册成“程序性记忆”,与对话内容分库存储。这部分在飞书文档《它》是拥有系统级权限、长期记忆的7×24小时数字员工里也提到,相似思路在企业级数字员工方案里已经落地。

落地建议:Mem0做语义层,对接Milvus或Qdrant做向量存储,热数据放Redis,三层之间通过一个抽象接口MemoryRouter统一调度。下面这段是能直接用的最小骨架——

from mem0 import Memory
from qdrant_client import QdrantClient
import redis

class MemoryRouter:
    def __init__(self):
        self.mem = Memory()  # Mem0 语义层
        self.vector = QdrantClient(":memory:")  # 向量兜底
        self.redis = redis.Redis()  # 热状态

    async def write(self, role, content, ts):
        # 热:当前对话最后5轮
        if ts - self.redis.get("session_start_ts") < 3600:
            self.redis.rpush(f"chat:{role}", content)
            return
        # 温:进 Mem0,自动摘要去重
        self.mem.add(content, user_id=role, metadata={"ttl": 4*3600})

    async def recall(self, role, query, top_k=5):
        # 先查 Mem0,再回退到向量库
        mem_hits = self.mem.search(query, user_id=role, limit=top_k)
        if len(mem_hits) >= top_k:
            return mem_hits
        return self.vector.search("cold_kb", query, top_k - len(mem_hits))

跑通这段之后,Prompt里的记忆拼装逻辑就可以从“全量拼接”变成“按需召回”:

async def build_prompt(agent_id, user_query):
    long_term = await memory.recall(agent_id, user_query, top_k=3)
    short_term = redis_client.lrange(f"chat:{agent_id}", -10, -1)
    profile = vector_client.get("cold_kb", f"profile:{agent_id}")
    return f"""
[用户画像] {profile}
[长期记忆] {[m['memory'] for m in long_term]}
[近期对话] {short_term}
[当前问题] {user_query}
"""

Token账本:怎么算才不亏

压测数据摆在那:7小时14分,单次会话940万Token。换算成钱是每天约50美元。改造后的目标是把“每次唤醒的历史记忆”压到3万Token以内。

按上面的MemoryRouter结构做一遍核算——

热数据:Redis中只保留最近10轮对话,平均每轮300 Token,单次唤醒占用 ≈ 3000 Token,永不过期。

温数据:Mem0做摘要后,每条记忆平均80 Token,每次召回3条 ≈ 240 Token。可控。

冷数据:通过向量库检索返回原文片段,平均每片段600 Token,召回数控制在2条以内 ≈ 1200 Token。

合计单次唤醒 ≈ 4500 Token,相比原方案的随手召回节省86%。按每天6000次会话估算,每周记忆调用成本可压到230美元,约为改造前的13%。

需要提醒的是,这个数字对应3B小模型路由+Mem0摘要的组合(参考《2026年企业部署AI Agent的成本控制和账单审计实操》里对FinOps的拆解)。如果Agent需要更高质量的语义抽取,可以把摘要模型从3B升级到7B,温数据那部分的Token开销几乎不变,但模型调用成本会上升,建议优先在路由层把“是否需要全量记忆”判准。

三个真实会踩的坑

第一,过期不删最致命。Mem0默认不清理冷数据,6个月后你会得到一个比模型还大的“记忆废料库”。务必在写入时把ttl写进metadata,再起个轻量级后台任务做按需GC。

第二,路由层不能省。直接让模型“自己决定要不要调记忆”会导致过度召回——每次对话都拉一遍完整历史,把上面算出的4500 Token膨胀到3万。路由最好交给一个3B SLM做意图分类和预算裁决,命中长程任务才放行Mem0访问。

第三,向量库别只存文本。排障Agent的记忆里,工具返回的JSON结构、错误码、调用链路时间戳远比自然语言重要。这些结构化字段最好单独走Key-Value索引(比如Redis Hash),向量库只承担相似度召回,两者解耦后,召回延迟能压到30ms以内。

把这三件事做扎实,加上Mem0+Milvus+Redis这套基线架构,撑起单Agent连续干跑一周的工程问题基本就能闭环。剩下要担心的,反而是模型本身的推理成本——但那是另一篇文章要算的账。

相关阅读