LLM学习笔记(二)
8. 推理
server side batch是推理服务的标配(以提升server侧吞吐量为目的).
测试llama-2-13B的量化性能, 目前测试结果比较理想的是vLLM + AWQ (batch) 和Transformer + AWQ (single)。最快的是tensorrtllm awq。
8.1. 推理框架-TGI
https://www.zhihu.com/question/625415776?utm_id=0
HuggingFace推出。
8.2. 推理框架FasterTransformer
英伟达推出,后续推出了TensorRT-LLM后,就不再维护FasterTransformer了。
8.3. 选择推理框架的维度
并非有1个推理框架(例如vLLM,TensorRT-LLM,TGI,DJL等等)适合所有模型,同一个模型在不同的推理框架上可能表现不一样。
部分参考数据:
- vllm,g5 ,LLama2-7b 跑下来 290 token/s
- vllm的最大优势就是吞吐很好,且在batch 变大的情况下,latency的增加比较小
9. Chain of Thought
基本形态:one-shot prompt,给出一个step by step解决问题的例子:
其他形态:
- Zero-Shot-CoT:prompt末尾加”Let’s think step by step”。使用非常简单,但是效果不一定有few-shot好
- Manual-CoT:使用few-shot,在输入问题之前,手动设计一些问题和答案的样例(样例的答案给出中间推理步骤),这些问题和答案都需要手动构造,所以叫 Manual-CoT。很明显,要想模型效果好,需要投入一定人力成本
- Auto-CoT:Auto-CoT 其实也是受到了 Manual-CoT 的启发,既然 Manual-CoT 比 Zero-Shot-CoT 的性能要好,而且性能好的关键就在于人工设计的问题、中间推理步骤和答案的样例,那么就可以考虑将这部分进行自动化,从而节省人工成本
下面是一个Auto-CoT的例子:
Auto-CoT 包括两个主要阶段:(i)问题聚类:将给定数据集中的问题划分为几个聚类;(ii)演示抽样:从每个聚类中选择一个代表性问题,并使用简单的启发式方法使用 Zero-Shot-CoT 生成其推理链。总体过程如上图所示。
通过多样性选取有代表性的问题,对于每一个采样的问题拼接上“Let’s think step by step”(类似于 Zero-Shot-CoT )输入到语言模型,让语言模型生成中间推理步骤和答案,然后把这些所有采样的问题以及语言模型生成的中间推理步骤和答案全部拼接在一起,构成少样本学习的样例,最后再拼接上需要求解的问题一起输入到语言模型中进行续写。最终模型续写出了中间的推理步骤以及答案,并且质量非常高。
值得一提的是,在十个数据集上 Auto-CoT 是可以匹配甚至超越 Manual-CoT 的性能,也就说明自动构造的 CoT 的问题、中间推理步骤和答案样例比人工设计的还要好,而且还节省了人工成本。在 Auto-CoT 中,其实也是用到了很多个“Let’s think step by step”对每个采样的问题分别触发中间推理步骤和答案,这也是为什么叫它 “Let's think not just step by step but also one by one”。
10. Agent
10.1. Assistants API
OpenAI的Assistants API的常规工作流为:
- 创建1个Assistant,并指定其instructions和model。如果需要,也可以启用如Code Interpreter、Retrieval和Function calling的tools
- 在每个新用户开启对话时,创建一个Thread
- 在用户提问时,加入Messages到Thread
- 在Thread里运行Assistant来触发回复。这一步会自动调用相关的tools
https://cookbook.openai.com/examples/assistants_api_overview_python
本质上就是个Agent。OpenAI提供了直接集成Code Interpreter、自定义Function以及Retrieval的tools。
可以让Assistant决定调用提供的工具,例如Code Interpreter生成代码解决问题,或是提供自定义的Function来解决问题。
10.2. Function Calling
提供function的描述,让模型智能地输出一个包含了调用1个或多个function信息的JSON对象。本质上gpt不会自动调用function,而是返回调用function的JSON信息。
https://cookbook.openai.com/examples/how_to_call_functions_with_chat_models
例如:
前面定义了function的描述,名称,功能等,然后基于用户的信息,返回调用的function名称以及传入的参数(以json的格式)。
11. vLLM
开源的大模型推理加速框架,通过Paged Attention高效地管理attention中缓存的张量,实现比HuggingFace Transformers高14-24倍的吞吐量。
11.1. LLM的性能受到内存限制
在自回归解码过程中,LLM的所有输入token都会生成attention机制的key和value的张量,并且这些张量被保留在GPU内存中,用来生成下一个token。
这些缓存的key和value的张量通常称为KV缓存。KV缓存有2个特点:
- 内存占用大:在LLaMA-13B中,单个序列的KV缓存占用高达1.7GB的内存
- 动态化:其大小取决于序列的长度,而序列长度高度易变,且不可预测
因此,有效管理KV缓存是一个重大挑战。对此,研究团队发现现有系统由于碎片化和过度保留而浪费了60%至80%的内存。
用团队的导师Joey Gonzalez的一句话来讲:GPU内存碎片化=慢。
11.2. PagedAttention机制
为了解决这个问题,引入了PagedAttention机制,它允许在非连续的内存空间中存储连续的key和value。
具体来说,PagedAttention将每个序列的KV缓存分为若干个block,每个block包含固定数量token的key和value张量。在注意力计算过程中,PagedAttention内核能够高效地识别和提取这些block。
由于这些块在内存中不需要连续,因此也就可以像操作系统的虚拟内存一样,以更灵活的方式管理key和value张量——将块看作page,token看作bytes,序列看作process。
序列的连续逻辑块通过块表映射到非连续的物理块。随着生成新的token,物理块会按需进行分配。
PagedAttention将内存浪费控制在了序列的最后一个块中。
在实践中,这带来了接近最优的内存使用——仅有不到4%的浪费。
而这种内存效率的提升,能让系统将更多的序列进行批处理,提高GPU利用率,从而显著提高吞吐量。
此外,PagedAttention还具有另一个关键优势:高效的内存共享。
比如在并行采样中,就能从相同的提示生成多个输出序列。在这种情况下,提示的计算和内存可以在输出序列之间共享。
11.3. Paged Attention高效地内存共享
比如在并行采样中,就能从相同的prompt生成多个输出序列。在这种情况下,prompt的计算和内存可以在输出序列之间共享。
PagedAttention通过块表自然地实现了内存共享。
类似于进程共享物理页的方式,PagedAttention中的不同序列可以通过将它们的逻辑块映射到相同的物理块来共享块。
为了确保安全,PagedAttention会跟踪物理块的引用计数,并实现了写时复制机制。
PagedAttention的内存共享极大减少了复杂采样算法(如并行采样和束搜索)的内存开销,将它们的内存使用量减少了高达55%。这可以将吞吐量提高多达2.2倍。
https://baijiahao.baidu.com/s?id=1769290162439240324&wfr=spider&for=pc
11.4. 部署ChatGLM2模型
在不使用vLLM时,问ChatGLM2-6b一个问题“晚上睡不着应该怎么办”,推理耗时13-14s。输出379个中文字符,token生成速度约为30 token/s 左右。
使用vLLM部署后,推理耗时7.6s左右,输出218个中文字符,token生成速度约为 28个token/s左右
INFO 02-06 09:01:09 llm_engine.py:649] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 20.6 tokens/s, Running: 1 reqs, Swapped: 0 reqs, Pending: 0 reqs, GPU KV cache usage: 0.7%, CPU KV cache usage: 0.0%
12. Realtime Stable Diffusion
加速推理,以及实时SD视频:
https://github.com/cumulo-autumn/StreamDiffusion
SD Turbo 1步成图,结合stream方案一秒100张图
13. topP与temperature
- Temperature:控制选择单词的随机性。更低的值可以让生成的文本更一致、可控;更高的值给予模型更多的创造性,生成的文本一致的可能性更低。
- 为0表示永远选择最可能的单词作为下一个输出单词
- Top_p:考虑候选单词的数量。更高的值表示模型会考虑更多的候选单词,甚至是较为不可能的单词,让生成的文本更多样化.
- Top_p = 0.5:这意味着仅考虑那些总概率至少达到总概率的50%的单词,排除了可能性较低的单词,并保持了一定水平的多样性响应。例如:如果您要求一本冒险书的标题,Top-p为0.5,模型可能会提出:“蓝山的神秘”。
- Top_p = 0.9:这包括了更多的选择单词,允许更多的变化和独创性。例如:对于同样的冒险书标题和Top_p为0.9,模型可能会创建:“深渊之声:勇者的肖像”。