Agent 上下文怎么去重?3 种压缩策略实测对比

先给结论:我用 800 条消息(33,690 字符,其中 300 条完全重复、100 条只差大小写/空格、100 条消息内部有重复句)实测三种去重策略——精确去重只降到原来的 66.8%,归一化去重降到 54.8%,分句去重直接压到 33.2%,而且三者都完整保留了 300 条唯一信息,耗时分别只有 0.06ms / 1.04ms / 1.97ms。去重不是越狠越好,而是要在不丢信息的前提下把重复拿掉。

为什么 Agent 需要上下文去重

Agent 一轮任务会不断把工具结果、历史消息、日志片段拼进上下文。常见浪费有三类:

  1. 完全重复:同一段工具输出被多次追加;
  2. 近似重复:只差大小写、空格、标点;
  3. 消息内部重复:一条长消息里同一句出现多遍。

它们不会让回答更准,只会推高 token 成本、拉长延迟,还可能让模型被重复内容带偏。

三种策略的最小实现

# 1) 精确去重:整条消息完全一致才删
seen = set(); out = []
for m in msgs:
    if m in seen: continue
    seen.add(m); out.append(m)

# 2) 归一化去重:先统一大小写/空白/标点,再比
def norm(s): return re.sub(r"\s+", "", s).lower().strip("。. ")
seen = set(); out = []
for m in msgs:
    k = norm(m)
    if k in seen: continue
    seen.add(k); out.append(m)

# 3) 分句去重:把消息拆成句子,按句去重后再拼回
seen = set(); out = []
for m in msgs:
    parts = [p for p in re.split(r"[。!?]", m) if p.strip()]
    keep = [p for p in parts if norm(p) not in seen]
    if not keep: continue
    for p in keep: seen.add(norm(p))
    out.append("。".join(keep) + "。")

实测数据

环境:Windows + Python 3.15.2,输入 800 条消息 / 33,690 字符;唯一信息 300 条。

策略保留条数移除条数保留字符字符占比唯一信息保留耗时
精确去重50030022,52066.8%300/3000.06ms
归一化去重40040018,47054.8%300/3001.04ms
分句去重30050011,17033.2%300/3001.97ms

三个关键结论:

  1. 精确去重只能处理“一模一样”:300 条完全重复被删掉后,仍有 66.8% 的文本留在上下文里。
  2. 归一化去重多抓一类:大小写/空格变体也被识别,字符占比降到 54.8%,代价是 1ms 级匹配。
  3. 分句去重收益最大:连消息内部的重复句也能去掉,字符占比压到 33.2%,唯一信息一条没丢;耗时不到 2ms。

注意:三种策略的「唯一信息保留」都是 300/300,说明在这份样本上没有误删;但真实场景里归一化/分句去重可能误合并语义不同的短句,需要配合白名单或人工抽检。

怎么选

场景建议
只是防止工具输出被重复追加精确去重足够,最便宜
多来源拼接、格式不统一归一化去重
长消息里重复句多、上下文吃紧分句去重
语义级重复(改写过)需要 embedding/相似度,本文未覆盖

实践建议:先精确去重,再归一化,最后按预算决定是否分句去重;三层可叠加,成本从低到高。

怎么复现

单个脚本、零第三方依赖:

python -X utf8 context_dedupe.py

脚本会构造完全重复/近似重复/内部重复三类样本,输出三种策略的保留条数、字符占比、唯一信息保留数与耗时,可直接改样本规模对比。

结论与下一步

  • 上下文去重的收益看字符占比,不是看“删了多少条”。
  • 分句去重在这份样本上把上下文压到三分之一,且 2ms 内完成,适合上下文吃紧的 Agent。
  • 下一步可以做的:加语义相似度去重;对代码/日志块设白名单不拆句;把去重前后的 token 估算写进日志,持续观察收益。

去重的目标不是“越短越好”,而是同样的信息,用更少的上下文表达。

Logo

更多推荐