压缩上下文

4 阅读6分钟

📋 上下文压缩和分级截断方案

一、核心原则

  1. 延迟截断:在智能提取之前不截断文件内容
  2. 分级压缩:按照重要性分层压缩,优先保留关键信息
  3. 预算管理:根据模型上下文窗口动态分配token预算
  4. 智能优先:使用语义分析,而非简单字符截断

二、模型上下文窗口配置

模型输入上限输出上限推荐使用率剩余缓冲
Chatrhino-750B128k tokens32k tokens70%38k
Chatrhino-81B-Pro128k tokens4k tokens75%32k
Chatrhino-10B32k tokens4k tokens80%6k
DeepSeek-R164k tokens8k tokens75%16k

当前使用:Chatrhino-750B,推荐目标token数约90k tokens


三、Token预算分配策略(Chatrhino-750B示例)

3.1 预算分配表(目标90k tokens)

组件预算占比预算tokens说明
指令部分3%2700Prompt指令、任务说明
元数据2%1800接口签名、路径、方法
Service文件17%15300最重要,包含接口定义
Model文件9%8100数据模型定义
结构化约束3%2700字段约束、校验规则
基础测试用例6%5400已生成的用例
其他辅助信息10%9000其他相关接口、示例等
安全缓冲50%45000应对突发情况、动态扩展

实际可用:约 45k tokens(排除缓冲)

3.2 动态调整规则

  • 简单任务(单个接口):降低预算至60k
  • 复杂任务(多个接口、大量约束):使用完整90k
  • 批量生成(20+用例):需要预留更多空间,使用75k

四、分级截断策略

4.1 文件读取阶段(节点4)

原则:存储完整文件,延迟截断到LLM调用前

code

文件读取 → 完整存储到state → LLM调用前才截断

理由

  • 后续节点需要智能提取,不能丢失结构化信息
  • 内存成本远低于token成本
  • 可根据不同任务需求灵活处理

4.2 文件优先级排序(按重要性)

优先级1 - 必读文件

  • 向量查询确认的目标接口所在文件
  • metadata中的source文件

优先级2 - 高优先级文件

  • 包含service关键词的YAML文件(接口定义)
  • 包含目标接口相关模型定义的文件

优先级3 - 中优先级文件

  • 其他service文件
  • 常用model文件

优先级4 - 低优先级文件

  • 配置文件
  • 辅助工具文件

规则

  • 优先级1:必须包含,不截断
  • 优先级2:智能提取,保留目标接口
  • 优先级3:结构化截断,保留关键部分
  • 优先级4:超阈值直接丢弃

五、智能压缩策略

5.1 YAML文件压缩(三级策略)

第一级:目标接口提取

  • 使用operationId精准匹配
  • 提取完整的接口定义块(包括请求/响应schema)
  • 如果提取成功,通常只有2k-5k tokens
  • 成功率:约70-80%

第二级:结构化压缩

  • 提取paths部分的所有接口签名
  • 保留components中的关键schema(与目标接口相关)
  • 删除注释、空行
  • 压缩率:约50-70%

第三级:关键词保留

  • 保留前100行(通常包含metadata)
  • 提取所有顶层键(paths, components等)
  • 保留包含关键词的行(operationId, required, $ref等)
  • 压缩率:约30-50%

第四级:首尾保留

  • 前半部分 + 后半部分
  • 中间用省略号标记
  • 压缩率:可控,但可能丢失中间内容

5.2 JSON/Schema压缩

策略

  • 保留必需字段(name, type, required, description)
  • 压缩description:保留前100字符
  • 示例值:只保留第一个
  • 数组字段:只保留前3个元素

示例

yaml

原始:10个参数×平均300字符=3000字符压缩后:10个参数×平均120字符=1200字符压缩率:60%

5.3 测试用例压缩

策略

  • 完整保留前5个用例(参考模板)
  • 其他用例只保留:case_id, test_point, params_desc
  • 截断error_info为50字符

六、动态压缩流程

6.1 压缩决策树

code

开始
  ↓
读取所有候选文件
  ↓
按优先级排序(必读 > 高 > 中 > 低)
  ↓
【决策】Token预算是否足够?
  ├─ 是 → 使用完整内容
  └─ 否 → 进入压缩流程
         ↓
    尝试第一级压缩(目标接口提取)
         ↓
    【决策】提取成功且符合预算?
         ├─ 是 → 使用提取内容 → 结束
         └─ 否 → 继续压缩
                ↓
           尝试第二级压缩(结构化压缩)
                ↓
           【决策】符合预算?
                ├─ 是 → 使用 → 结束
                └─ 否 → 继续压缩
                       ↓
                  第三级压缩(关键词保留)
                       ↓
                  【决策】符合预算?
                       ├─ 是 → 使用 → 结束
                       └─ 否 → 丢弃低优先级文件
                              ↓
                         重新评估剩余文件
                              ↓
                         重复压缩流程

6.2 Token监控点

监控点1:文件读取后

  • 估算所有文件的总token数
  • 如果超预算20%以上,触发提前压缩

监控点2:Prompt构建中

  • 实时计算已组装的token数
  • 达到80%预算时,启动降级策略

监控点3:LLM调用前

  • 最终检查prompt总长度
  • 如果仍然超预算,报错并提供调整建议

七、降级策略(当压缩后仍然超预算)

7.1 文件层面降级

降级等级1:丢弃低优先级文件

  • 移除辅助配置文件
  • 保留:目标接口文件 + 主要service + 主要model

降级等级2:压缩高优先级文件

  • Service文件:从结构化压缩改为关键词保留
  • Model文件:只保留目标相关的schema

降级等级3:只保留核心

  • 只保留目标接口的完整定义
  • 其他接口只保留签名

7.2 内容层面降级

降级等级1:减少指令

  • 合并重复指令
  • 删除注释性文本

降级等级2:减少约束

  • 只保留P0、P1优先级的约束
  • 丢弃业务错误场景

降级等级3:减少基础用例

  • 只保留2-3个典型用例作为参考
  • 其他用例只保留case_id

7.3 降级决策阈值

超预算比例处理策略
0-10%警告,但继续执行
10-30%自动降级等级1
30-50%自动降级等级2
>50%报错,要求手动调整

八、特殊场景处理

8.1 大型YAML文件(>50k字符)

场景:单体应用,所有接口在一个大文件

处理方案

  1. 优先提取目标接口的完整定义
  2. 提取同组的其他接口(同一path下)
  3. 保留components中的引用schema
  4. 其他部分完全忽略

预期token:3k-8k tokens

8.2 多文件复杂依赖

场景:接口A依赖Model1,Model1引用Model2...

处理方案

  1. 递归跟踪$ref引用
  2. 提取所有被引用的schema
  3. 保留完整的依赖链
  4. 忽略未被引用的schema

预期token:5k-15k tokens

8.3 批量生成大量用例

场景:需要生成50+测试用例

处理方案

  1. 减少基础用例数量(只保留5个)
  2. 只保留P0、P1约束
  3. 分批生成(每批10-15个)
  4. 使用循环迭代

预期token:8k-12k tokens/批


九、监控和日志

9.1 Token使用报告

每次LLM调用前输出:

code

=== Token使用报告 ===
模型: Chatrhino-750B
输入上限: 128k tokens
目标使用: 90k tokens

组件使用:
  指令部分: 2.5k tokens (2.8%)
  元数据: 1.8k tokens (2.0%)
  Service文件: 15.2k tokens (16.9%)
  Model文件: 8.1k tokens (9.0%)
  约束信息: 2.5k tokens (2.8%)
  基础用例: 5.3k tokens (5.9%)
  总计: 35.4k tokens (39.3%)

剩余预算: 54.6k tokens (60.7%)
状态: ✅ 正常

9.2 压缩动作日志

code

[智能压缩] service.yaml (15000 字符)
  ├─ 尝试提取目标接口: createRedisInstance
  ├─ ✅ 提取成功: 2800 字符
  └─ 压缩率: 81.3%

[结构化压缩] model.yaml (8000 字符)
  ├─ 未找到精确匹配
  ├─ 应用第二级压缩
  ├─ 提取 paths 和 components
  └─ 压缩后: 3200 字符 (60.0%)

9.3 告警机制

警告级别

  • 🟡Warning:使用率>70%
  • 🟠Alert:使用率>85%,自动降级
  • 🔴Critical:使用率>95%,拒绝执行

十、配置参数

10.1 全局配置

yaml

context_compression:
  # 模型配置
  model:"Chatrhino-750B"
  target_usage_ratio:0.70  # 目标使用率
  
  # 预算配置
  budgets:
    instructions:2700
    metadata:1800
    service_files:15300
    model_files:8100
    constraints:2700
    base_cases:5400
    buffer:45000
  
  # 阈值配置
  thresholds:
    warning:0.70
    alert:0.85
    critical:0.95
  
  # 降级配置
  degrade:
    level1_threshold:0.10  # 超预算10%,触发等级1
    level2_threshold:0.30
    level3_threshold:0.50
  
  # 压缩配置
  compression:
    extract_interface:true  # 尝试提取目标接口
    structural:true        # 启用结构化压缩
    keyword_based:true     # 启用关键词保留
    head_tail_ratio:0.5    # 首尾保留比例

10.2 文件类型配置

yaml

file_policies:
  service.yaml:
    priority:high
    max_chars:20000  # 初始截断阈值
    extraction:true   # 启用智能提取
    
  model.yaml:
    priority:medium
    max_chars:8000
    extraction:false  # 不提取,使用结构化压缩
    
  config.yaml:
    priority:low
    max_chars:3000
    drop_if_overflow:true  # 超预算直接丢弃

十一、实施建议

阶段1:快速实施(1-2天)

  1. 实现Token估算函数
  2. 实现预算分配和监控
  3. 添加简单的首尾截断
  4. 添加日志和告警

阶段2:智能压缩(3-5天)

  1. 实现目标接口提取
  2. 实现结构化压缩
  3. 实现关键词保留
  4. 完善降级策略

阶段3:优化完善(持续)

  1. 根据实际使用调整预算
  2. 优化压缩算法
  3. 添加更多文件类型支持
  4. 性能优化

十二、风险评估

风险概率影响应对措施
压缩后丢失关键信息降级到下一级,记录日志
Token估算不准保守估算,预留buffer
多文件依赖链断裂实现$ref追踪
性能开销大缓存压缩结果

十三、成功指标

  • ✅ 关键信息保留率 > 95%
  • ✅ 平均压缩率 > 60%
  • ✅ Token使用率稳定在60-80%
  • ✅ 压缩耗时 < 100ms/文件
  • ✅ 降级触发率 < 5%