什么是消息剪裁?
消息剪裁(Message Pruning)是一种自动管理对话历史长度的机制,在保持对话连贯性的同时,减少不必要的 Token 消耗。
为什么需要剪裁?
降低成本
减少 Token 使用,降低 API 调用成本
启用剪裁
设置 prune: true 启用消息剪裁:
{
"model": "anthropic/claude-3-7-sonnet-20250219",
"messages": [...],
"prune": true
}
剪裁选项
通过 pruneOptions 自定义剪裁行为:
{
"prune": true,
"pruneOptions": {
"targetTokens": 60000,
"preserveRecentMessages": 5
}
}
重要:如果不设置 pruneOptions,系统使用默认值(targetTokens: 80000),适用于大多数场景。只有在需要更激进的剪裁时才需要自定义配置。
参数说明
| 参数 | 类型 | 默认值 | 说明 |
|---|
targetTokens | number | 80000 | 触发剪裁的阈值。当消息总 Token 数超过此值时,会执行剪裁优化 |
maxOutputTokens | number | 100000 | 剪裁后消息的绝对上限(超过会警告但不阻止) |
preserveRecentMessages | number | 3 | 始终保留的最新消息数量(确保对话连贯性,建议至少保留 3 条最新消息) |
参数理解:
targetTokens:小于此值不会触发剪裁,大于此值才开始优化
maxOutputTokens:剪裁的最终目标上限,但不是硬性限制
preserveRecentMessages:无论如何都会保留的消息数,设置过小可能影响对话连贯性
剪裁策略
系统会根据消息历史的特征自动选择最合适的优化策略:
gentle_optimization - 温和优化(常用)
适用场景:消息总数适中,仅需轻度优化策略:
- 保留最近的 N 条消息(由
preserveRecentMessages 控制)
- 从较早的消息开始逐步移除
- 确保 user/assistant 消息对的完整性
- 系统提示词始终保留
aggressive_image_removal - 激进的图片移除
适用场景:消息中包含大量图片或文件附件策略:
- 优先移除历史消息中的图片和文件 part
- 保留文本内容以维持对话连贯性
- 显著降低 Token 消耗(图片占用大量 tokens)
hybrid_optimization - 混合优化
适用场景:消息历史既长又包含附件策略:
- 结合移除旧消息和移除附件
- 平衡对话历史和 Token 消耗
- 根据消息重要性动态调整
aggressive_truncation - 激进截断
适用场景:消息总数远超阈值,需要大幅减少策略:
- 仅保留最近的核心消息
- 移除大部分历史对话
- 优先保证响应速度和成本
适用场景:消息总数略超阈值策略:
- 最小化的调整
- 仅移除少量最早的消息
- 最大程度保留上下文
自动策略选择:您无需手动选择策略,系统会根据消息历史的长度、内容类型(是否包含图片)、Token 总数等因素自动选择最优策略。
检查剪裁结果
响应头 X-Message-Pruned 指示是否进行了剪裁:
完整示例
大多数情况下,使用默认配置即可:const response = await fetch("https://huajune.duliday.com/api/v1/chat", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "anthropic/claude-3-7-sonnet-20250219",
messages: longConversationHistory, // 对话历史
prune: true, // 仅启用剪裁,使用默认配置
stream: false,
}),
});
// 检查是否进行了剪裁
const isPruned = response.headers.get("X-Message-Pruned") === "true";
if (isPruned) {
console.log("消息已剪裁以优化成本");
}
const data = await response.json();
console.log(`输入 tokens: ${data.data.usage.inputTokens}`);
默认配置:targetTokens: 80000, preserveRecentMessages: 3。这适用于绝大多数场景,无需手动调整。
如果需要更激进的剪裁(例如成本敏感型应用):const response = await fetch("https://huajune.duliday.com/api/v1/chat", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "anthropic/claude-3-7-sonnet-20250219",
messages: longConversationHistory,
prune: true,
pruneOptions: {
targetTokens: 50000, // 降低阈值,更早触发剪裁
preserveRecentMessages: 5, // 保留更多最新消息以维持连贯性
},
stream: false,
}),
});
const isPruned = response.headers.get("X-Message-Pruned") === "true";
const data = await response.json();
console.log(`剪裁状态: ${isPruned ? "已剪裁" : "未剪裁"}`);
console.log(`输入 tokens: ${data.data.usage.inputTokens}`);
console.log(`输出 tokens: ${data.data.usage.outputTokens}`);
自定义配置注意事项:
targetTokens 设置过低会导致频繁剪裁,可能影响对话质量
preserveRecentMessages 建议至少保留 3-5 条消息
- 建议先使用默认配置,根据实际效果再调整
最佳实践
不同场景使用不同的剪裁配置:{
"prune": true,
"pruneOptions": {
"targetTokens": 60000,
"preserveRecentMessages": 8
}
}
推荐策略:
- 默认配置适用于大多数场景(80000 tokens 阈值)
- 只有在明确需要更激进的成本控制时才降低
targetTokens
preserveRecentMessages 建议保持在 3-8 之间
记录剪裁前后的消息数量和 Token 变化:const originalLength = messages.length;
const estimatedTokens = messages.length * 100; // 粗略估算
const response = await fetch(url, {
method: "POST",
headers: { /* ... */ },
body: JSON.stringify({
messages,
prune: true,
pruneOptions: { targetTokens: 50000 }
})
});
const isPruned = response.headers.get('X-Message-Pruned') === 'true';
const data = await response.json();
console.log('剪裁统计:');
console.log(` - 原始消息数: ${originalLength} 条`);
console.log(` - 是否剪裁: ${isPruned ? '是' : '否'}`);
console.log(` - 实际输入 tokens: ${data.data.usage.inputTokens}`);
console.log(` - 节省比例: ${isPruned ?
Math.round((1 - data.data.usage.inputTokens / estimatedTokens) * 100) : 0}%`);
使用返回的 usage 信息监控和优化成本:const response = await fetch(url, { /* ... */ });
const data = await response.json();
const { inputTokens, outputTokens, totalTokens } = data.data.usage;
// 计算成本(以 Claude 3.7 Sonnet 为例)
const INPUT_COST_PER_1M = 3.0; // $3 per 1M input tokens
const OUTPUT_COST_PER_1M = 15.0; // $15 per 1M output tokens
const inputCost = (inputTokens / 1_000_000) * INPUT_COST_PER_1M;
const outputCost = (outputTokens / 1_000_000) * OUTPUT_COST_PER_1M;
const totalCost = inputCost + outputCost;
console.log(`Token 使用情况:`);
console.log(` 输入: ${inputTokens} tokens (\$${inputCost.toFixed(4)})`);
console.log(` 输出: ${outputTokens} tokens (\$${outputCost.toFixed(4)})`);
console.log(` 总计: ${totalTokens} tokens (\$${totalCost.toFixed(4)})`);
// 如果成本过高,考虑调整 targetTokens
if (inputTokens > 70000) {
console.warn('⚠️ 输入 tokens 较高,建议降低 targetTokens 参数');
}
成本优化建议:
- 定期监控每次请求的 Token 使用量
- 如果输入 tokens 持续偏高,考虑降低
targetTokens
- 平衡成本与对话质量,避免过度剪裁
根据实际使用情况动态调整剪裁参数:async function chatWithAdaptivePruning(messages) {
// 根据消息数量动态决定是否需要剪裁
const messageCount = messages.length;
let pruneConfig = {
prune: false // 默认不剪裁
};
if (messageCount > 100) {
// 超长对话:更激进的剪裁
pruneConfig = {
prune: true,
pruneOptions: {
targetTokens: 45000,
preserveRecentMessages: 10
}
};
} else if (messageCount > 50) {
// 长对话:启用剪裁
pruneConfig = {
prune: true,
pruneOptions: {
targetTokens: 60000,
preserveRecentMessages: 8
}
};
}
const response = await fetch(url, {
method: "POST",
headers: { /* ... */ },
body: JSON.stringify({
model: "anthropic/claude-3-7-sonnet-20250219",
messages,
...pruneConfig,
stream: false
})
});
return response.json();
}
动态策略优势:
- 短对话无需剪裁,保持完整上下文
- 长对话自动优化,降低成本
- 根据业务场景灵活调整
注意事项
剪裁的权衡考虑:剪裁会移除部分对话历史,可能影响:
- 对早期内容的引用(AI 无法访问已删除的消息)
- 需要完整上下文的任务(如长篇文档分析)
- 多轮复杂推理(依赖历史推理步骤)
建议:
- 在成本敏感的场景中优先使用剪裁
- 关键对话或需要完整上下文的任务中谨慎使用
- 通过
preserveRecentMessages 保留足够的最新消息(建议 ≥ 3)
性能对比
以下是使用自定义激进配置(targetTokens: 40000)的性能对比:
| 场景 | 不剪裁 | 启用剪裁(激进) | 节省 |
|---|
| 100 条消息对话 | ~25,000 tokens | ~10,000 tokens | 60% |
| 50 条消息对话 | ~12,000 tokens | ~8,000 tokens | 33% |
| 20 条消息对话 | ~5,000 tokens | 无需剪裁 | - |
| 包含图片的 50 条对话 | ~45,000 tokens | ~15,000 tokens | 67% |
说明:
- 上表基于
targetTokens: 40000 的自定义配置,非默认值
- 使用默认配置(
targetTokens: 80000)时,100 条消息对话(~25k tokens)不会触发剪裁
- 图片和文件附件占用大量 tokens,使用
aggressive_image_removal 策略可显著降低成本
- 实际节省比例取决于消息长度、内容类型和配置参数
成本节省示例
以 Claude 3.7 Sonnet 为例(输入 $3/1M tokens,输出 $15/1M tokens):
| 场景 | 原始成本 | 剪裁后成本 | 节省金额 |
|---|
| 1000 次调用 | $75.00 | $30.00 | $45.00 (60%) |
| 10000 次调用 | $750.00 | $300.00 | $450.00 |
| 100万次调用 | $75,000.00 | $30,000.00 | $45,000.00 |
对于高频调用的应用,启用消息剪裁可以显著降低 API 成本,特别是在长对话和包含附件的场景中。
下一步