agent 开发中,压缩历史信息常用策略

在 Agent 开发中,**历史信息压缩(History Compression)**是一个核心问题,因为:

  1. Context Window 有限:即使是 GPT-4 Turbo(128K)或 Claude 3(200K),也无法无限容纳历史对话。
  2. 成本高昂:每次请求都携带完整历史会导致 Token 消耗指数级增长。
  3. 噪音干扰:冗长的历史会稀释关键信息,降低 Agent 的决策质量。

以下是工业界和学术界常用的历史信息压缩策略,从简单到复杂分为 5 个层级:


一、基础策略:截断与采样 (Truncation & Sampling)

适用于简单场景,不需要额外模型。

1. 滑动窗口 (Sliding Window)

  • 原理:只保留最近的 N 轮对话。

  • 实现

    python 复制代码
    def sliding_window(history, max_turns=5):
        return history[-max_turns:]
  • 优点:简单高效。

  • 缺点:丢失早期关键信息(如用户在第1轮说的任务目标)。

2. 首尾保留 (Head-Tail Retention)

  • 原理:保留最开始的 K 轮(任务描述)+ 最近的 M 轮(当前上下文)。

  • 实现

    python 复制代码
    def head_tail_retention(history, head=2, tail=3):
        if len(history) <= head + tail:
            return history
        return history[:head] + history[-tail:]
  • 优点:保证任务目标不丢失。

  • 缺点:中间的推理链条可能丢失。

3. 关键轮次采样 (Key Turn Sampling)

  • 原理:只保留包含关键信息的轮次(如用户提问、工具调用结果、决策点)。

  • 实现 :基于规则过滤。

    python 复制代码
    def filter_key_turns(history):
        key_turns = []
        for turn in history:
            if turn['role'] == 'user':  # 用户输入
                key_turns.append(turn)
            elif 'tool_call' in turn:  # 工具调用
                key_turns.append(turn)
            elif turn.get('is_decision', False):  # 标记为决策点
                key_turns.append(turn)
        return key_turns

二、语义压缩:摘要与重写 (Summarization)

使用 LLM 对历史进行语义压缩,保留核心信息。

1. 递归摘要 (Recursive Summarization)

  • 原理:每隔 N 轮,用 LLM 将这 N 轮对话总结成一段话。

  • 实现

    python 复制代码
    def recursive_summarize(history, llm, chunk_size=5):
        if len(history) <= chunk_size:
            return history
        
        # 对前 chunk_size 轮进行摘要
        chunk = history[:chunk_size]
        summary_prompt = f"请将以下对话总结为一段话:\n{chunk}"
        summary = llm.generate(summary_prompt)
        
        # 用摘要替换原始对话
        compressed = [{"role": "system", "content": f"历史摘要: {summary}"}]
        compressed.extend(history[chunk_size:])
        
        return recursive_summarize(compressed, llm, chunk_size)
  • 优点:大幅减少 Token 数。

  • 缺点:摘要可能丢失细节,且增加了额外的 LLM 调用成本。

2. 渐进式压缩 (Progressive Compression)

  • 原理:越久远的历史,压缩得越狠。

  • 策略

    • 最近 3 轮:保留原文。
    • 3-10 轮:提取关键句。
    • 10 轮以上:只保留摘要。
  • 实现

    python 复制代码
    def progressive_compress(history):
        recent = history[-3:]  # 最近3轮原文
        middle = extract_key_sentences(history[-10:-3])  # 中间提取关键句
        old_summary = summarize(history[:-10])  # 早期摘要
        return [old_summary] + middle + recent

三、结构化压缩:状态追踪 (State Tracking)

不存储完整对话,而是维护一个结构化的状态对象

1. 槽位填充 (Slot Filling)

  • 原理:将对话信息抽取为 Key-Value 对。

  • 示例

    python 复制代码
    # 原始对话
    history = [
        {"role": "user", "content": "我要买iPhone 15 Pro Max 256GB 黑色"},
        {"role": "assistant", "content": "好的,正在为您查询..."},
        {"role": "user", "content": "价格在8000以内"}
    ]
    
    # 压缩为状态
    state = {
        "product": "iPhone 15 Pro Max",
        "storage": "256GB",
        "color": "黑色",
        "price_limit": 8000
    }
  • 优点:极致压缩,只保留决策所需的关键信息。

  • 缺点:需要预定义槽位模式,不适合开放域对话。

2. 记忆图谱 (Memory Graph)

  • 原理:将对话中的实体和关系构建为知识图谱。

  • 实现

    python 复制代码
    # 使用 Neo4j 或 NetworkX
    graph.add_node("用户", name="张三")
    graph.add_node("商品", name="iPhone 15")
    graph.add_edge("张三", "iPhone 15", relation="想购买")
  • 优点:适合复杂的多轮任务(如客服、推荐)。

  • 缺点:构建和查询成本高。


四、向量化压缩:Embedding + 检索 (RAG-based)

将历史对话存储为向量,按需检索相关片段。

1. 向量数据库 (Vector DB)

  • 原理:每轮对话编码为 Embedding,存入 Faiss/Milvus/Pinecone。

  • 流程

    1. 每轮对话结束后,将对话内容用 text-embedding-ada-002 编码。
    2. 存入向量数据库,附带元数据(时间戳、轮次、是否关键)。
    3. 下次对话时,用当前 Query 检索 Top-K 最相关的历史片段。
  • 实现

    python 复制代码
    from langchain.vectorstores import FAISS
    from langchain.embeddings import OpenAIEmbeddings
    
    # 存储历史
    embeddings = OpenAIEmbeddings()
    vectorstore = FAISS.from_texts(
        texts=[turn['content'] for turn in history],
        embedding=embeddings
    )
    
    # 检索相关历史
    current_query = "用户刚才说的价格是多少?"
    relevant_history = vectorstore.similarity_search(current_query, k=3)
  • 优点:动态压缩,按需加载。

  • 缺点:需要额外的向量存储和检索开销。


五、模型层压缩:长上下文模型 + 注意力机制

利用模型自身的能力处理长文本。

1. 长上下文模型 (Long-Context LLMs)

  • 模型:Claude 3 (200K), GPT-4 Turbo (128K), Gemini 1.5 Pro (1M)。
  • 策略:直接喂入完整历史,让模型自己"压缩"(通过注意力机制)。
  • 优点:不丢失信息。
  • 缺点:成本极高(Claude 3 的 200K 输入约 $10)。

2. 注意力压缩 (Attention Compression)

  • 技术:LongLoRA, FlashAttention, Sparse Attention。
  • 原理:在模型层面优化注意力计算,减少对冗余 Token 的关注。
  • 适用:需要自己训练或微调模型。

六、混合策略:工业界最佳实践

实际项目中,通常组合多种方法:

python 复制代码
class HistoryCompressor:
    def __init__(self, max_tokens=4000):
        self.max_tokens = max_tokens
        self.vectorstore = FAISS(...)  # 向量库
        
    def compress(self, history, current_query):
        # 1. 首尾保留
        head = history[:2]  # 任务描述
        tail = history[-3:]  # 最近对话
        
        # 2. 中间部分向量检索
        middle_history = history[2:-3]
        if middle_history:
            relevant = self.vectorstore.similarity_search(
                current_query, 
                k=2,
                filter={"turns": middle_history}
            )
        else:
            relevant = []
        
        # 3. 组合
        compressed = head + relevant + tail
        
        # 4. Token 超限时强制摘要
        if count_tokens(compressed) > self.max_tokens:
            compressed = self.summarize(compressed)
        
        return compressed

七、总结:选择策略的决策树

场景 推荐策略 原因
短对话(<10轮) 不压缩 / 滑动窗口 成本低,信息损失小
任务型对话(槽位明确) 状态追踪 极致压缩,适合结构化任务
开放域对话(闲聊) 递归摘要 + 向量检索 保留语义,按需召回
多轮复杂推理 首尾保留 + 关键轮次 保证推理链完整
超长上下文(>50轮) 向量检索 + 长上下文模型 动态加载,避免信息过载

核心原则: 压缩不是目的,保留决策所需的最小信息集才是目标。

相关推荐
海绵宝宝de派小星2 小时前
图像处理基础概念与常用操作
图像处理·人工智能·ai
@鱼香肉丝没有鱼2 小时前
Transformer底层原理—Encoder结构
人工智能·深度学习·transformer
发哥来了2 小时前
主流Sora2相关商用服务公司可靠性对比
大数据·人工智能
张3蜂2 小时前
身份证识别接口方案
人工智能·python·开源
小真zzz2 小时前
2026年2月:AI模板生成PPT的深度解析:ChatPPT如何重新定义行业标准
人工智能·powerpoint·ppt·chatppt·aippt
AI营销快线2 小时前
线索转化率低?原圈科技AI CRM系统,实现高潜线索精准匹配
人工智能·科技
xixixi777772 小时前
今日 AI 、通信、安全前沿日报(2026 年 2 月 5 日,星期四)
人工智能·网络安全·ai·信息安全·大模型·通信·前沿
2501_941329722 小时前
【校园安全】YOLO11-C3k2-DBB实现校园安全行为识别与异常检测系统
人工智能·安全·目标跟踪
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-整体架构优化设计方案(续)
java·数据库·人工智能·spring boot·架构·领域驱动