📋 上下文压缩和分级截断方案
一、核心原则
- 延迟截断:在智能提取之前不截断文件内容
- 分级压缩:按照重要性分层压缩,优先保留关键信息
- 预算管理:根据模型上下文窗口动态分配token预算
- 智能优先:使用语义分析,而非简单字符截断
二、模型上下文窗口配置
| 模型 | 输入上限 | 输出上限 | 推荐使用率 | 剩余缓冲 |
|---|---|---|---|---|
| Chatrhino-750B | 128k tokens | 32k tokens | 70% | 38k |
| Chatrhino-81B-Pro | 128k tokens | 4k tokens | 75% | 32k |
| Chatrhino-10B | 32k tokens | 4k tokens | 80% | 6k |
| DeepSeek-R1 | 64k tokens | 8k tokens | 75% | 16k |
当前使用:Chatrhino-750B,推荐目标token数约90k tokens
三、Token预算分配策略(Chatrhino-750B示例)
3.1 预算分配表(目标90k tokens)
| 组件 | 预算占比 | 预算tokens | 说明 |
|---|---|---|---|
| 指令部分 | 3% | 2700 | Prompt指令、任务说明 |
| 元数据 | 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字符)
场景:单体应用,所有接口在一个大文件
处理方案:
- 优先提取目标接口的完整定义
- 提取同组的其他接口(同一path下)
- 保留components中的引用schema
- 其他部分完全忽略
预期token:3k-8k tokens
8.2 多文件复杂依赖
场景:接口A依赖Model1,Model1引用Model2...
处理方案:
- 递归跟踪$ref引用
- 提取所有被引用的schema
- 保留完整的依赖链
- 忽略未被引用的schema
预期token:5k-15k tokens
8.3 批量生成大量用例
场景:需要生成50+测试用例
处理方案:
- 减少基础用例数量(只保留5个)
- 只保留P0、P1约束
- 分批生成(每批10-15个)
- 使用循环迭代
预期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天)
- 实现Token估算函数
- 实现预算分配和监控
- 添加简单的首尾截断
- 添加日志和告警
阶段2:智能压缩(3-5天)
- 实现目标接口提取
- 实现结构化压缩
- 实现关键词保留
- 完善降级策略
阶段3:优化完善(持续)
- 根据实际使用调整预算
- 优化压缩算法
- 添加更多文件类型支持
- 性能优化
十二、风险评估
| 风险 | 概率 | 影响 | 应对措施 |
|---|---|---|---|
| 压缩后丢失关键信息 | 中 | 高 | 降级到下一级,记录日志 |
| Token估算不准 | 低 | 中 | 保守估算,预留buffer |
| 多文件依赖链断裂 | 中 | 高 | 实现$ref追踪 |
| 性能开销大 | 低 | 低 | 缓存压缩结果 |
十三、成功指标
- ✅ 关键信息保留率 > 95%
- ✅ 平均压缩率 > 60%
- ✅ Token使用率稳定在60-80%
- ✅ 压缩耗时 < 100ms/文件
- ✅ 降级触发率 < 5%