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连续干跑一周的工程问题基本就能闭环。剩下要担心的,反而是模型本身的推理成本——但那是另一篇文章要算的账。