04. Prompt 压缩和 Token 优化有哪些常见策略?
整理 Prompt 压缩、Token 优化、上下文管理与成本延迟权衡。
简单回答
Token 优化的目标是在不损失关键信息的前提下,减少每次请求的 token 数量,从而降低成本和延迟。常见策略分三类:压缩输入(去冗余信息、用更精炼的表达)、结构优化(改用更节省 token 的格式)、以及动态管理上下文(在多轮对话中裁剪历史消息)。没有万能方案,需要在信息完整性和 token 效率之间权衡,错误的压缩会严重损害模型理解。
详细解答
为什么 Token 优化很重要
Token 成本在大规模 LLM 应用里是真实的运营成本。以 GPT-4o 为例,input token 约 10/M。一个每天处理 10 万次请求、平均每次 3000 input token 的应用,每天光 input 就花 80,000。
除了成本,token 数量还直接影响延迟——更短的 prompt 处理更快,特别是在 prefill 阶段。对于对延迟敏感的场景(实时对话、代码补全),这是关键优化方向。
输入内容的压缩
去除冗余信息是最直接的方式。很多 System Prompt 随着时间积累了大量重复或过时的说明,定期审查去掉冗余内容。一个测试方法:把某段说明删掉,看输出质量是否下降;如果没有变化,那段说明可能是冗余的。
精炼语言:把"请你在回答的时候确保你给出的回答能够充分地解决用户的问题"压缩成"给出完整的解答",意思没变,token 减少了一半以上。这听起来简单,但真正在项目里系统地做这件事,往往有 20%~30% 的压缩空间。
RAG 场景下的上下文压缩:检索到的文档片段往往包含很多和问题无关的内容。常见手段有:
- 抽取式压缩(Extractive Compression):只保留和问题直接相关的句子,其余删掉
- 生成式压缩(Generative Compression):让一个小模型把检索结果压缩成更精炼的摘要
- LLMLingua 等专门的 Prompt 压缩工具:用小模型打分每个 token 的重要性,删掉低重要性的 token,在保持语义的前提下做大比例压缩(可以做到 2~5 倍压缩率)
文档格式的转换:原始文档可能是 HTML、Markdown 或 PDF 解析出来的文本,包含大量格式标签、空行、重复的页眉页脚等。预处理时把这些清理掉,通常能节省 10%~30% 的 token。
结构和格式优化
减少 Markdown 格式符号:Markdown 用 ##、**、- 等符号,这些符号本身也是 token。如果输出不需要渲染 Markdown,可以在 System Prompt 里要求纯文本输出,减少格式符号的 token 消耗。
用紧凑的数据格式:对于结构化数据,CSV 或者紧凑 JSON 比带空格的格式化 JSON 节省很多 token:
Few-shot 例子的长度控制:Few-shot 例子越长,token 消耗越大。对于只需要格式示范的场景,可以用非常简短的例子,而不是完整的长示例。
多轮对话的上下文管理
多轮对话是 token 消耗的大头——随着对话进行,每次请求都要把完整的历史对话送给模型,历史消息越来越长,成本线性增加。
滑动窗口:只保留最近 N 轮对话,丢弃更早的历史。简单有效,但可能丢失对话中很早提及的重要信息(比如用户最开始提到的特殊需求)。
重要信息摘要:在对话进行一定轮数后,用一个摘要节点把之前的对话压缩成关键信息摘要,之后只携带这个摘要而不是完整历史。摘要里应该包含:用户明确提到的约束和需求、已经确认的决策、以及影响后续对话的关键背景。
KV Cache 友好的 Prompt 设计(高级):在云 API 中,很多提供商支持 Prompt Caching——如果 Prompt 的前缀部分(特别是 System Prompt)在多次请求间保持不变,可以缓存这部分的 KV 值,减少重复计算费用。设计上,把变化频率低的部分(System Prompt、固定的 Few-shot 例子)放在 Prompt 最前面,变化频率高的部分(用户输入、动态检索结果)放在后面,最大化缓存命中率。
权衡和风险
Token 压缩不是越激进越好,过度压缩有明显风险:
信息损失导致效果下降:压缩掉了模型需要的上下文,答案质量下降。这是最常见的代价,必须在每次压缩后评测效果。
模型对紧凑格式的理解偏差:某些极端压缩(比如 LLMLingua 删掉大量 token)会产生语法不完整的文本,在大多数情况下强模型能理解,但在某些细粒度任务上可能出现理解偏差。
压缩方案要以评测为前提,做 A/B 对比(压缩前后的效果),确保质量没有明显下降再上线。
面试时可以这样答
Token 优化在规模化 LLM 应用里是真实的成本问题,三类策略。
输入内容层面:去冗余,用更精炼的表达,RAG 场景下检索到的文档压缩再喂给模型(LLMLingua 这类工具可以做到几倍压缩);预处理时清理 HTML 标签、页眉页脚这些无用格式,通常就有 10%~30% 的节省。
格式层面:不需要渲染 Markdown 就关掉,减少格式符号;JSON 用紧凑格式而非格式化 JSON;Few-shot 例子能短就短,别用长示例做格式示范。
多轮对话层面:滑动窗口只保留最近 N 轮;定期做摘要,把早期对话压成关键信息继续携带;如果用支持 Prompt Caching 的 API,把 System Prompt 这类不变的部分放最前面,最大化缓存命中。
风险是信息损失,过度压缩会降效果,每次优化都要 A/B 测一下,不能只看 token 数下降。
常见追问
- LLMLingua 的压缩原理是什么?它是怎么判断哪些 token 可以删除的?
- Prompt Caching 具体怎么实现?哪些云厂商支持?怎么设计 Prompt 来最大化缓存命中?
- 如果要大规模部署,token 压缩和调用更小的模型,哪个 ROI 更高?