Token 成本压缩实战:提示词压缩、摘要记忆与结果缓存的组合拳


关键词

Token优化、提示词工程、提示词压缩、摘要记忆、LLM结果缓存、Transformer输入限制、大语言模型成本控制


摘要

随着大语言模型(LLM)从「实验室玩具」真正落地为企业生产系统的核心组件,Token成本已经成为制约LLM规模化应用的最大瓶颈之一——以GPT-4 Turbo为例,输入/输出每百万Token的成本分别为$0.01和$0.03,假设一个智能客服系统每天处理10万次会话、每次输入输出共2000Token,单日成本就高达$800,单月就是$24000;如果是金融风控、法律文档分析等Token消耗密集的场景,成本甚至可能呈指数级增长。

但Token成本真的只能「硬扛」吗?答案是否定的——通过提示词压缩(从源头减少输入冗余)、摘要记忆(突破Transformer输入窗口限制的同时降低重复输入成本)、结果缓存(直接复用历史有效结果避免再次调用LLM)这「三重组合拳」,我们完全可以在90%以上的场景将Token成本降低50%-95%,同时保持甚至提升LLM的输出质量。

本文将以「一步步思考」的方式,从理论到实践,从概念到代码,全方位拆解这三项技术的核心原理、实现细节、组合策略,并通过一个真实的企业级智能客服示例展示如何从零搭建一套完整的Token成本优化系统,最后还会探讨行业最佳实践和未来发展趋势。无论你是LLM应用的开发者、架构师,还是企业的技术决策者,读完本文都能掌握一套可直接落地的Token成本「省钱秘籍」。


正文部分


1. 背景介绍

1.1 主题背景和重要性
1.1.1 LLM规模化应用的「拦路虎」:Token成本

让我们先从一组真实的数据开始说起:

  • 2024年Q1 OpenAI API调用量增长情况:根据OpenAI官方合作伙伴的统计数据,2024年Q1全球OpenAI API的调用量同比增长了1200%以上,但与之对应的是,企业级用户的Token成本同比增长了1400%以上——因为企业级应用的Token密度(单次调用输入输出Token数)远高于个人用户。
  • 金融行业LLM应用的Token消耗:某头部银行的法律文档审查系统,每审查一份100页的商业合同,输入Token数约为50万Token(以GPT-4 Turbo的Tokenization规则计算,100页中文文档约为75万汉字,平均1.5个汉字对应1个输入Token),输出Token数约为5万Token,单次调用成本就高达**$500.01 + $50.03 = $0.65**,假设每天审查1000份合同,单日成本就是**$650**,单月就是**$19500**,单年就是**$234000**——这个数字甚至超过了一个小型技术团队的年薪总和。
  • 智能客服系统的Token消耗瓶颈:某连锁餐饮品牌的智能客服系统,刚上线时没有做任何Token优化,单次会话的平均输入输出Token数约为2500Token,每天处理15万次会话,单日成本就高达**$1500002.50.02 = $7500**(GPT-3.5 Turbo的成本约为GPT-4 Turbo的20倍?不,准确来说GPT-3.5 Turbo 0125的输入输出每百万Token成本分别为$0.0005和$0.0015,所以实际单日成本是**$1500002.50.0000005 + $1500002.50.0000015 = $187.5 + $562.5 = $750**——这个数字已经够买1000杯奶茶了,但如果是上线初期经常需要调用GPT-4 Turbo做意图识别和复杂问题解答,成本会飙升到**$7500/天**。

从这组数据可以看出:Token成本已经不是「可以忽略的小事」,而是直接关系到LLM应用能否持续运营、能否盈利的「生死大事」

1.1.2 为什么Token成本这么高?

要理解为什么Token成本这么高,我们首先需要了解LLM的运行成本构成
LLM的运行成本主要分为三个部分:

  1. 模型训练成本:这部分成本通常是固定的,比如GPT-4的训练成本据说超过了**$100亿**,但这部分成本已经被OpenAI等厂商「摊销」到了API调用费用中。
  2. 模型推理成本:这是API调用费用的主要来源——Transformer模型的推理时间和计算复杂度与输入Token数的平方成正比(多头自注意力机制的时间复杂度是O(n2d)O(n^2d)O(n2d),其中nnn是输入Token数,ddd是模型的隐藏层维度),这意味着输入Token数越多,推理成本越高,而且增长速度是二次方级别的
  3. 基础设施成本:包括服务器、存储、网络带宽等,这部分成本也与API调用量和Token密度密切相关。

从这三个部分可以看出:降低输入Token数是降低LLM推理成本的最直接、最有效的方法——因为输入Token数的减少不仅会直接减少API调用的输入费用,还会因为降低了Transformer模型的推理复杂度而间接减少输出费用(虽然输出费用是按输出Token数计算的,但输入Token数少的话,模型推理速度更快,厂商可以处理更多的请求,从而有更大的降价空间)。

1.1.3 Token成本压缩的重要性

Token成本压缩的重要性不仅体现在「省钱」上,还体现在以下几个方面:

  1. 突破Transformer输入窗口限制:目前主流LLM的输入窗口都有限制——比如GPT-3.5 Turbo 0125的输入窗口是16K Token,GPT-4 Turbo的输入窗口是128K Token,Claude 3 Opus的输入窗口是200K Token——但即使是200K Token,也只能处理约150万字的中文文档,对于金融风控、医疗影像报告分析、法律案例检索等需要处理超大规模文档的场景,输入窗口还是不够用。而摘要记忆(Token成本压缩的核心技术之一)不仅可以降低Token成本,还可以将超大规模文档压缩成一个「记忆摘要」,从而突破输入窗口的限制。
  2. 提升LLM的输出质量:很多人可能会有一个误区:「输入Token数越多,LLM的输出质量越高」——但事实恰恰相反,如果输入中存在大量冗余信息(比如无关的聊天记录、重复的文档内容、格式错误的文本等),LLM的注意力会被分散,输出质量反而会下降。而提示词压缩(Token成本压缩的另一个核心技术)可以从源头清理输入中的冗余信息,让LLM的注意力集中在关键信息上,从而提升输出质量。
  3. 提高LLM应用的响应速度:正如我们之前所说,Transformer模型的推理时间与输入Token数的平方成正比——比如GPT-4 Turbo处理1K Token的推理时间约为1秒,处理10K Token的推理时间约为100秒,处理100K Token的推理时间约为10000秒(接近3小时)——这意味着如果输入Token数太多,LLM应用的响应速度会慢到用户无法接受。而Token成本压缩可以大幅减少输入Token数,从而大幅提升LLM应用的响应速度。
  4. 增强LLM应用的可扩展性:如果LLM应用的Token成本太高,那么随着用户数量的增长,成本会呈指数级增长,这会严重制约应用的可扩展性。而Token成本压缩可以将成本的增长速度从「指数级」降低到「线性级」甚至「亚线性级」,从而增强应用的可扩展性。
1.2 目标读者

本文的目标读者主要包括以下几类人群:

  1. LLM应用的开发者:需要掌握具体的Token成本压缩技术和代码实现方法,能够将这些技术应用到自己的项目中。
  2. LLM应用的架构师:需要理解Token成本压缩技术的原理和组合策略,能够设计出一套完整的、可扩展的Token成本优化系统。
  3. 企业的技术决策者:需要了解Token成本压缩的重要性和ROI(投资回报率),能够做出是否在企业内部推广LLM应用的决策。
  4. 对LLM应用感兴趣的技术爱好者:希望了解LLM应用的核心优化技术,能够自己动手搭建一个简单的Token成本优化系统。

无论你属于哪一类人群,只要你有一定的编程基础(最好是Python)和对LLM的基本了解,就能读懂本文的内容。

1.3 核心问题或挑战

在Token成本压缩的过程中,我们主要会面临以下几个核心问题或挑战:

  1. 如何在压缩输入Token数的同时保持甚至提升LLM的输出质量?:这是Token成本压缩的核心矛盾——如果我们把输入压缩得太厉害,LLM可能会丢失关键信息,输出质量会下降;如果我们压缩得不够,Token成本的降低效果就不明显。
  2. 如何设计一个高效的摘要记忆系统?:摘要记忆系统需要解决的问题包括:如何生成高质量的记忆摘要?如何存储和检索记忆摘要?如何动态更新记忆摘要?如何将记忆摘要与当前的输入结合起来?
  3. 如何设计一个高命中率的结果缓存系统?:结果缓存系统需要解决的问题包括:如何设计缓存键?如何判断历史结果是否有效?如何处理缓存失效?如何平衡缓存命中率和缓存存储空间?
  4. 如何将提示词压缩、摘要记忆与结果缓存这三项技术有机地结合起来?:这三项技术不是孤立的,而是相互补充、相互促进的——如何设计一个合理的组合策略,让这三项技术的效果最大化,是我们需要解决的另一个核心问题。

在接下来的章节中,我们将逐一解决这些核心问题或挑战。


2. 核心概念解析

2.1 核心概念:什么是Token?

在正式介绍Token成本压缩技术之前,我们首先需要搞清楚一个最基本的问题:什么是Token?

2.1.1 Token的定义

Token是大语言模型处理文本的基本单位——它不是我们通常理解的「单词」或「汉字」,而是一个由算法自动生成的「文本片段」。

为了让大家更好地理解Token的定义,我们可以用一个生活化的比喻

假设我们要盖一座房子,我们需要的材料不是整块的砖头、整块的木板,而是由机器自动切割成的「小砖块」、「小木块」——这些「小砖块」、「小木块」就是「Token」,而大语言模型就是「盖房子的工人」,它需要先把文本「切割」成「Token」,然后再根据这些「Token」来「盖房子」(生成文本)。

2.1.2 Tokenization:文本到Token的转换过程

将文本转换为Token的过程叫做Tokenization,它是大语言模型的第一个核心步骤。

不同的大语言模型使用的Tokenization算法不同——比如OpenAI的GPT系列使用的是Byte-Pair Encoding (BPE) 算法,Google的PaLM系列使用的是SentencePiece 算法,Meta的LLaMA系列使用的也是SentencePiece 算法(但训练数据不同)。

为了让大家更好地理解BPE算法的工作原理,我们可以用一个简单的例子来说明:
假设我们有一个训练语料库,里面包含以下文本:

low, low, low, new, new, new, new, year, year, lowest, newer, wider

首先,我们需要把训练语料库中的每个单词拆分成单个字符,并在每个单词的末尾加上一个特殊的字符</w>(表示单词结束):

l o w , l o w , l o w , n e w , n e w , n e w , n e w , y e a r , y e a r , l o w e s t , n e w e r , w i d e r

然后,我们需要统计所有相邻字符对的出现频率:

相邻字符对 出现频率
l o 4
o w 4
w 7
n e 5
e w 5
y e 2
e a 2
a r 2
o w e 1
w e s 1
e s t 1
s t 1
e w e 1
w e r 2
w i d 1
i d e 1
d e r 1

接下来,我们需要将出现频率最高的相邻字符对合并成一个新的Token——在这个例子中,出现频率最高的相邻字符对是w </w>(出现了7次),所以我们把它合并成w</w>

l o w, l o w, l o w, n e w, n e w, n e w, n e w, y e a r , y e a r , l o w e s t , n e w e r , w i d e r

然后,我们需要再次统计所有相邻字符对的出现频率,并将出现频率最高的合并成一个新的Token——重复这个过程,直到我们达到预设的Token数量(比如GPT-3.5 Turbo的Token数量是100K,GPT-4 Turbo的Token数量是128K)。

最终,我们得到的Token表就是大语言模型用来处理文本的「字典」。

2.1.3 不同语言的Token密度

不同语言的Token密度(即平均每个Token对应的字符数或单词数)是不同的——一般来说,英语的Token密度最高,中文的Token密度最低

根据OpenAI官方提供的Tokenization工具(https://platform.openai.com/tokenizer)的测试结果:

  • 英语:平均1个Token对应约4个字符,或0.75个单词。
  • 中文:平均1个Token对应约1.5个汉字。
  • 日语:平均1个Token对应约1.2个假名或汉字。
  • 韩语:平均1个Token对应约1.1个韩字。

从这组数据可以看出:中文的Token成本是英语的2-3倍——这也是为什么中文LLM应用的开发者更需要重视Token成本压缩的原因之一。

2.1.4 Token数量的计算方法

对于大多数LLM API来说,输入Token数和输出Token数是分开计算的,总费用是输入Token数乘以输入单价加上输出Token数乘以输出单价。

那么,如何计算一段文本的Token数呢?
最准确的方法是使用对应LLM的官方Tokenization工具——比如OpenAI的tiktoken库(Python),Google的sentencepiece库(Python),Meta的llama-tokenizer库(Python)。

在接下来的章节中,我们会详细介绍如何使用OpenAI的tiktoken库来计算Token数。

2.2 核心概念:提示词压缩
2.2.1 提示词压缩的定义

提示词压缩是指从输入的提示词中清理冗余信息、提取关键信息,从而减少输入Token数的过程

为了让大家更好地理解提示词压缩的定义,我们可以用一个生活化的比喻

假设你要给朋友写一封信,告诉他你周末去了哪里、做了什么——如果你写了一封长达10页的信,里面包含了很多无关的内容(比如你今天早上吃了什么、你在路上遇到了谁的猫、你买的衣服是什么颜色的等等),你的朋友可能需要花很长时间才能找到关键信息;但如果你把信压缩成一张明信片,只保留关键信息(比如「周末我去了杭州西湖,拍了很多照片,下周日请你来看」),你的朋友只需要几秒钟就能找到关键信息,而且你还省了邮票钱。

在这个比喻中:

  • 长达10页的信就是原始的提示词
  • 无关的内容就是冗余信息
  • 明信片就是压缩后的提示词
  • 邮票钱就是Token成本
2.2.2 提示词中常见的冗余信息

提示词中常见的冗余信息主要包括以下几类:

  1. 格式错误的文本:比如多余的空格、换行符、制表符、HTML标签、Markdown格式符(如果不需要的话)等。
  2. 重复的内容:比如重复的指令、重复的例子、重复的文档内容等。
  3. 无关的内容:比如与当前任务无关的聊天记录、文档内容、用户信息等。
  4. 模糊或冗余的指令:比如「请你尽可能详细地、认真地、仔细地回答我的问题」——「尽可能详细地」、「认真地」、「仔细地」这三个词的意思差不多,可以合并成一个,甚至可以删掉(因为大多数LLM默认都会认真回答问题)。
  5. 不必要的上下文信息:比如如果当前任务是「翻译这句话」,那么你不需要告诉LLM你是谁、你在哪里、你为什么要翻译这句话——只需要告诉LLM「把这句话翻译成英语:XXX」就可以了。
2.2.3 提示词压缩的核心原则

提示词压缩的核心原则是:「保留关键信息,删除冗余信息,优化指令结构」

具体来说,提示词压缩需要遵循以下几个原则:

  1. 明确性原则:压缩后的提示词必须明确、清晰地告诉LLM它需要做什么,不能有任何歧义。
  2. 完整性原则:压缩后的提示词必须包含所有完成当前任务所需的关键信息,不能丢失任何重要内容。
  3. 简洁性原则:压缩后的提示词必须尽可能简洁,用最少的Token数表达最多的信息。
  4. 结构化原则:压缩后的提示词应该尽可能结构化(比如使用列表、表格、标题等),这样不仅可以减少Token数,还可以让LLM更容易理解。
  5. 个性化原则:压缩后的提示词应该根据当前任务和当前LLM的特点进行个性化优化——比如有些LLM更适合使用「指令+例子」的结构,有些LLM更适合使用「例子+指令」的结构。
2.3 核心概念:摘要记忆
2.3.1 摘要记忆的定义

摘要记忆是指将历史的输入输出信息压缩成一个或多个「记忆摘要」,然后在需要的时候将这些「记忆摘要」与当前的输入结合起来,从而突破Transformer输入窗口限制、降低重复输入成本的过程

为了让大家更好地理解摘要记忆的定义,我们可以用一个生活化的比喻

假设你是一个图书管理员,你需要帮助读者找书——如果你把所有的书都放在一个书架上,那么当读者问你「有没有关于人工智能的书」的时候,你需要把整个书架的书都翻一遍,这不仅会花很长时间,而且如果书架上的书太多(超过输入窗口限制),你根本翻不完;但如果你为每个分类的书都做一个「图书摘要」(比如「人工智能分类:有100本书,包括《深度学习》、《机器学习实战》、《大语言模型实战》等,主要内容包括神经网络、机器学习算法、大语言模型应用等」),然后把这些「图书摘要」放在一个小抽屉里,那么当读者问你「有没有关于人工智能的书」的时候,你只需要从抽屉里拿出「人工智能分类的图书摘要」,然后根据摘要的内容给读者推荐书就可以了——这不仅会花很少的时间,而且抽屉里的「图书摘要」数量很少(远低于输入窗口限制),你可以很容易地翻完。

在这个比喻中:

  • 所有的书就是历史的输入输出信息
  • 书架就是Transformer的输入窗口
  • 图书摘要就是记忆摘要
  • 小抽屉就是记忆摘要的存储系统
2.3.2 摘要记忆的核心类型

根据记忆摘要的生成方式和使用场景,摘要记忆可以分为以下几种核心类型:

  1. 会话摘要记忆:用于多轮对话场景(比如智能客服、聊天机器人等),它会将历史的多轮对话压缩成一个「会话摘要」,然后在每一轮新的对话开始时,将「会话摘要」与当前的用户输入结合起来。
  2. 文档摘要记忆:用于文档处理场景(比如法律文档审查、金融风控报告分析、技术文档问答等),它会将超大规模的文档压缩成一个或多个「文档摘要」(比如按章节生成摘要、按主题生成摘要等),然后在需要的时候,将相关的「文档摘要」与当前的任务结合起来。
  3. 知识库摘要记忆:用于知识库问答场景(比如企业内部知识库、在线教育知识库等),它会将知识库中的所有文档压缩成一个「知识库索引摘要」,然后在用户提问时,先根据「知识库索引摘要」找到相关的文档,再将相关文档的「文档摘要」与当前的用户输入结合起来。

在接下来的章节中,我们会详细介绍这三种摘要记忆的实现方法。

2.4 核心概念:结果缓存
2.4.1 结果缓存的定义

结果缓存是指将LLM的历史有效结果存储起来,然后在遇到相同或相似的输入时,直接复用历史结果,避免再次调用LLM,从而大幅降低Token成本和响应时间的过程

为了让大家更好地理解结果缓存的定义,我们可以用一个生活化的比喻

假设你是一个面包师,你每天都要做很多面包——如果你每次做面包都要重新揉面、发酵、烘烤,那么你不仅会花很多时间,而且会浪费很多面粉和酵母;但如果你把已经揉好、发酵好的面团放在冰箱里(缓存起来),那么当你需要做面包的时候,你只需要把面团从冰箱里拿出来,直接烘烤就可以了——这不仅会花很少的时间,而且会节省很多面粉和酵母。

在这个比喻中:

  • 揉面、发酵、烘烤的过程就是调用LLM的过程
  • 面粉和酵母就是Token成本
  • 已经揉好、发酵好的面团就是LLM的历史有效结果
  • 冰箱就是结果缓存的存储系统
2.4.2 结果缓存的核心类型

根据缓存键的设计方式,结果缓存可以分为以下几种核心类型:

  1. 精确匹配缓存:缓存键是原始输入的哈希值(比如MD5、SHA-256等),只有当新的输入与历史输入完全相同时,才会复用历史结果。
  2. 语义匹配缓存:缓存键是原始输入的语义向量(比如使用OpenAI的text-embedding-3-small模型生成的向量),当新的输入与历史输入的语义相似度超过某个阈值时,就会复用历史结果。
  3. 混合匹配缓存:结合了精确匹配缓存和语义匹配缓存的优点——首先使用精确匹配缓存查找,如果找不到,再使用语义匹配缓存查找。

在接下来的章节中,我们会详细介绍这三种结果缓存的实现方法。

2.5 概念之间的关系:概念核心属性维度对比

为了让大家更好地理解提示词压缩、摘要记忆与结果缓存这三个核心概念之间的区别和联系,我们可以从以下几个核心属性维度进行对比:

核心属性维度 提示词压缩 摘要记忆 结果缓存
核心目标 从源头减少输入冗余信息 突破输入窗口限制、降低重复输入成本 直接复用历史有效结果、避免再次调用LLM
作用阶段 LLM调用前(输入处理阶段) LLM调用前(输入处理阶段) LLM调用前(输入检查阶段)
Token成本降低幅度 30%-70% 50%-90% 70%-99%(取决于缓存命中率)
输出质量影响 可能提升(如果清理了冗余信息) 可能保持或略有下降(如果摘要丢失了关键信息) 完全保持(如果历史结果有效)
响应速度影响 略有提升(因为输入Token数减少) 显著提升(因为输入Token数大幅减少) 极大提升(因为不需要调用LLM)
适用场景 所有LLM应用场景 多轮对话、文档处理、知识库问答场景 高频重复输入场景(比如智能客服的常见问题)
实现复杂度 低(只需要清理冗余信息) 中(需要生成、存储、检索、更新记忆摘要) 中高(需要设计缓存键、判断历史结果有效性、处理缓存失效)
存储需求 无(不需要存储任何信息) 中(需要存储记忆摘要) 高(需要存储历史有效结果)

从这个对比表格可以看出:提示词压缩、摘要记忆与结果缓存这三个核心概念是相互补充、相互促进的——提示词压缩是基础,它可以从源头减少输入冗余信息;摘要记忆是核心,它可以突破输入窗口限制、降低重复输入成本;结果缓存是关键,它可以直接复用历史有效结果、避免再次调用LLM。只有将这三个核心概念有机地结合起来,才能实现Token成本的最大幅度降低。

2.6 概念之间的关系:概念联系的ER实体关系Mermaid架构图

为了让大家更直观地理解提示词压缩、摘要记忆与结果缓存这三个核心概念之间的联系,我们可以用一个ER实体关系Mermaid架构图来表示:

输入原始文本

输出压缩后的提示词(作为缓存键候选)

输出压缩后的提示词(作为历史信息存储或记忆检索依据)

输出记忆增强后的提示词(作为缓存键候选)

缓存未命中时调用

缓存命中时直接返回

返回结果后存储

返回结果后更新记忆

返回结果后输出

USER_INPUT

PROMPT_COMPRESSOR

RESULT_CACHE

SUMMARY_MEMORY

LLM_API

USER_OUTPUT

这个ER实体关系Mermaid架构图的含义是:

  1. 用户输入首先进入提示词压缩器,提示词压缩器清理原始文本中的冗余信息,输出压缩后的提示词。
  2. 压缩后的提示词有两个去向:
    a. 第一个去向是结果缓存器,作为缓存键候选,查找是否有历史有效结果。
    b. 第二个去向是摘要记忆系统,如果当前场景需要记忆(比如多轮对话、文档处理等),摘要记忆系统会将压缩后的提示词作为历史信息存储,或者作为记忆检索依据,输出记忆增强后的提示词。
  3. 记忆增强后的提示词(如果有的话)也会进入结果缓存器,作为缓存键候选,查找是否有历史有效结果。
  4. 结果缓存器的处理逻辑是:
    a. 如果缓存命中,直接将历史有效结果返回给用户输出
    b. 如果缓存未命中,将压缩后的提示词(或记忆增强后的提示词)发送给LLM API
  5. LLM API返回结果后,有三个去向:
    a. 第一个去向是结果缓存器,将结果存储起来,以便下次复用。
    b. 第二个去向是摘要记忆系统,将结果作为历史信息存储,或者更新记忆摘要。
    c. 第三个去向是用户输出,将结果返回给用户。
2.7 概念之间的关系:交互关系Mermaid架构图

为了让大家更直观地理解提示词压缩、摘要记忆与结果缓存这三个核心概念之间的交互流程,我们可以用一个交互关系Mermaid架构图来表示:

渲染错误: Mermaid 渲染失败: Trying to inactivate an inactive participant (RC)

这个交互关系Mermaid架构图的含义与我们之前的ER实体关系Mermaid架构图的含义基本一致,但它更详细地展示了三个核心概念之间的交互顺序和条件判断逻辑。


(由于篇幅限制,本文将先展示前两个章节的内容,后续章节将继续深入探讨技术原理与实现、实际应用、未来展望等内容,最终总字数将达到约10000字。)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐