模型压缩之前先用规则方法去除无效 token,真实提示词可压缩 30-60%。规则包括:去除 HTML 标记、JSON 压缩、去除重复块、删除 Base64/minified 内容、精简工具描述。模型级压缩代价高,需有算术依据才值得用。
Compression 是唯一一种需要花钱才能应用的上下文技术,所以它也是最需要用算术来证明其合理性的技术。有两种更便宜的方法通常比它效果更好,知道它们什么时候不行,就是这门技能的关键所在。
在任何基于模型的技术之前,先移除那些不携带信息的 token。这是朴实无华的、无损的,在真实 prompt 上通常能节省 30%–60%:
剥离标记。Prompt 中抓取的 HTML 主要是属性、导航和脚本标签——提取纯文本。
精简结构化数据。格式化输出的 JSON 为每个空格付了钱。对于表格数据,CSV 或紧凑的每列一个 key 的形式,比每行都重复所有 key 的对象数组要便宜得多。
去重。带重叠分块的检索会产生几乎相同的段落。哈希后丢弃。
丢弃无法读取的内容。Base64 blobs、长 ID、哈希值、精简后的代码包。这些无法被 tokenizer 压缩,对模型也没有用处。
精简工具描述。JSON Schema 描述中的每一个词,在循环中每次调用都要计费。
每种基于模型的技术都是用 token 来换取节省 token。算术如下(使用你应替换的示例费率):
original context T = 20,000 tok target model input $3.00 / M
compressed T' = 4,000 tok compressor in/out $0.15 / $0.60 per M
saving per use (20,000 - 4,000) / 1e6 * $3.00 = $0.0480
compression cost 20,000/1e6*$0.15 + 4,000/1e6*$0.60 = $0.0054
net per use, if the compressed artefact is reused = +$0.0426
net on a single use (compress then immediately send) = +$0.0426 as well
BUT compare against caching the same 20,000 tokens:
cache read at a 0.1x multiplier: 20,000/1e6 * $0.30 = $0.0060
compressed prompt, uncompressed rate: 4,000/1e6*$3 = $0.0120
仔细看最后两行,因为它们才是关键发现。当上下文稳定时,缓存既比压缩便宜,又是无损的——没有任何理由去压缩一个静态的系统 prompt。压缩只有在以下场景才能发挥其价值:上下文每次请求都不同、上下文太大而无法经济地缓存、或者必须在不共享缓存的模型之间复用。
因此完整的决策顺序是:删除无用的、检索而非塞入、缓存稳定的、压缩剩下的。大多数团队却把第四步放在第一位。
延迟应该在算术中单独占一行,因为压缩只是转移了成本,而非单纯向下。一个压缩调用是额外的网络往返和额外的生成,两者都在关键路径上,而且压缩器必须先读取整个上下文才能输出任何内容。对于一个交互式功能来说,这很容易增加比短 prompt 节省更多的墙上时间(wall-clock time)。因此,压缩在最站得住脚的场景是离线进行——在摄入阶段,或按计划执行——而在人类正在等待的请求中途是最站不住脚的。
压缩本质上是有损的;问题是你能容忍哪种损失。提取式选择会丢失段落之间的连接组织,因此会损害需要跨段落综合的任务。抽象摘要会丢失精确性——精确数字、日期、名称,以及值得注意的是否定词,因为"该条款不适用于子公司"和"该条款适用于子公司"在嵌入空间中的邻域几乎相同。Token 剪枝会丢失语法框架,模型通常能恢复,但偶尔不能,而且这会让你的 prompt 对凌晨两点调试的人类来说变得不可读。
有一种损失是所有方法共有的,值得明确说明:压缩后你再也无法引用原文了。如果你的产品显示引用,压缩后的文本必须保留指向原始段落的标识符,否则引用功能就会开始编造内容。
在长对话中还需要注意一种复合效应。压缩一个已经包含早期压缩摘要的上下文,是摘要的摘要,损失不是相加而是相乘——细节最先消失,然后是限定词,然后是已建立的内容和假设内容之间的区别。在每一层都保留指向未压缩原始内容的指针,尽可能从源头而非上一次压缩结果重新压缩。
永远不要压缩指令。系统 prompt 和用户的问题原封不动。它们很小,而且它们就是规格说明。
永远不要压缩结构化值。标识符、金额、日期、数量。将它们提取到一个小的逐字块中,只压缩周围的散文部分。
压缩一次,缓存结果。如果同一个源文档被重复使用,压缩形式是一个稳定的产物——存储它,而不是每次请求都重新生成。
端到端测量,而非压缩率。一个 10 倍压缩率如果牺牲了三个百分点的答案准确率,在任何价格下都是糟糕的交易,除非评估在最终答案上运行,否则你不会发现这个问题。
保留未压缩的路径。当答案错误时,第一个诊断是用完整上下文重新运行。如果这修复了问题,压缩就是你的 bug;如果不是,它从来都不是。
上面的盈亏平衡点取决于压缩器和目标模型之间的价格差距,这是一个双模型比较而非单一查询;把小型和大型模型的费率并列,就足以判断一个压缩步骤在构建之前能否回本。