← 全部文章

Agent 的 messages 越滚越大?几个实用解法

上一篇我们写了 Agent 的本质是循环:问模型 → 跑工具 → 回喂。

跑起来你就会撞到一个隐藏的坑:

messages 数组越滚越大。

每轮对话,你都在往后 append:用户消息、助理消息、每个工具的结果……几十轮之后:

  • token 暴涨 → 又贵又慢;
  • 再久一点 → 超过上下文窗口,直接报错。

这不是小问题,是生产级 Agent 的头号工程问题。这篇讲清它、并给几个能落地的解法。

为什么一定会涨

system 提示
+ 用户消息
+ [助理消息 + 工具结果] × N   ← 每一轮都往后堆,永不回收

问题在于:你从不删除,只添加。 而工具结果往往是最大的那个(一次 cat 日志 100KB 很常见)。

6 个解法(从简单到进阶)

1. 别把大结果塞进 messages(收益最大,最常被忽略)

工具返回 100KB 日志?别原样回喂。 只回喂摘要 / 前 N 行,原始数据落盘,需要时再查。

原则:进入 messages 的每个字节,都要付 token 钱。

def run_tool_safely(out, limit=2000):
    if len(out) > limit:
        return out[:limit] + f"\n…(截断,共 {len(out)} 字符,已存文件)"
    return out

2. 滑窗裁剪

保留 system + 最近 K 轮,丢掉更早的。简单粗暴。

def trim(messages, keep=12):
    head = [m for m in messages if m.get("role") == "system"]
    return head + messages[-keep:]

3. 滚动摘要(推荐)

丢之前,先让模型把"要丢掉的历史"压成一段话,替换掉原始消息。窗口小,信息还在。

def compact(messages, keep=8):
    if len(messages) <= keep:
        return messages
    old, recent = messages[:-keep], messages[-keep:]
    summary = summarize(old)                 # 让模型把 old 总结成一段
    return [{"role": "system", "content": f"早前对话摘要:{summary}"}] + recent

4. 结构化记忆

从对话里抽出事实 / 偏好 / 结论,存成小文档或键值(如"用户在做 Jetson 边缘网关"),需要时注入。

记忆 ≠ 全量历史。 记住"要点",不是背下"全程"。

5. 检索式记忆(RAG)

历史存到外部(向量库 / 文件),用时按需检索相关片段,而不是全塞进上下文。

6. 子 Agent / 上下文隔离

让子 Agent 在自己的上下文里干脏活,只把结果返回给主 Agent。上下文不共享,就不会一起膨胀。

怎么选

你的场景推荐
一次性短任务滑窗裁剪就够
长对话滚动摘要
要记住用户偏好 / 事实结构化记忆
历史长且要精准回溯检索式记忆(RAG)
复杂多步任务子 Agent 隔离

为什么这对边缘特别重要

本地 / 边缘模型上下文更小(很多只有 8K~32K)。

在云端,messages 管理是优化;在边缘,它是能不能跑。

收尾

一句话记住:

上下文是预算,不是仓库。 每一轮都要问自己:这段历史,还值得留着吗?

能不留就不留,能压缩就压缩,能外置就外置。


💬 你的 Agent 是怎么管上下文 / 记忆的?评论区聊聊。 🛠️ 需要嵌入式 / 边缘 AI / Agent 定制与咨询?见 关于页。

评论 0

还没有评论,来抢沙发~

登录 登录后即可参与评论