上下文压缩策略实验


文档摘要

源文件:chapter2/context-compression/README.md 上下文压缩策略实验 本项目演示并对比 LLM Agent 的不同上下文压缩策略,以"研究 OpenAI 联合创始人当前去向"这一任务作为测试用例。 概览 随着 LLM 上下文窗口越来越大(128K+ token),高效地管理上下文对以下方面变得至关重要: 成本优化 — 减少 token 用量 性能 — 更快的响应速度 可靠性 — 避免上下文溢出错误 相关性 — 聚焦重要信息 本实验实现并对比了 6 种上下文压缩策略,以理解它们各自的取舍。

源文件:chapter2/context-compression/README.md

上下文压缩策略实验

本项目演示并对比 LLM Agent 的不同上下文压缩策略,以"研究 OpenAI 联合创始人当前去向"这一任务作为测试用例。

概览

随着 LLM 上下文窗口越来越大(128K+ token),高效地管理上下文对以下方面变得至关重要:

  • 成本优化 — 减少 token 用量
  • 性能 — 更快的响应速度
  • 可靠性 — 避免上下文溢出错误
  • 相关性 — 聚焦重要信息

本实验实现并对比了 6 种上下文压缩策略,以理解它们各自的取舍。

压缩策略

1. 不压缩(No Compression)

  • 描述:将所有原始网页内容直接塞入 Agent 上下文
  • 预期结果:几次工具调用后因上下文溢出而失败
  • 用途:演示基线问题

2. 非上下文感知:逐页摘要(Individual Summaries)

  • 描述:用 LLM 对每个网页单独摘要,再把所有摘要拼接起来
  • 预期结果:保留了页面级细节,但可能丢失跨页面关系
  • 取舍:需要多次 LLM 调用(每页一次),但保持了页面边界
  • 适用场景:希望把每个来源当作独立来源处理时

3. 非上下文感知:合并摘要(Combined Summary)

  • 描述:先把所有网页内容拼接,再生成一份综合摘要
  • 预期结果:对整体内容理解更好,但可能丢失页面级归属信息
  • 取舍:只需一次 LLM 调用,但页面较多时可能触及 token 上限
  • 适用场景:希望跨多个来源提炼总体主题时

4. 上下文感知摘要(Context-Aware Summarization)

  • 描述:合并所有搜索结果,生成聚焦查询的摘要
  • 预期结果:更好地保留相关性
  • 取舍:摘要需要额外一次 LLM 调用

5. 上下文感知 + 引用(Context-Aware with Citations)

  • 描述:类似第 4 种,但附上引用与来源链接
  • 预期结果:支持带来源追踪的后续提问
  • 取舍:上下文略大,但保持可溯源性

6. 窗口化上下文(Windowed Context)

  • 描述:保留最近一次工具调用的完整内容,压缩较早的历史
  • 预期结果:在细节与效率之间取得平衡
  • 取舍:近期细节 vs. 历史压缩
  • 智能压缩:只压缩尚未被压缩过的消息(用 [COMPRESSED] 标记防止重复压缩)

安装

  1. 进入项目目录:
cd chapter2/context-compression
  1. 安装依赖:
pip install -r requirements.txt
  1. 设置环境变量:
cp env.example .env # Edit .env with your API keys

所需 API Key:

  • MOONSHOT_API_KEY:用于 Kimi(Moonshot)模型(必需)。书中实验 2-9 使用 Kimi K3(一款推理
    模型,真实上下文窗口约 1M token;demo 通过 CONTEXT_WINDOW_SIZE 把上下文预算刻意限制在
    128K,以便观察溢出/压缩行为)。模型名可通过 .env 中的 MODEL_NAME-m/--model CLI 参数
    配置(例如 kimi-k2.5kimi-k3moonshot-v1-128k)。
  • OPENROUTER_API_KEY:通用回退。未设置 MOONSHOT_API_KEY 时,只要配置了
    OPENROUTER_API_KEY,实验会自动改走 OpenRouter(kimi-* 映射为
    moonshotai/kimi-k2)。设置了 MOONSHOT_API_KEY 时行为完全不变。
  • SERPER_API_KEY:用于网络搜索(可选,未提供时会使用模拟数据)

获取 API Key:

脚本概览

脚本 用途 产出
main.py 交互式 demo / 单策略运行器 控制台输出
experiment.py 自动化策略对比(token / 压缩率 / 成功率表) 结果写入 results/
run_all_strategies.py 带详细逐轮日志运行策略 日志写入 logs/
quickstart.py 检查环境并启动上述脚本的菜单封装 控制台输出

三个主入口都提供 argparse CLI(中文 --help)。用 -h 运行任一脚本可查看完整选项列表。以下三个最常用的参数是共用的:

  • -s/--strategy — 选择要运行的一种或多种策略(默认全部 6 种);取值见下方"Compression Strategies"或运行 --list-strategies
  • -m/--model — 覆盖模型名(默认读取环境变量 MODEL_NAME
  • -n/--max-iterations — 每个策略允许的最大工具调用轮数

--strategy 接受的策略别名:no_compressionindividualcombinedcontext_awarecitationswindowed

用法

运行完整实验(对比表 + JSON)

对比全部 6 种策略(默认),或其中一部分:

python experiment.py # 运行全部 6 种策略并生成对比表 python experiment.py -s context_aware # 只运行"上下文感知压缩" python experiment.py -s individual combined # 只对比两种非任务感知策略 python experiment.py -m moonshot-v1-128k -o results/run.json # 换模型 + 指定输出路径 python experiment.py --list-strategies # 查看可选策略名

这会:

  • 依次测试选定的每种压缩策略
  • 研究 OpenAI 联合创始人的去向
  • 打印对比表(成功 / 用时 / Tokens / 压缩率 / 溢出次数)
  • 把结果保存到 results/experiment_TIMESTAMP.json(或 -o/--output 指定的路径)

关键参数:-s/--strategy-m/--model-o/--output-n/--max-iterations--streaming--list-strategies

带日志运行全部策略

带详细日志和压缩输出运行策略:

python run_all_strategies.py # 全部 6 种策略 python run_all_strategies.py -s windowed # 只跑自适应窗口化 python run_all_strategies.py --log-dir logs/k2 -m kimi-k2.5

特性:

  • 依次运行选定的压缩策略
  • 把所有压缩摘要记录到文件
  • 实时显示流式输出
  • 把详细日志保存到 <log-dir>/strategy_run_TIMESTAMP.log
  • 把 JSON 结果保存到 <log-dir>/strategy_results_TIMESTAMP.json
  • 最后生成对比小结

关键参数:-s/--strategy-m/--model--log-dir-n/--max-iterations--list-strategies

交互式 demo

带流式输出测试单个策略:

python main.py # Interactive: choose a strategy at the prompt python main.py -s citations # Run a specific strategy non-interactively python main.py -s windowed --no-streaming # Disable streaming output

特性:

  • 选择任意压缩策略(交互式,或用 -s/--strategy
  • 默认启用流式响应(--no-streaming 可关闭)
  • 查看实时执行过程
  • 尝试后续提问(针对引用策略)

自定义用法

from agent import ResearchAgent from compression_strategies import CompressionStrategy # Create agent with specific strategy agent = ResearchAgent( api_key="your_api_key", compression_strategy=CompressionStrategy.CONTEXT_AWARE_CITATIONS, enable_streaming=True ) # Execute research result = agent.execute_research() # Access results if result['success']: print(result['final_answer']) print(f"Tool calls: {len(result['trajectory'].tool_calls)}")

项目结构

context-compression/ ├── config.py # Configuration management ├── web_tools.py # Web search and fetch tools ├── compression_strategies.py # Compression strategy implementations ├── agent.py # Main research agent with streaming ├── experiment.py # Experiment runner for comparisons (CLI) ├── run_all_strategies.py # Detailed per-round logging runner (CLI) ├── main.py # Interactive demo / single strategy runner (CLI) ├── quickstart.py # Menu wrapper (env check + launcher) ├── requirements.txt # Python dependencies ├── env.example # Environment variables template ├── logs/ # Detailed logs (created by run_all_strategies.py) └── results/ # Experiment results (created on run)

关键组件

网络工具(web_tools.py

  • search_web:用 Serper API 搜索,并爬取每条结果
  • fetch_webpage:抓取网页并把 HTML 转成干净文本
  • Mock 数据:在无 API Key 时提供示例数据

压缩策略(compression_strategies.py

  • ContextCompressor:实现全部 6 种策略
  • CompressedContent:压缩结果的数据类
  • 动态压缩:基于查询与上下文

研究 Agent(agent.py

  • 流式支持:实时响应流
  • 工具集成:网络搜索与抓取能力
  • 消息管理:处理对话历史
  • 窗口化压缩:动态历史压缩

实验运行器(experiment.py

  • 自动化测试:运行全部策略
  • 指标收集:执行时间、压缩率、成功率
  • 对比报告:可视化对比表
  • 结果持久化:输出 JSON 供分析

收集的指标

  • 成功率:任务是否成功完成
  • 执行时间:完成研究的总耗时
  • 压缩率:压缩后大小 / 原始大小
  • 上下文溢出次数:接近上下文上限的次数
  • 工具调用数:执行的网络搜索次数
  • 最终答案长度:生成报告的大小

预期结果

基于各压缩策略:

  1. 不压缩:❌ 因上下文溢出失败
  2. 非上下文感知:⚠️ 能完成但可能漏掉细节
  3. 上下文感知:✅ 在大小与相关性之间取得良好平衡
  4. 带引用:✅ 最适合后续追问,略大
  5. 窗口化上下文:✅ 长对话中最有效率

实测结果(真实运行)

以下数字来自一次真实的端到端运行——没有模拟数据。每种策略都使用了
实时 Serper 网络搜索(抓取并爬取真实的 2026 年网页)以及当前的
Moonshot 推理模型。

  • 模型kimi-k3(Moonshot 推理模型;真实窗口约 1M token,但 demo 把
    压缩/溢出预算限制在 CONTEXT_WINDOW_SIZE = 128000
  • 搜索:真实 Serper(google.serper.dev)网络搜索 + 页面爬取
  • 任务:识别并追踪 OpenAI 联合创始人的职业状态(约 11 位联合创始人)
  • 运行日期:2026-07-18 · MAX_ITERATIONS=15 · 原始 JSON:results/kimi_k3_real_20260718.json

各列含义:Tokens = 累计 Kimi API token 用量(所有迭代的 prompt + completion);
Compress = 压缩后字符数 / 原始字符数(越小 = 压得越狠);
Overflows = 128K 预算被接近/超出的次数。

# Strategy Success Iterations Tokens Compress Overflows Time
1 no_compression ❌ (overflow at 165,227 tok > 128K) 5 166,043 102.1% 1 107s
2 non_context_aware_individual_summary 12 276,608 10.9% 4 2980s
3 non_context_aware_combined_summary 10 93,449 4.3% 0 1189s
4 context_aware_summary 7 40,157 3.0% 0 967s
5 context_aware_with_citations 10 222,992 4.1% 3 1235s
6 windowed_context 7 174,601 102.4% 4 867s

说明:

  • 不压缩完全按设计失败:上下文在第 5 次迭代左右就超出 128K 预算
    (使用了 165,227 个 token)。
  • 上下文感知摘要(#4) 是 token 最高效的成功策略
    (40,157 token,3.0% 字符压缩率)——它在压得最狠的同时仍能完成任务。
  • 逐页摘要(#2) 远比其他策略慢(约 50 分钟),因为每个抓到的页面都要
    由推理模型单独摘要;token 用量也最高。
  • 窗口化上下文(#6) 只在 prompt 用量超过 80% 阈值
    (≈102,400 token)时才压缩,并一次性批量压缩所有未压缩的工具消息;由于
    它保留近期完整内容,其字符层面的"压缩率"始终在 ~100% 附近,而它仍然
    在所有会压缩的策略中最快完成任务。
  • 以上是单次运行、使用推理模型和实时网络搜索的测量值,因此各次运行的绝对
    数字会有波动;结论性的信息是它们之间的相对排序。

配置

编辑 .envconfig.py

  • MODEL_NAME:使用的 LLM 模型(默认:kimi-k3)
  • MODEL_TEMPERATURE:响应随机性(默认:0.3)
  • MAX_ITERATIONS:最大工具调用次数(默认:50)
  • MAX_WEBPAGE_LENGTH:每页最大字符数(默认:50000)
  • SUMMARY_MAX_TOKENS:摘要最大 token 数(默认:500)
  • CONTEXT_WINDOW_SIZE:demo 用于触发溢出/压缩的上下文预算(默认:128000;注意 Kimi K3 真实窗口约 1M token——这里故意用更小的预算以触发压缩)

故障排查

没有 API Key

若未设置 SERPER_API_KEY,系统会使用模拟数据,让你无需网络搜索即可测试压缩策略。

上下文溢出

若在使用"不压缩"以外的策略时遇到上下文溢出,可尝试:

  • 减小 MAX_WEBPAGE_LENGTH
  • 减小 SUMMARY_MAX_TOKENS
  • num_results 限制搜索结果数

执行缓慢

  • 在 demo 中关闭流式以加快输出
  • 减小 MAX_ITERATIONS 以加快实验
  • 用模拟数据替代真实网络搜索

研究任务

实验使用了一个具体的研究任务:

"Find the current affiliations of all OpenAI co-founders"

这个任务很理想,因为它:

  • 需要多次搜索(每位联合创始人一次)
  • 产生大量内容(生平信息)
  • 考验上下文管理(信息不断累积)
  • 结果可验证(去向是已知的)

扩展项目

新增压缩策略:

  1. CompressionStrategy 枚举中添加策略
  2. ContextCompressor 类中实现
  3. compress_search_results() 中添加处理
  4. 如有必要更新实验运行器

更换研究任务:

  1. 修改 agent.py 中的系统提示
  2. 更新 web_tools.py 中的模拟数据
  3. 相应调整工具描述

许可证

本项目是 AI Agent 实战训练课程的一部分,用于教学目的。


作者与出处
原作者: bojieli
来源:bojieli
许可证:Apache-2.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: bojieli 转发
评论区 (0)
U