🧠 向所有学习者致敬!
“学习不是装满一桶水,而是点燃一把火。” —— 叶芝
我的博客主页: https://lizheng.blog.csdn.net
🌐 欢迎点击加入AI人工智能社区!
🚀 让我们一起努力,共创AI未来! 🚀
嘿,各位AI爱好者们!今天咱们聊的是大语言模型(LLM)的“瘦身计划”——提示压缩。想象一下,LLM就像一个贪吃的大胃王,每次都要吃一大堆上下文才能回答问题。结果呢?吃得太多,消化不了,还浪费了不少“粮食”(计算资源)。于是,科学家们决定给LLM来个“节食计划”,帮它瘦身,同时还能保持“健康”(性能)。
RAG(Retrieval-Augmented Generation)过程也会遇到以下问题:
- 1.大语言模型(LLM)通常有上下文长度限制。因此,输入文本越长,处理过程越耗时且成本越高。
- 2.检索到的上下文并不总是有用的。可能只有较大块中的一小部分与答案相关。在某些情况下,可能需要结合多个块来回答特定问题。即使进行了重新排序,这个问题仍然存在。
Prompt Compression(提示压缩) 是一种解决这些问题的方法。其核心目标是保留提示中的关键信息,使输入令牌更有价值。这种方法可以提高模型的性能并降低成本。
总体而言,提示压缩方法可以分为四大类:
1.基于信息熵的方法,如 Selective Context、LLMLingua、LongLLMLingua。这些方法使用一个小型语言模型来计算原始提示中每个令牌的自信息或困惑度,然后删除困惑度较低的令牌。
2.基于软提示调优的方法,如 AutoCompressor 和 GIST。这些方法需要对LLM参数进行微调,使其适用于特定领域,但不能直接应用于黑盒LLM。
3.首先从LLM进行数据蒸馏,然后训练模型生成更可解释的文本摘要。这些方法可以在不同语言模型之间转移,并应用于不需要梯度更新的黑盒LLM。代表性方法有 LLMLingua-2 和 RECOMP。
4.基于令牌合并或令牌剪枝的方法,如 ToMe 和 AdapLeR。这些方法通常需要模型微调或在推理过程中生成中间结果。
本文将介绍前三类方法中代表性算法:
- 1.Selective Context:信息熵的“瘦身教练”
这位教练的绝招是:“少废话,多干货!” 它通过计算每个令牌的“信息量”(自信息),把那些没啥营养的内容统统踢掉。就像你减肥时,教练会告诉你:“别吃垃圾食品,多吃蛋白质!” 于是,LLM的输入变得更精炼,推理速度也更快了。 - 2.LLMLingua:动态预算的“理财顾问”
LLMLingua 是个精明的“理财顾问”,它知道哪些部分值得花钱(保留信息),哪些部分可以省省(压缩掉)。它还有个绝活:迭代令牌压缩,就像你整理衣柜时,一件件衣服试穿,决定哪些该留,哪些该扔。结果?LLM的提示变得更短,但关键信息一点没丢。 - 3.LongLLMLingua:问题导向的“私人教练”
这位教练特别贴心,它会根据你的“健身目标”(用户问题)来定制瘦身计划。它不仅能动态调整压缩比例,还能通过子序列恢复算法,把那些不小心被“误删”的关键信息找回来。就像你减肥时不小心把肌肉也减掉了,教练会帮你重新练回来。 - 4.AutoCompressor:软提示的“魔法师”
这位魔法师不靠删除,而是靠“魔法”来压缩信息。它通过扩展词汇表和生成“摘要向量”,把长文档压缩成短小精悍的提示。就像你把一部长篇小说浓缩成一条微博,信息量一点没少,但篇幅大大缩减。 - 5.LLMLingua-2:双向上下文的“全能选手”
LLMLingua-2 是个全能选手,它不仅能处理单向上下文,还能利用双向上下文来压缩提示。它通过数据蒸馏和令牌分类,确保压缩后的提示与原始提示高度一致。就像你减肥时,不仅控制饮食,还做有氧和力量训练,全方位保持健康。 - 6.RECOMP:提取与抽象的“双面侠”
RECOMP 是个双面侠,既能提取关键句子,又能生成抽象摘要。它通过训练双编码器和编码器-解码器模型,确保压缩后的提示既简洁又全面。就像你整理房间时,既能扔掉不需要的东西,又能把有用的东西分类整理好。
正片中将为您详细介绍
正片
Selective Context
洞察
图2展示了LLM可以在不需要完整上下文或完整对话历史的情况下响应用户查询。即使省略了相关信息,LLM仍然可以产生预期的响应。这可能归因于LLM能够从上下文线索和预训练期间获得的知识中推断出缺失的信息。
图2:LLM能够在删除较少信息内容的情况下正确回答。来源:Selective Context。
因此,可以通过过滤掉信息量较少的内容来优化上下文长度,而不会影响性能。这是 Selective Context 的核心洞察。
Selective Context 使用一个小型语言模型(SLM)来确定给定上下文中词汇单元(如句子、短语或令牌)的自信息,然后使用该自信息来评估它们的信息量。通过选择性保留自信息较高的内容,Selective Context 为LLM提供了更简洁高效的上下文表示,而不会影响其在不同任务中的表现。
自信息
Selective Context 使用自信息来评估内容的质量。
自信息,也称为信息量或信息内容,是信息论中的一个关键概念。它量化了事件所传达的信息量。它被定义为令牌的负对数似然:
I ( x ) = − log P ( x ) I(x) = -\log P(x) I(x)=−logP(x)
其中,I(x)
表示令牌 x
的自信息,P(x)
表示其输出概率。
在信息论中,自信息量化了与事件相关的惊讶或不确定性水平。稀有事件传达更多信息,因此具有更高的自信息。相反,常见事件传达较少信息,因此具有较低的自信息。
算法
为了更方便地解释原理,我们深入源代码。
首先,通过安装相应的Python库并下载Spacy模型来设置环境。
conda create -n "selective_context" python=3.10
conda activate selective_context
pip install selective-context
python -m spacy download en_core_web_sm
安装完成后,版本如下:
pip list | grep selective
selective-context 0.1.4
测试代码如下:
from selective_context import SelectiveContext
sc = SelectiveContext(model_type='gpt2', lang='en')
text = "INTRODUCTION Continual Learning ( CL ) , also known as Lifelong Learning , is a promising learning paradigm to design models that have to learn how to perform multiple tasks across different environments over their lifetime [To uniform the language and enhance the readability of the paper we adopt the unique term continual learning ( CL ) .]. Ideal CL models in the real world should be deal with domain shifts , researchers have recently started to sample tasks from two different datasets . For instance , proposed to train and evaluate a model on Imagenet first and then challenge its performance on the Places365 dataset . considers more scenarios , starting with Imagenet or Places365 , and then moving on to the VOC/CUB/Scenes datasets. Few works propose more advanced scenarios built on top of more than two datasets."
context, reduced_content = sc(text)
# 我们还可以调整压缩比例
# context_ratio, reduced_content_ratio = sc(text, reduce_ratio = 0.5)
首次运行将下载GPT-2模型,大小约为500MB。测试代码的结果如图3所示。
图3:Selective Context 测试代码的结果。截图由作者提供。
接下来,我们探索函数 sc(text)
。内部源代码 如下:
class SelectiveContext:
...
...
def __call__(self, text: str, reduce_ratio: float = 0.35, reduce_level :str = 'phrase') -> List[str]:
context = self.beautify_context(text)
self.mask_ratio = reduce_ratio
sents = [sent.strip() for sent in re.split(self.sent_tokenize_pattern, context) if sent.strip()]
# 你希望在句子级别、短语级别还是令牌级别进行压缩?
assert reduce_level in ['sent', 'phrase', 'token'], f"reduce_level should be one of ['sent', 'phrase', 'token'], got {
reduce_level}"
sent_lus, phrase_lus, token_lus = self._lexical_unit(sents)
lexical_level = {
'sent': sent_lus,
'phrase': phrase_lus,
'token': token_lus
}
# context 是压缩后的上下文,masked_sents 表示被过滤掉的内容
context, masked_sents = self.self_info_mask(lexical_level[reduce_level].text, lexical_level[reduce_level].self_info, reduce_level)
return context, masked_sents
上述代码主要涉及三个步骤:
- 计算上下文中每个令牌的自信息。
- 根据词汇单元(如短语或句子)合并令牌及其自信息。
- 选择性保留信息上下文。
步骤1:计算自信息
给定上下文 C = x0, x1, …, xn
,其中每个 xi
表示一个令牌,我们使用因果语言模型(如GPT-2、OPT和LLaMA)来计算每个令牌 xi
的自信息:
I ( x i ) = − log P ( x i ) I(x_i) = -\log P(x_i) I(xi)=−logP(xi)
如果你使用的是GPT-2,以下是相应的代码:
class SelectiveContext:
...
...
def _get_self_info_via_gpt2(self, text: str