超长上下文怎么塞进Agent:滑动窗口配要点压缩,token省了一半还没丢关键信息
做长对话的智能体,最先撞墙的就是上下文。聊到二三十轮,token蹭蹭涨,要么超模型窗口直接报错,要么账单看着肉疼。我折腾了大半个月,最后落到"滑动窗口+要点压缩"这套组合,实测token砍了快一半,关键信息基本没丢。记一下过程。
一开始走的弯路
我最早是粗暴截断——只留最近N轮,前面的全扔。结果用户聊着聊着,智能体就"失忆"了:开头说好的需求,到后面全忘。客诉直接来了。
后来改成全量塞,每轮把历史全带上。信息是不丢了,但一个稍微长点的会话,单次请求两万多token,慢且贵。
现在的做法:分层
我把上下文切成三块,分别处理。
近期窗口(原样保留)
最近的5到6轮对话,一个字不动,全须全尾带上。这部分最影响当前回答的连贯性,不能压。
中期记忆(压成要点)
再往前的对话,不直接扔,而是隔一段就触发一次压缩:让模型把这几轮聊了啥总结成几条要点。比如十轮关于"用户要订一张6月飞东京的机票,预算3000,偏好夜间航班"的来回,压完就剩三四行结论。原始一千多token,压完一百出头。
长期事实(抽出来单存)
像用户的偏好、确认过的关键决定,我单独抽成结构化的fact存到外面(就一个简单的KV),每轮按需取,不混在对话流里。
压缩的触发时机
不是每轮都压——那太费。我设的是:当历史token累计超过一个阈值(我设的4000),就把"近期窗口之前"的内容打包压一次,压完替换掉原文。相当于滑动窗口往前滚的时候,被滚出去的内容先过一道压缩再归档。
if history_tokens > 4000:
old = messages[:-6] # 近期6轮之外
summary = compress(old) # 让模型总结成要点
messages = [summary] + messages[-6:]
一个没解决干净的坑
压缩本身也要调一次模型,是有成本和延迟的。我测下来,压一次大概多花半秒、几百token,但换来后续每轮都省,整体还是赚。另外压缩偶尔会丢掉一些当时看着不重要、后面又被问起的细节——比如用户随口提过的一个航司黑名单。这个我还没特别好的解法,目前是把"用户明确表达的排除项"强行进长期事实那一层,绕过压缩。
搭这套我没自己写调度,用了个零代码配智能体的平台,窗口、压缩节点、记忆存储都是拖出来连的,改阈值就是改个数字。
模型这层提一句:压缩和对话都得调大模型,我用讯飞的现成模型服务(MaaS)接的API,不用操心模型部署和算力,调用直接走。
—
你们的长上下文是怎么扛的?有没有上向量记忆做检索式召回的?我感觉那套对"很久以前提过一嘴"的场景更稳,但工程复杂度高,纠结要不要上,评论区给点意见。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)