0%

最近吴恩达出了一个小课程,传送门: Building and Evaluating Advanced RAG ApplicationsB站也有人搬运了,有中英文字幕。最近也正好在做RAG相关的项目,看到这个课程里有一些新的东西,权当在这篇博客里总结记录。

另外还推荐阅读一篇综述Trends in Integration of Knowledge and Large Language Models: A Survey and Taxonomy of Methods, Benchmarks, and Applications, 该综述的第三章详细介绍了retrieval augmentation的方法。我这篇博客会首先理顺一些理论,然后再介绍吴恩达课程里的知识(个人认为吴大佬出的关于LLM的一系列shot course可食用性不够高,比如上面说的这个RAG相关的课怎么看都觉得是在推广LlamaIndex这个框架,对于原理一句话带过,很多细节不清楚)。

3.2节提到的两个工作值得注意:

  1. Query2doc

Query2doc prompts the LLMs to generate a pseudo-document by employing a few-shot prompting paradigm. Subsequently, the original query is expanded by incorporating the pseudo-document. The retriever module uses this new query to retrieve a list of relevant documents.

  1. Rewrite-Retrieve-Read

Different with Query2doc,they adopt a trainable language model to perform the rewriting step

在抽取的context的使用上,我们一般的认知是加入到prompt里,告诉LLM根据这个context回答某个query,这篇综述在3.2节还概括介绍了另外两种使用knowledge的方式:

image-20231205145030752

我个人认为第二种方式实操性差一点,第三种和第一种应该是大家会普遍采取的方式,第二种需要更多精细的prompt设计。


以下为课程相关的 ,传送门: Building and Evaluating Advanced RAG Applications. 课程笔记参考Frameworks in Focus: ‘Building and Evaluating Advanced RAG’ with TruLens and LlamaIndex Insights

构建 Construction

简单的RAG构建的资料太多太多了,最简易的RAG构建可以参考Simple RAG for GitHub issues using Hugging Face Zephyr and LangChain.

RAG中两个最核心的模块: Retrieval 和 Generation (Read),内部都有很多可以enhance的地方。这里列举一些可以查阅的资料,内整理了一些对于RAG的enhancement的点:

img

上面这张图来自于langchain的cookbook,蓝色部分是作者认为all possibilities for system enhancement。我这里只对一些我关注的技术做整理和探索。

Chunking

有一堆文档,如何将这些文档切分成“完美的”chunk。

我比较关注的是对PDF格式的文件的处理,比较有参考价值的资料:5 Levels Of Text Splitting,内介绍的level1和level2的切分方式都是现在比较常见的。

对于PDF中的图片,也有博客进行了探索

对于PDF中table的处理,一个可行的方式是用Unstuctured这个library抽取出HTML格式的table,然后用LLM将其summary一下,那么对于retriveal的时候,是将summary的vector和query的vector去进行比对的,如果match上了,就会把原生的HTML的表格表示输入给LLM去生成最终的答案。做法详见Semi-structured RAG

对于PDF中图片的处理,也是对image先用LLM总结描述一下。其实5 Levels Of Text Splitting里面介绍的方法都是可以的,但我觉得实操会有一定的难度。因为PDF中的images是会被单独放到一个文件夹里的,前后夹的文本其实是丢失了,这样不可避免的就会丢失一定的语义信息。表格其实还好,但是很多时候贴了一张图片之后,后面的文字基本上是相关联的。这时候需要把图片的信息和后面的文字结合起来就需要知道每一个图片所在pdf的位置,我目前看到的资料还没有很好的解决这个问题。

评估 Evaluation

该课程建议从三个维度来评测一个RAG Application的好坏:

image-20231205105234142
  • 问题和回答的相关性
  • 根据问题抽取出来的context和问题的相关性
  • 回答和context的相关性

该课程主要目的是宣传自己的框架Trulens(目前该框架在github有1.8k star,热度不咋高),如果想了解Evaluation的全景知识建议看一下Retrieval-Augmented Generation for Large Language Models: A Survey

上面的review中很重要的两个总结:

  1. 上面所说的三个quality score如何计算?可以看到仍然是我们熟悉的一些metrics
image-20240228142327120
  1. 现有的可用评估框架有哪些?
image-20240508133011839

我们上面提到的课程里使用的就是该表格中列出的TruLens. 上面这张表格总结的还不是特别全面,而且没有datasets的整理,24年新出的文章CRUD-RAG: A Comprehensive Chinese Benchmark for Retrieval-Augmented Generation of Large Language Models 中对这部分做了整理:

image-20240228152011016

这里做一下update,在作者写这篇文章时,综述Retrieval-Augmented Generation for Large Language Models: A Survey还未对评估的数据集做整理,但最近一期3月的论文更新中已经有了这部分的内容。主要增添了对于每一个评测任务的数据集的整理。

其中[7]就是RGB,它数据的生成是利用一系列收集到的news report,然后利用LLM来基于这些report生成relevant events,questions和answers。[38]是ARES,利用flan-t5来生成的一系列合成query和answer。其中比较重要的一列是是否有金标准,也就是上图中的倒数第二列。 13,12以及38分别是TruLens-Eval,RAGAS和ARES,这三个是不需要金标准的,不过代价是需要用到Chatgpt来做自动评估呀,这些可都是白花花的银子。使用Trulens-Eval都是需要配置openai的API的。

LangChain Benchmark

对于想要快速去搭建一个评估RAG的框架的人来说,最好是有现成的可以直接用的评估体系,省去自己搜集数据以及编写各种计算metrics的麻烦。langchain提供了这么一个benchmark包,介绍传送门,截止到24年3月,该库已经包含了三个开源数据集,两个是上面介绍的python文档和pdf的QA问答数据集,还有一个是正在开发中的基于PPT的问答数据集:

image-20240314142718109

这份langchain官方教程里用了好多新的tool,其中一个就是Smith, 在notebook中clone的所有数据集都可以在这个平台上看到,有点像console。LangChain Docs Q&A的数据长这样:

1
2
3
4
{
"question": "How can I parallelize calls in LangChain?",
"answer": "To make parallel calls from a LangChain object, use the 'batch()' (or asynchronous 'abatch()') method. You can also use a `RunnableParallel` object."
}

langchain-benchmark总体而言还处于初期,对于retrival的task也只有三个数据集做支撑,定制化的程度不是特别高。具体可以参考langchain-benchmark官方教程

今天在看huggingface官网文档的时候又看到官方出了新的evaluation的guidebook,这份代码里写的相当详细,不再是一个普通的RAG评估流程,还介绍了评估数据集的生成方式,最重要的是还做了数据集的filtering,这份教程对于企业内部生成自己的评估数据集是有很大的参考价值的。

CRUD

现在我们花点篇幅来详细说一下CRUD这个中文评估benchmark。作者的出发点在于评估一个RAG的应用,要区别于评估一个LLM模型,下面这句话是作者从四个维度来评估RAG的出发点:

Lewis et al. [25] argue that the core of RAG systems is their interactive way of combining LLMs with external knowledge sources

RAG和LLM的交互方式,也就是RAG帮助LLM做了哪些东西让LLM能更好的回答问题,作者觉得是这四个方面:Create,Read,Update和Delete.

image-20240314135617343

Read很常见,RAG会从知识库中搜集更多的信息来供LLM回答问题,Update主要是为了解决LLM无法回答具有时效性的问题,或者当时训练模型时没有加入的信息,Delete这点其实在我看来有点牵强。Read和Update这两点确实是评估一个RAG很关键的方面。

做RAG的评估,最重要的两点就是:

  1. 数据集的准备,作者打算从上面四个维度去衡量一个RAG的好坏,那就得准备相应的数据集,这部分的工作是我们平时自己做测评的重点
  2. 测评metrics的选择,除了我们熟知的BLEU,ROUGE,还有bert判分。其中还有作者基于QuestEval创造的RAGQuestEval评分。这个metrics还挺有意思的。这里放在这里详细介绍下:

首先基于ground truth sentence生成一系列的问题,生成问题的prompt设计是这样的:

你是一位新闻编辑,现在,你被提供了一篇新闻,请先从新闻中抽取出你认为重要的所有关键信息(通常为一个关键词,包含文章中的所有实体和名词性短语),然后,根据关键信息设计几个问题,考验大家能否正确回答问题。用json的形式返回答案。以下是个例子。

新闻:2014年,全国新增并网光伏发电容量1060万千瓦,约占全球新增容量的四分之一。其中,全国新增光伏电站855万千瓦,分布式205万千瓦。据统计,2014年中国光伏发电量达到了250亿千瓦时,同比增⻓超过 200%。

{json_response}

现在你需要为这篇新闻设计问题,尽量涵盖大多数关键信息,请尽量让答案可以用两三个词回答,答案不能太长,key_info包含文章中的所有实体和名词性短语,question与key_info一一对应,数量一致,输出用json的格式:

{news}

注意这里先让LLM抽取文章中的所有实体和名词性短语作为关键信息,question是根据这些关键信息生成的。问题生成完之后分别用reference sentence和ground truth sentence作为context,去让LLM回答上面生成的问题。如果遇到无法回答的问题就让LLM答“无法回答”. 最后一步针对回答的结果计算precision 和 recall。

该文章作者在数据的处理方面,选择去爬取网上最新的news,然后用这8000个新闻建立了三个task的数据集:open-domain multi-document summarization(考察RAG的delete能力),text-continuation(考察RAG的Generation能力),question-answering(read能力)和hallucination modification(考察RAG的Update能力)。

其实仔细看上面review中的总结,CRUD这篇文章里提到的应该考察RAG的“哪些能力”还是不够全面的,而且我个人认为CRUD里面仅仅是以end-to-end的方式计算generated anwser和gound truth之间的差距也是不太可取的,它没有涉及到RAG里面很重要的一个环节:retrieval。更全面的方式应该是计算三种quality scores(具体参考review的介绍):

  • context relevance: query 和 context 的关系
  • faithfulness(groundness):answer 和 context 的关系

This measures the factual consistency of the generated answer againest the given context

主要用于检测LLM的幻觉。这里博客 对trulens的计算方式做了详细介绍,注意它里面的prompt的设计。Ragas框架对于faithfulness的计算查看Faithfulness,也是用chatgpt来把answer中的statement拆开然后分别去与召回的context做对照,可以查看ragas框架计算faithfulness的代码.

My spicy comment: trulens和ragas两者还挺类似的,就是ragas除了计算faithfulness,还多了好几个metrics,如context precision, context recall, context entity recall。其实就是把context relevance这个metric拆分地更细了。不仅如此,ragas把answer relevance也拆的更细了,它包含了answer correctness, answer relevance和answer similarity. 相比较而言,ragas在笔者写这篇文章的时候,star数是要比trulens多的,前者4.8k,后者1.8k。而且issues明显要多于trulens,直觉上看应该是ragas用的人比较多。

在整理这部分metrics的时候,也搜了一下大家都在用什么样的框架来评估自己的RAG,看到reddit上也有人有这样的疑问Why is everyone using RAGAS for RAG evaluation? For me it looks very unreliable, 我觉得其中一个回答比较贴合当下对于RAG评估的一个现状:

There is no proper techincal report, paper, or any experiment that ragas metric is useful and effective to evaluate LLM performance. That's why I do not choose ragas at my AutoRAG tool. I use metrics like G-eval or sem score that has proper experiment and result that shows such metrics are effective. I think evaluating LLM generation performance is not easy problem and do not have silver bullet. All we can do is doing lots of experiment and mixing various metrics for reliable result. In this term, ragas can be a opiton... (If i am missing ragas experiment or benchmark result, let me know)

https://www.reddit.com/r/LangChain/comments/1bijg75/comment/kvoj1q8/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button

  • answer relevance: answer 和 query 的关系

至于计算出上面这三个方面的数值,有多种方式。有用LLM的,比如Trulens就是用的chatgpt,也可以用claude,参考见基于大语言模型知识问答应用落地实践 – 使用 TruLens 做自动化 RAG 项目评估测试。也有直接计算相似度的,比如我们熟悉的bert score,rouge-L。review在这里也进行了整理:

image-20240508132450374

Customization模式

其实在具体的业务场景下,如果已经搭建了一套RAG系统,如何来评估这个RAG系统的好坏,更合理的方式还是需要用自己的数据来测评,如果只是用一些公开的benchmark,如上面提到的langchain benchmark,还是CRUD提出的以新闻为数据的benchmark,都有一点不那么让人信服,毕竟你费劲巴拉地搭建一个RAG的chatbot,还是要在自己的具体的业务场景表现好,客户才会买账吧。

但更多情况下,业务场景下往往是缺少金标数据集的,这时候就需要去针对自己的业务场景去生成一些“合成”数据集。我们可能基于的就是一堆的业务文档,这些文档有的是PDF,有的可能是word,也会有PPT,如果根据这些文档去生成自己的评测数据集,这样基于这个评测数据集我们再去“调整”我们RAG中的各个能影响RAG performance的环节:embedding模型选择哪个,LLM选择哪个?chunking应该如何优化等等?加了rewrite和rerank等techniques之后有没有让RAG的效果变好,这里的变好仅仅是指在我们自己的业务数据上变好,而不是在其他开源的benchmark上,这样才具有一定的说服力。

参考博客RAG Evaluation, 文章介绍了一种根据documents生成synthetic evaluation dataset的办法,里面还加了一些tricks:如何用一个critique agents去筛选QA。不过该篇文章evaluation环节仅仅计算了answer和query的关系(faithfulness),它给出的理由是:

Out of the different RAG evaluation metrics, we choose to focus only on faithfulness since it the best end-to-end metric of our system’s performance.

RAG 中的PainPoints

参考:

上面视频对应的博客

image-20240725140423246
image-20240725140443402

写这篇博客的初衷是自己一直以来都在关注supervised finetuning,但对强化学习这一块一直都没有过多的涉猎,一方面是因为它是大模型技术模块里相对成本比较高的过程,还有一方面是我对强化学习没有系统性的学习,觉得有一丢丢的难理解,躺在list里的斯坦福的强化学习课程也一直搁浅,传送门: cs234n, 课程视频和PPT都是可以免费下载的。

我这篇博客主要是受llama2模型的paper的启发,觉得这篇文章在RLHF方面写的非常之细致,并且代码也进行了开源,可以对照代码进行学习. 移步这篇文章的3.2节。当然也有很多博客详细介绍了这篇文章的强化学习部分的细节,参考【LLM】Meta LLaMA 2中RLHF技术细节

首先RLHF包含了两个步骤,第一个就是训练一个reward modeling来对LM生成的回答进行打分,这个分数是一个数值型的数据;第二部分就是用这个RM去调整我们的LM,使得LM能output更符合人类期望的回答。也有作者将SFT放到了RLHF的第一阶段,比如A Survey of Large Language Models 的5.2.3节将RLHF分为了三阶段:

image-20231011143645416

不过我认为SFT还是隔离开讲比较好。

Reward Modeling

数据

prompt好准备,那么打分这个就要靠人来打分了,人打分有一定的主观臆测性,所以就换成了比较哪一种回答比较好,像LLAMA2的做法就是分了四个等级:significantly better, better, slightly better or negligibly better / unsure。

RM模型

hugging face blog 中有一段话:

这个过程中一个有趣的产物是目前成功的 RLHF 系统使用了和生成模型具有 不同 大小的 LM (例如 OpenAI 使用了 175B 的 LM 和 6B 的 RM,Anthropic 使用的 LM 和 RM 从 10B 到 52B 大小不等,DeepMind 使用了 70B 的 Chinchilla 模型分别作为 LM 和 RM) 。一种直觉是,偏好模型和生成模型需要具有类似的能力来理解提供给它们的文本

RM的训练

直观上理解我们现在有了prompts,也有了这些prompts的generation在我们的LM上的的generation的评分ranking,那么怎么来用这些数据训练呢?

就拿LLAMA2的做法来说,它用了一个和预训练模型一模一样的模型作为RM的初始模型,唯一不同的是将LM中用作预测下一个token的分类头替换成了另一个可以输出分值的回归头就像下面这样:

上图出自state of GPT。

loss的计算采用的是ouyang 2022的Training language models to follow instructions with human feedback 提出的计算方式:

image-20231011143044591

其中r是RM输出的标量值代表分值。不过llama2的做法在这个loss基础上加了一个margin,刚刚提到它在人工标注这些generation的时候分了四个档次,有的回答会比另一个对手super better,有的只是稍微好一点,所以这种“好的程度”可以在loss中区分出来,所以作者在loss的的计算里加了一个margin:

image-20231011143054960

super better的就用一个比较大的m值。

RL Fine-tuning

推荐阅读

最近框架vLLM在LLaMA-13B以及7B模型上的推理速度相比较Tranformers有了质的提升。之前写过一篇大模型量化技术的文章,量化技术算是大模型出来初期大家使用的普遍比较多的方法之一,这里强调一点,我这里所说的模型加速是指在推理阶段我们让模型运行的更快,而且返回的结果要和原来的大参数模型差不多。这里重点强调的原因是我在看一些资料的时候发现有不少博客分享的是在模型训练阶段或者finetune阶段如何让模型训练的更快,这里就涉及到efficient finetuning的技术(p-tuning, prefix-tuning等),我这篇博客只关注模型训练完成之后如何在推理阶段让它更快,在同样时间内处理更多sequence(吞吐量througout),显存占用更低。大模型推理加速技术为什么这么受关注还是因为想在一些消费级别显卡上部署一个大模型为用户所用,而不是仅仅停留在实验室阶段。

我在看这个topic下的文章的时候,发现往往一些方法提出来有一些是减少了显存占用,有一些是提高了吞吐量(跟减少latency一回事),所以具体在实现时应用哪个办法加速你的模型推理还要根据实际情况去对比分析,或者你每个方法都尝试一下也行。当然又一些方法集成地很好,比如量化模型中的GPQT已经集成进transformers库,用起来很方便。如果碰到一些很复杂的,比如prune“剪枝”就有点难以快速验证。

vLLM 暂时还没有文章发出来,我在谷歌搜寻有没有review介绍大模型加速文章的时候也没找到很新的文章,不过找到了一篇微软在23年发布的LLMA, 我本来觉得思想类似,但是后来仔细看了下文章发现并不是一回事,我觉得文章标题有点误导人,起的太大了,本质上文章其实就是发现了decoding时候生成的句子和之前的句子有一部分的文字重叠,所以作者考虑这部分重叠内容其实不需要让模型再去decoding了,那就想了个办法,在decoding的时候把前面一步的结果保存下来,比较当前步骤和前一步骤token的差距,差距小的就不再进行计算了

一点不成熟的想法:这个文章思路可取,但创造力有限。

不过它在introduction章节介绍了四种比较通用的加速方法:quantization, pruning, compression and distillation,同样的分类也可以在A Comprehensive Survey on Model Quantization for Deep Neural Networks文章中找到, 不过两者介绍的有一点点的不同:

image-20230828093646830

Survey将四种技术统一包含在了模型压缩里。我觉得review里这种分类比较合理,因为微软这篇文章compression引用的文章是

Bert-of-theseus: Compressing bert by progressive module replacing, compression应该是一种统称。后面我看到知乎有一篇文章更详细的介绍了大模型的推理优化技术,它这个分类也符合我的理解,模型压缩(model compression)里包含模型量化,pruning,low-rank approximation和知识蒸馏这些技术。而且知乎这篇文章的分类也符合survey里的介绍:

In designing accelerators, researchers concentrate on network compression, parallel processing, and optimizing memory transfers for processing speed-up.

我这里做个思维导图总结一下:

image-20230830133030762

题外话,根据LLMA文章的意思,它提出的这种帮助reduce the serving cost的方式不属于上述任意一类,它认为以transformer为基础的生成模型,推理阶段主要消耗的时间瓶颈在autoregressive decoding。这里贴原文便于理解

While there are general methodologies that help reduce the serving cost of LLMs such as quantization(Dettmers & Zettlemoyer, 2023), pruning (Frantar & Alistarh, 2023), compression (Xu et al., 2020) and distillation (Wang et al., 2020), the inference efficiency bottleneck of these transformer-based generative models (e.g., GPT) is mainly associated with autoregressive decoding: at test time, output tokens must be decoded (sequentially) one by one, which poses significant challenges for the LLMs to be deployed at scale. 这里补充介绍一下AI模型中精度,你会在各种场合下碰到FP32,FP16,int8,int4等名词。

32-bit:也称全精度(Single precision),fp32, 采用32位(4字节)来对数据进行编码。能够表达的数据动态区间是 \[ 1.4 * 10^{-45} - 1.7 * 10 ^ {38} \]

Float_example

16-bit:半精度(half precision),fp16, 能够表达的数据动态区间是 \[ 6 * 10^{-8} - 65504 \]

BF-16: 也称为半精度,可以表达比FP16更大的数,但是精度比fp16差

image-20230830145435142

int8,int4顾名思义就是 8bit和4个bit来表示数字,int8的表达数值范围是 -128~127 why,无符号范围是0~255,int4的表达数值范围是-8~7。注意这里的计算方式和上面的浮点数可不一样,上面的浮点数中的8bits的exponent是指数表达,所以将指数那一部分的表达加和之后还要取2的指数,见具体计算. 再详细一点的介绍见hugging face 博客

模型压缩 model compression

Quatization 量化

参考文献

模型的量化可以分为两种方式:

  1. post-training quantization 模型训练好之后,将模型的参数们降低精度
  2. quantization-aware Training 在模型训练的过程中使用量化的方式,优点是比前者performance要好,但是需要更多的计算资源去训练

量化顾名思义要把原来用高精度表达的值映射到一个低精度的空间,目标呢就是让模型的performance不能有很大的降低。那如何映射和对哪一些值进行映射,这两个方向是现在量化方法的主攻方向。

很典型的LLM.int8()算法,不是大刀阔斧地对所有值一次性量化,也不是把矩阵中所有值一起量化,而是先找出那些离群值,然后对这些离群值再按照居正中行列来进行量化:

LLM.int8()

最重要的是上面那一部分。计算拆解见大规模 Transformer 模型 8 比特矩阵乘简介

GPTQ

读者可以自行阅读GPTQ的原文来了解它具体是如何做的,我喜欢找一些其他的文章来看别的作者是如何介绍自己的同行作品的,比如下面的这篇文章SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 的第六章节related work里这样比较自己的smoothQuant和其他的量化模型方法的:

GPTQ (Frantar et al., 2022) applies quantization only to weights but not activations. GPTQ这种方法只对weights做了量化,并没有对激活值做量化(我个人认为虽然这是事实,但有点硬凹的意思,因为对activations做量化映射并不会加速很多)

LLM.int8() uses mixed int8/fp16 decomposition to address the activation outliers. However, such implementation leads to large latency overhead, which can be even slower than FP16 inference. 意思是LLM.int8()这种方法只是减少了显存占用,并没有减少推理延迟,说白了就是慢,runtime没提高

Sparsity

low-Rank Approximation

Lora

用lora的方式替换全参数微调大模型已经成为好多研究者的选择,一个是它的确有效的降低了训练参数的比例,第二个很大的原因是它的performance还不错,也就是只训练低秩的那些参数矩阵完全可以得到一个高质量的模型.

We propose Low-Rank Adaptation, or LoRA, which freezes the pretrained model weights and injects trainable rank decomposition matrices into each layer of the Transformer architecture, greatly reducing the number of trainable parameters for downstream tasks

从文章的介绍可以看出,它主要是应用于transformer架构中的layer中,这个layer包含self-attention,也包含MLP。只要有矩阵乘的地方都可以用lora。

lora图示

具体的在transformer中如何使用呢?我们知道transformer架构中涉及矩阵运算的地方:

image-20231228171113210

在上图中的self-attention中涉及四个weights矩阵:(Wq, Wk, Wv, Wo)。在feed-forward(lora原文中叫MLP,我觉得原因在于这里是有两个线性变换的),具体看attention is all you need 原文:

image-20231228171318056

所以每一个encoder的layer都有6个weights矩阵可以实施lora。lora的作者仅仅对attention weights做了lora,更简化的只是对其中的Wq和Wv做了lora变换。实现上由于现在有了peft库,只是几句话就能实现对这两个矩阵进行lora:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def create_peft_config(model):
from peft import (
get_peft_model,
LoraConfig,
TaskType,
prepare_model_for_int8_training,
)

peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
inference_mode=False,
r=8,
lora_alpha=32,
lora_dropout=0.05,
target_modules = ["q_proj", "v_proj"] # 这里仅仅对Q和V的变换矩阵做lora
)

# prepare int-8 model for training
model = prepare_model_for_int8_training(model)
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
return model, peft_config

# create peft config
model, lora_config = create_peft_config(model)

Knowledge Distillation

知识蒸馏出现的比较早,一开始也是在Bert上流行起来的。在LLM这种非常多参数的模型上用的不多。

这里罗列我看的对我理解很有帮助的文章:

Continuous Batching

参考文献:

vLLM

vllm这个包本质上是将显存GPU高效利用了(PagedAttention技术),还有上面提到的LLMA. 不过它们的思路其实大同小异,本质上是为了解决transformer的decoder在文本生成时自回归结构带来的无法并发的开销。推荐阅读为什么现在大家都在用 MQA 和 GQA?

图片

那么既然时间开销都在右边这个decoding的阶段,那就想办法解决它。那就是刚刚那篇文章介绍的KV Cache。作者提到的内存墙的问题也是这个问题的切入点,如何让计算单元更迅速的从存储单元获取数据,Paged Attention和Flash Attention都是来解决这个问题的。MQA的本质是减少了数据读取次数,第一次读取进来的K和V给所有的Q用,就放在缓存里。文章里详细讲解了MQA和GQA,这里不再赘述,但有一点值得注意的是,这两种办法再使用的时候可能并不能只是在推理的时候直接改变结构,也许要像作者说的那样:

如果要用 MQA 和 GQA,可以是从头训练的时候就加上,也可以像 GQA 论文里面一样,用已有的开源模型,挑一些头取个 mean 用来初始化 MQA 或 GQA 继续训练一段时间。

Text Generation Inference

Transformer结构优化

经典的Transformer架构出来之后,很多工作都在这个架构之上进行了魔改,希望能加快transformer的推理速度,推荐阅读survey Efficient Transformers: A Survey , 目前该review已经是第三版本,最新版本是2022年3月份出的,所以内容里没有flash Attention以及一些更新的技术,希望作者快快更新第四版本的review,技术迭代太快了,亟需大神肝的review总结。

大部分Transformer结构改进的方法的目标都是为了降低GPU的显存占用,也就是提高运算效率,将GPU的运算效率拉满,这就涉及到很底层的对于计算机系统结构的知识。

flash Attention

Flash Attention (Fast and Memory-Efficient Exact Attention)详细介绍可以阅读ELI5: FlashAttention,这是除了了multi-query attention技术之外用的比较多的加速推理的方式,当然Paged Attention算是vllm火起来之后的后起之秀。当然也可以阅读paper

attention on GPT-2

在medium的这篇博客里作者首先澄清两个概念,一个是FLOPs(每秒钟浮点运算次数)和IO,前者在GPU的更新换代的情况下获得了高速发展,而GPU的计算单元和显存间的通信却没有获得同样数量级的增长。而从上图可以看出来(原文paper中的),Attention的计算过程中大部分时间都是memory-bound导向的运算,而计算密集型的操作比如矩阵乘法其实只占了耗费时间的一小部分。

传统的attention计算步骤:

image-20230829162652549

注意这里的HBM是:

image-20230829162732067

最上面一层是GPU的缓存,中间是高带宽内存,可以理解为GPU的显存,也就是你去买显卡,标注在显卡上的存储,这部分存储会大一点,运算单元需要从这里拿数据到计算单元去计算,可以直接交互,也可以先存储在缓存SRAM内,缓存会比HBM快很多。

从标准的attention计算看到有很多不需要把计算中间结果写回HBM的环节。至于FlashAttention计算推导部分我看了上面的英文博客和从 FlashAttention 到 PagedAttention, 如何进一步优化 Attention 性能,还是没能理解,感兴趣的小伙伴还是自己去知乎这篇文章里好好看一下。

Paged Attention

FLAT Attention

并行 Parallel Processing

推荐阅读