【每周一读】A Survey of Techniques for Maximizing LLM Performance
这次不是文章,是OpenAI的talk,干货满满。
直接把在飞书文档上记的笔记当过来了。
----------------------------------
【我学到了什么】
首先PE和FSL,低成本快速迭代并和评估结合,建立baseline;
通过RAG引入新知识&减少幻觉,查看做错的具体case,针对问题进行相应的优化(检索不到?优化分块/embedding/query transform等;top-k选取不恰当?rerank;回答不恰当?重新PE,引入tools,chain of thought等);
可以结合ragas评估问题出在哪;
想要减少tokens,用某种语气、格式回答,让LLM理解复杂指令,用少量优质数据微调,看方向是否正确;微调不是早期就要做的事情。
不断测试-查看错误用例-找到问题-优化-迭代
首先PE和FSL,低成本快速迭代并和评估结合,建立baseline;
通过RAG引入新知识&减少幻觉,查看做错的具体case,针对问题进行相应的优化(检索不到?优化分块/embedding/query transform等;top-k选取不恰当?rerank;回答不恰当?重新PE,引入tools,chain of thought等);
可以结合ragas评估问题出在哪;
想要减少tokens,用某种语气、格式回答,让LLM理解复杂指令,用少量优质数据微调,看方向是否正确;微调不是早期就要做的事情。
不断测试-查看错误用例-找到问题-优化-迭代
----------------------------------
【笔记】
找到问题;如何解决它;用什么tools

优化LLM很困难
- 很难分离信号和噪音,找到问题“是什么”
- LLM表现抽象且难以衡量,不知道问题“有多大”
- 很难知道何时用何种方法解决问题

优化LLM性能并不总是线性的:RAG和Fine-tuning解决了不同的问题,有时需要其中一个,有时需要两者

- 上下文优化:模型需要知道什么
- LLM优化: 模型需要如何行动(采取什么方法)
优化流程
经典流程从Prompt engineering开始:
有了prompt,对输出进行一致评估:这是context问题还是LLM行动问题?
需要更多相关上下文 -> RAG;
需要更一致的指令遵循 -> Fine-tuning;
或者两者兼有。

- 有了prompt,创建评估,找到基线;
- 为模型提供几个输入-输出示例,说明你希望模型如何行动;
- 这些少量示例大大提升了模型性能,连接知识库使该过程工业化 => RAG;
- 现在有了相关上下文,但模型并没有以我们想要的格式/风格输出,微调模型 => Fine-tuning;
- 检索效果不好,需要内容与模型需求更加相关 => 优化RAG;
- 用RAG引入的新示例再来微调模型。
Prompt engineering

Prompt成功案例

通过prompt告诉模型我们想要如何行动,但我们往往不知道哪些token对模型是最有效的。
好的开始方式是展示而不是讲述问题:提供少量示例(输入-输出对),并展示希望模型做出的反应。

希望可以工业化,few-shot示例能够基于用户需求,基于问题的上下文
RAG

这里用了个考试的例子很有意思:prompt提供完成考试需要的指示,微调学到的是回答问题的方法论,RAG就是开卷。如果模型知道方法论,知道它要找什么,RAG让模型可以打开书本,翻到正确的书页并提取需要的内容。

适用于为模型引入新的知识。
减少幻觉:提供上下文内容,并告诉模型只用上下文内容而不是先前的知识来回答问题。
让模型去学新的语言、格式等等,更多是微调做的事情(学习方法论)而不是RAG。
RAG成功案例
RAG pipeline + LLM + 两个知识库,需求:获取用户问题,决定用哪个知识库,发起查询并用它回答问题。

45% baseline
简单的检索
=> 65% (20次迭代)
HyDE对有些用例很有用,有些不行;
FT嵌入层效果好,但贵且慢;
分块&嵌入,尝试不同大小的信息块,嵌入不同的内容;
=> 85%
Reranking用交叉编码器对结果重新排序,或使用基于规则的内容(想要最新的内容);
Classification让模型对这两个域进行分类,根据被分到哪个类,在prompt中提供额外的元数据;
=> 98%
进一步PE,更好地设计prompt
查看做错的问题类别,引入tools(从文档中提取结构化数据:SQL tool输入变量执行查询,返回结构化数据答案
Query expansion 一起问了多个问题,把问题解析为查询列表,并行执行,合成答案
整个过程没有用到微调,此处要解决的每个问题都是context:要么没有给正确的上下文,要么模型不知道哪个上下文块是正确的。知道自己要解决的问题是什么,是非常重要且必要的。
RAG反面教材
需求:减轻幻觉,只用知识库内容。有人类检查并标记幻觉。


如果告诉模型只用上下文内容,但搜索效果不好,那么模型很难得到正确答案。
评估RAG时,实际上也在评估可能出错的其它整个轴:LLM、搜索……
RAG开源评估框架
Ragas分解了不同的评估指标,可以开箱直用或根据自己的需求调整。
有四个评估指标,其中两个衡量LLM问题回答得有多好,另两个衡量上下文与问题的相关程度。

LLM生成指标:
忠诚度 - 把回答分解成事实,把每个事实和内容对比,如果不相符即为幻觉(返回的数值高于阈值)
回答相关度 - 有时模型充分利用得到的内容给出答案,但与用户的问题无关(需要让模型决定是否用某个内容)
内容检索指标:(对客户最有用)
并不是给模型的上下文chunks越多效果就越好,内容越多反而越可能会出现幻觉/忘记中间的内容(lost in the middle),我们只需要精确的上下文片段,用更少的内容获取正确答案。

上下文精度 - 该指标评估检索内容的信噪比,获取每个内容块并与答案比较,看答案中是否使用了该内容(判断上下文更多能否带来帮助)
上下文召回率 - 能否检索到答案需要的所有相关信息,如果这个值低,说明需要优化检索(增加reranking、FT嵌入层、尝试不同的嵌入等)
微调
Def. 用现有的训练过的模型,在更小的、领域特定的数据集上继续训练,来完成特定的任务
优点

和PE能打包到模型上下文窗口里的token相比,微调过程中能为模型展示更多的例子,实现更好的性能;
不用在提示中提供复杂的说明、上下文例子,每个提示发送的token更少,因此更便宜&高效;
微调通常是把较大模型的知识蒸馏到较小模型,和较小模型交互通常也会更加高效。


微调无需复杂指令、上下文学习或显式模式

微调适合:
- 获取基础模型中已经存在的知识,并强调其中的一个子集;
- 修改/自定义模型输出的结构或语气(如JSON);
- 在微调过程中可以给模型展示更多示例,因此可以教会模型复杂指令。
微调不适合:
- 向模型添加新知识
- 快速迭代新用例(微调是相对慢的反馈循环,不要从它开始)
微调成功案例
需求:输入自然语言的设计mock描述,让LLM输出一组结构化的设计指南,来生成full-sized mock呈现给用户


为什么微调有效?1. 不需要新的知识,需要具体的结构输出 2. 有高质量训练数据,有好的baseline来比较评估,了解微调目标
微调反面教材
需求:用AI充当写作助手
问题:模型撰写的文章没有捕捉到特定的语气(博客、社媒帖、email)=> 微调
收集了140k条Slack数据 - 格式化为与微调兼容的格式 - 微调模型

需要考虑微调所选用的数据是否真的复制了想要模型作出的行为
可行的是先用一两百条Slack数据在模型上微调实验,看它是否朝着期望的方向前进
如何微调

- 获取数据集(下载开源数据集,在私人市场上购买数据,付费人工标记员,从更大模型蒸馏),收集、验证、格式化
- 训练,需要理解训练过程中调整的超参数和它们对模型的影响,理解损失函数是否和不同下游任务的性能相关(比如功能性代码片段可能会有多种实现方式,如果是next token prediction和精准token匹配,就会效果不好)
- 评估模型(聘请专家对输出排名、采用不同模型的输出并互相排名、用更强大的模型对输出排名)
- 部署并进行推理(可以从推断中采样,构建新的数据集,进一步微调,和前两步形成反馈循环)

Start small,开发一个小型高质量数据集,进行微调,评估模型,查看是否在朝着正确的方向前进(微调时查看输出,了解它在哪些领域陷入困境,用新数据专门针对这些领域)
数据质量胜过数据数量,专注于更少的高质量数据
Fine-tuning + RAG

微调省去复杂指令和few-shot示例,节省了提示中的token,因此有更多空间留给检索上下文
应用
Text-to-SQL:给定数据库模式,从自然语言生成SQL查询并回答问题


上下文检索:简单过滤,对收到的问题难度进行排名,在RAG中只带回同等难度的示例
自我一致性检查:构建并执行query,如果模型搞砸了会给它错误信息+一点注释,然后再试一次(让GPT自我修复)

PE - few-shot learning - HyDE - 增加示例 - 微调
