Prompt Engineering、Finetune、RAG:OpenAI LLM 应用最佳实践

news2024/12/24 11:18:04

一、背景

本文介绍了 2023 年 11 月 OpenAI DevDay 中的一个演讲,演讲者为 John Allard 和 Colin Jarvis。演讲中,作者对 LLM 应用落地过程中遇到的问题和相关改进方案进行了总结。虽然其中用到的都是已知的技术,但是进行了很好的总结和串联,并探索了一条改进 LLM 应用的切实可行的路线,提供了一个最佳实践。

对应的 YouTube 视频:A Survey of Techniques for Maximizing LLM Performance。

二、概览

创建一个供演示的 LLM 应用 Demo 很简单,但是要投入生产环境使用却往往要投入几倍到几十倍的时间,因为几乎不可避免地要不断迭代以提升 LLM 应用程序的性能。其中,影响 LLM 应用程序性能的因素也有很多,比如数据、模型、系统、流程等等,此外涉及的技术方案也有很多,比如 In-Context  Learning、Few-shot Learning、RAG 和 Fine-tuning 等。

如何综合考虑以上的因素并合理利用相关技术是一个比较有挑战的工作,其中一种常见的错误是认为这个过程是线性的,如下图所示,首先 Prompt Engineering,再 RAG,最后 Finetune,按照这个顺序完成:

图片

作者认为最好沿着两个轴来考虑这个问题:

  • Context Optimization:如果模型没有相应的知识,比如一些私有数据。

  • LLM Optimization:如果模型不能产生正确的输出,比如不够准确或者不能遵循指令按照特定的格式或风格输出。

图片

在实践中,通常是利用各种技术不断地迭代来达到生产部署的需求,很多时候这些技术是可以累加的,需要找到有效的方法将这些改进组合起来,以获得最佳效果。如下图所示为作者总结的优化路线图,不过其涉及的优化点依旧没变,还是三点:

  • Prompt Engineering:包括 Prompt 优化以及增加 Few-shot learning,这是最简单的方式,不需要额外组件,也不用调整 LLM,只需控制 LLM 的输入即可。

  • RAG:通过检索的方式查找问题相关内容,并扩展到 LLM 的 Prompt 中,以供 LLM 参考。此优化需要引入一个检索系统,不过当前相关方案已经比较成熟,实施代价不高,比如 Milvus + LangChain。

  • Fine-tuning:通过增强 LLM 本身的能力来提升性能。依旧不需要额外组件,但是可能需要大量标注数据来微调模型,这个代价也可能比较高。

图片

三、Evaluation

在开始一切工作之前,首先要进行的是明确目标、确定评估指标。没有明确地评估指标,往往会导致走很多弯路,甚至错过一些行之有效的手段。常见的评估有自动化评估和人工评估:

  • 自动评估:针对一些常见的指标,使用常见的评估工具进行评估,实现简单,评估方便。

    • 精度评估:比如常见的 F1 Score,召回率,精确率等

    • 基于模型评估:在 LLM 的场景下,将模型作为评委进行评估是非常常见的方式,通常可以使用 GPT-4 作为评委,但是其成本比较高,因此也会折中的使用 GPT-3.5。

    • A/B Test:有些时候也会将 LLM 应用接入线上系统进行 A/B Test 评估,不过这个评估往往建立在其他评估已经取得不错结果的基础上。

  • 人工评估:有些评估可能比较主观,通常需要人工介入,比如流畅度、相关性、新颖性等,然而人工评估有时需要专业人士评估,其代价会比较高。

四、Prompt Engineering

当我们开始优化 LLM 应用时,通常首先做的事情是 Prompt Engineering,包括以下的几个方面:

  • 写一个清晰的指令

  • 将复杂任务拆分为简单的子任务

  • 给 GPT 思考的时间:比如经典的 “think step by step”

  • 给定一些参考文本:比如当前一些 LLM 的上下文窗口很大,甚至可以放下几本书,此时可以将其整体作为参考

  • 使用外部的工具:比如调用 Python,互联网搜索等

图片

虽然说首先要尝试的是 Prompt Engineering,但并不是适合所有场景:

  • 适合用于:

    • 早期测试以及了解需求

    • 与评估结合,确定 baseline 并提供后续的优化参考

  • 不适用于:

    • 引入新的信息

    • 可靠的复制复杂的样式或方法,比如学习新的编程语言

    • 最小化 Token 使用:Prompt Engineering 通常会增加输入 Token,导致计算量和时延的增加

图片

如下图所示就是一个比较模糊的指令:“以结构化方式提取有用的信息”,导致最终模型只是简单按照列表输出,输出内容也不符合要求。

图片

如下图所示,作者提供了更详细的示例,给定了清晰的指令,加了 “step by step”,要求模型不能跳过关键步骤,并且进行了任务拆解及格式约定,最终模型获得了不错的结果:

图片

如下图所示,同样可以给定模型一些 few-shot 示例,帮助模型更好的理解:

图片

评估应该贯穿 LLM 应用开发的整个生命周期,不仅是为了衡量每个阶段修改的影响,也为后续的改进提供参考。当完成 Prompt Engineering 阶段后,需要根据评估判断最可能的提升点是什么,判断模型是需要提升短期记忆(Short-term Memory)还是长期记忆(Long-term Memory):

  • 短期记忆:是指模型在处理单一输入时的临时存储信息,这些信息仅在模型处理当前输入时有效,一旦输入完成就会遗忘。它负责当前任务的理解和生成能力,不会影响模型对未来输入的处理。比如,模型缺乏特定的信息来回答问题。

  • 长期记忆:是指模型通过训练数据学到的知识,这些知识被永久的存储在模型参数中,包括语言规则、世界知识和常识等。比如,模型不能遵循特定的结构、风格或格式输出。

图片

五、RAG

RAG(Retrieval Augmented Generation,检索增强生成)通过集成外部知识库(私有数据、特定领域数据等)并使用 ICL(In-Context-Learning,上下文学习)来解决模型幻觉、知识不足等问题。如下图所示为 RAG 的常见范式,这里就不再具体陈述:

图片

当然,RAG 也不是万能的,也有其优势和不足:

  • 适合用于:

    • 向模型注入新的知识或者更新模型已有知识

    • 通过控制内容减少幻觉

  • 不适用于:

    • 嵌入对大范围领域的理解

    • 教模型掌握新的语言或特定格式、风格输出(当前模型上下文长度已经到了百万 Token 规模,似乎成为了一种可能)

    • 减少 Token 使用

图片

如下图所示为一个使用 RAG 的成功案例,通过各种手段将 Accuracy 从 Baseline 的 45% 提升到最终的 98%:

  • 45%:

    • 只使用简单的 Cosine 相似度来检索

  • 65%:

    • HyDE(Hypothetical Document Embeddings),如下图所示,主要是指利用 LLM 生成一个假设答案,然后利用假设答案去检索,最终再由 LLM 生成答案。尝试后没有取得很好的效果,所以未采用。

      图片

  • 微调 Embedding,但是代价比较高,并且比较慢,所以放弃。

  • RAG 中常用的 Chunking 方案(需要实验选择最优的 Chunk 大小),取得不错的结果。

  • 85%:

    • Re-Ranking 技术,这是搜索场景非常常见的手段,测试后取得了一定收益。

    • Classification 技术,使用模型对内容进行分类,判断内容属于哪个域,进而可以缩小检索内容或者在 Prompt 中添加一些额外的 Meta 信息,也取得不错的效果。

  • 98%:

    • Prompt Engineering,经过上述改进之后,作者再次尝试了 Prompt Engineering,还可以获得一定提升。

    • 使用工具,对于一些特定场景,允许模型使用工具能获得进一步的提升,比如访问 SQL database。

    • Query 扩展,也是搜索场景经常使用的手段,可以提升检索出的内容质量,进而提升最终的生成质量。

图片

当检索质量不好时,LLM 最终生成的结果也可能很差,比如有用户使用 GPT + RAG 的方式生成内容,并且告知模型只能根据用户提供的内容输出,然后用户认为模型输出的结果可能是包含了幻觉,但最终查看提供的内容时发现检索结果中确实有相关内容。

图片

图片

因此,在 RAG 阶段评估时,不仅要评估 LLM 生成的性能,也要评估 RAG 检索的性能,作者介绍了 Ragas 工具(GitHub - explodinggradients/ragas: Evaluation framework for your Retrieval Augmented Generation (RAG) pipelines),其提供了几个评估维度:

  • 生成指标

    • 忠诚度:衡量生成的答案在给定上下文中的事实一致性。它是根据答案和检索到的上下文计算得出,值范围介于 0 和 1 之间,越高越好。

    • 答案相关性:侧重于评估生成的答案与给定提示的相关性。对于不完整或包含冗余信息的答案,分数较低。该指标是使用问题和答案计算的,值范围介于 0 和 1 之间,分数越高表示相关性越高。

  • 检索指标

    • 上下文精度:用于评估上下文中存在的所有与基于事实相关的条目是否排名更高。理想情况下,所有相关块都必须出现在最高排名中。该指标是使用问题和上下文计算的,值范围介于 0 和 1 之间,分数越高表示精度越高。

    • 上下文召回:衡量检索到的上下文与标注答案的一致程度。它是根据 ground truth 和检索到的上下文计算的,值范围介于 0 和 1 之间,值越高表示性能越好。

图片

六、Fine-tuning

使用 Fine-tuning 主要有两个好处:

  • 提升模型在特定领域、特定任务上的性能。

  • 由于可以避免在 Prompt 中加入检索到的内容,因此可以降低 Token 数量,从而提升效率。此外,也可以通过蒸馏的方式把大模型的能力蒸馏到小模型里,比如用 70B 的模型蒸馏 13B 的模型。

图片

如下图所示作者提供了一个示例,需要提取文档中的结构化信息,并按特定格式输出,作者提供了复杂的指令,并提供了一个示例,模型确实按照格式要求输出,但是其中有些内容却出错了:

图片

如下图所示,经过微调后,不用输入复杂的指令,也不用在 Prompt 中提供示例,模型即可生成符合要求的输出:

图片

同样,Fine-tuning 也不是万能的,有其适合的场景也有不适合的场景(如果 Prompt Engineering 没有什么效果,那么 Fine-tuning 可能不是一个正确的选择):

  • 适合用于:

    • 激发模型中已有的知识

    • 自定义相应的结构或语气

    • 教会模型非常复杂的指令

  • 不适用于:

    • 向 base 模型中注入新知识

    • 快速在新场景验证

图片

作者提供了一个 Canva 的案例,该任务要求按照特定的格式输出内容,并提供特定字段,比如 “Titile”、“Style”、“Hero Image”,从结果可以看出,经过微调的 GPT-3.5 模型效果优于原始的 GPT-4,更优于原始的 GPT-3.5:

图片

此外,作者也提供了一个失败案例,具体可以参考:Fine-tuning GPT3.5-turbo based on 140k slack messages · Ross Lazerowitz。用户想要使用 GPT 按照自己的语气和风格自动生成 Twitter 和 LinkedIn 的博文。

  • 用户尝试了各种 Prompt Engineering 手段,没有取得很好的效果。

  • 用户还尝试了让 GPT 提取他以往博文的风格,比如语气、修辞等,可能由于数据太少,也没有成功。

  • 用户最后尝试了使用 GPT 3.5 Turbo 进行 Fine-tuning,选择的数据是自己过往的 140K Slack (一种国外流行的商务聊天应用,可以理解为聊天软件)聊天记录,并将其规范化为可以训练的数据格式,然后使用 GPT-3.5 Turbo 微调。得到的结果如下所示,确实很像工作中的聊天场景,完全偏离了用户的需求。

图片

虽然上述例子中微调没有满足用户的需求,但是微调确实朝着本应该正确的方向前进了(种瓜得瓜),只是用户的微调数据集偏离了他的需求,也因此可以看出数据集的重要性。

如下图为常见的微调流程

  • Data Preparation:非常重要的阶段,需要收集、验证、标注高质量的数据,并按照要求格式化。

  • Training:需要选择合适的超参,理解损失函数等。

  • Evaluation:有各种评估指标,此外也要看是否有针对微调任务的测试集;也可以使用 GPT-4 等高质量的模型进行评估。

  • Inference:也可以进一步收集数据,并标注用于后续迭代。

图片

作者总结了一个微调的最佳实践:

  • 从 Prompt Engineering 和 Few-shot Learning 开始,这些方案比较简单,可以快速验证

  • 建立基线,以便了解核心问题及后续更好地评估和对比

  • 数据集收集的代价比较高,从小的、高质量的数据集开始,可以验证模型是否沿着正确的方向前进,此外也可以结合主动学习(Active Learning)技术,不断迭代,构建高质量的数据。

图片

七、Fine-tuning + RAG

因为 Fine-tuning 和 RAG 是优化的不同方向,因此可以将两者结合起来,发挥各自的优势,比如:

  • Fine-tuning 可以使模型更好地理解复杂指令,使模型遵循特定的格式、风格等,也就避免了复杂指令的需求,降低 Token 的使用,为 RAG 提供更大的空间。

  • RAG 可以将相关知识注入到上下文中,增强模型的短期记忆能力。

图片

作者提供了一个典型的 Text-to-SQL 任务案例:给定一个自然语言文本,以及数据库的 Schema,需要生成 SQL 查询并回答问题。如下图所示,左侧为对应的 Schema 和自然语言文本,右侧为生成的 SQL 语句:

图片

如下图所示,作者首先尝试了 RAG,并逐步使用了各种检索优化技术:

图片

如下图所示,其中 Baseline 的 69% 是经过了 Prompt Engineering 得到的结果,然后经过 RAG 逐步将其提升到 80%:但是离目标还有一定距离:

图片

如下图所示,作者进一步尝试了 Fine-tuning,首先通过 FT + Reduced Schema 可以将 Accuracy 从 69% 提升到 81.7%,进一步使用 Fine-tuning + RAG 可以提升到 83.5%,基本符合目标 84%。其中使用的都是比较简单的 Prompt Engineering 和 RAG 方案,没有采用特别复杂的技术,可以看出 Fine-tuning + RAG 的潜力。

图片

八、相关链接

  1. https://www.youtube.com/watch?v=ahnGLM-RC1Y

  2. https://humanloop.com/blog/optimizing-llms

  3. https://zhuanlan.zhihu.com/p/667938175

  4. https://github.com/explodinggradients/ragas

  5. https://rosslazer.com/posts/fine-tuning/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1500335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue+SpringBoot打造天沐瑜伽馆管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 瑜伽课程模块2.3 课程预约模块2.4 系统公告模块2.5 课程评价模块2.6 瑜伽器械模块 三、系统设计3.1 实体类设计3.1.1 瑜伽课程3.1.2 瑜伽课程预约3.1.3 系统公告3.1.4 瑜伽课程评价 3.2 数据库设计3.2.…

从零开始学习Diffusion Models: Sharon Zhou

How Diffusion Models Work 本文是 https://www.deeplearning.ai/short-courses/how-diffusion-models-work/ 这门课程的学习笔记。 文章目录 How Diffusion Models WorkWhat you’ll learn in this course [1] Intuition[2] SamplingSetting Things UpSamplingDemonstrate i…

SpringBoot第三课-日志

1.日志分类 2.默认使用 默认使用logback与slf4j作为底层默认日志 但是由于日志是系统启动就需要使用,所以与其他的自动配置不同,自动配置是后来使用的,而日志是使用监听器配置好的。 ApplicationListener 3.日志级别 1.级别介绍 SpringB…

【MySQL 系列】在 Windows 上安装 MySQL

在 Windows 平台上安装 MySQL 很简单,并不需要太复杂的步骤。按照本文的步骤操练起来就可以了。 文章目录 1、下载 MySQL 安装程序2、安装 MySQL 数据库2.1、选择安装类型2.2、检查所需组件2.3、安装所选产品组件2.4、产品配置2.5、配置高可用性2.6、配置服务器类型…

正则表达式-分组

1、oracle-正则表达式:将09/29/2008 用正则表达式转换成2008-09-29 select regexp_replace(09/29/2008, ^([0-9]{2})/([0-9]{2})/([0-9]{4})$, \3-\1-\2) replace from dual; 解析:regexp_replace-替换, 第一个参数:需要进行处…

分享7款前端直接使用的项目动画特效(附在线演示)

分享7款非常不错的项目动画特效 其中有jQuery特效、canvas特效、CSS动画等等 下方效果图可能不是特别的生动 那么你可以点击在线预览进行查看相应的动画特效 同时也是可以下载该资源的 图片分割组合特效 首先会把图片分割成均匀的小块 之后又会将这些小块拼接组合起来 以下效…

节日专访|「我」是「我」

又到了 Zilliz 一年一度的特别时刻——三八妇女节专访。按照惯例,我们每年都会选定一个话题进行讨论,今年的主题是「我是我」。 我是我, 是生物学上以性别划分的女性, 是在不同职业领域中绽放光彩的工程师、财务、市场运营…… 是…

数据结构从入门到精通——栈

栈 前言一、栈1.1栈的概念及结构1.2栈的实现1.3栈的面试题 二、栈的具体实现代码栈的初始化栈的销毁入栈出栈返回栈顶元素返回栈中的元素个数检测是否为空Stack.hStack.ctest.c 前言 栈,作为一种后进先出(LIFO)的数据结构,在计算…

力扣大厂热门面试算法题 6-8

6. Z 字形变换,7. 整数反转,8. 字符串转换整数 (atoi),每题做详细思路梳理,配套Python&Java双语代码, 2024.03.08 可通过leetcode所有测试用例。 目录 6. Z 字形变换 解题思路 边界条件 完整代码 Python Ja…

李想已经5天没发微博了

李想的微博已经5天没更新了。 理想MEGA发布之后的第二天,李想在微博转发了一条某汽车自媒体和理想MEGA设计师BenBaum的访谈视频,并配文表示,Ben的访谈非常好。 不过,在之后的5天时间里,李想的微博便悄无声息了。这与“…

yocto本地离线构建时报错

解决方案:在local.conf中添加 BB_NO_NETWORK "1"禁用网络,从本地downloads中fetch源码

【方法】如何打开7Z分卷压缩文件?

什么是7Z分卷压缩文件?就是在压缩文件时,将文件压缩成若干个大小一样、以“文件名.7z.序号”格式命名的7Z压缩包,可以方便存储和传输,如下图所示。 一、7Z分卷压缩文件如何打开? 我们只需要按照普通压缩包的打开方式&…

智慧园区综合运营数字化解决方案

1. 楼栋管理 2. 物业管理 3. 安防管理 4. 门禁管理 5. 停车管理 6. 能源管理 7. 环保管理 8. 园区生活服务 9. 招商管理 10. 收费中心 11. 园区地图 12. 门户网站 智慧园区软件方案:智慧园区软件解决方案,园区运营管理系统(源码)-…

DiT:Scalable Diffusion Models with Transformers

TOC 1 前言2 方法和代码 1 前言 该论文发表之前,市面上几乎都是用卷积网络作为实际意义上的(de-facto)backbone。于是一个想法就来了:为啥不用transformer作为backbone呢? 文章说本论文的意义就在于揭示模型选择对于…

二叉树—层序遍历

102. 二叉树的层序遍历 代码实现: /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ /*** Return an array of arrays of size *returnSize.* The sizes of the arrays …

L波段光端机-L波段+CATV射频光端机工作机制及行业应用探究

L波段光端机-L波段CATV射频光端机工作机制及行业应用探究 北京海特伟业任洪卓发布于2023年3月8日 一、何为L波段光端机 L波段光端机是一种用于光通信的设备,其主要工作波长位于L波段,即40~860MHz和950~2600MHz的带宽,可选独立工作于950~260…

开发Chrome扩展插件

1.首先开发谷歌chrome扩展插件,没有严格的项目结构目录,但是需要保证里面有一个mainfest.json文件 (必不可少的文件)。在这个文件里有三个属性必不可少:name、version、mainfest_version; // 清单文件的版本,这个必须写…

消息队列-Kafka-消费方如何分区与分区重平衡

消费分区 资料来源于网络 消费者订阅的入口:KafkaConsumer#subscribe 消费者消费的入口:KafkaConsumer#poll 处理流程: 对元数据重平衡处理:KafkaConsumer#updateAssignmentMetadataIfNeeded 协调器的拉取处理:onsum…

java常用排序算法——冒泡排序,选择排序概述

前言: 开始接触算法了,记录下心得。打好基础,daydayup! 算法 算法是指解决某个实际问题的过程和方法 排序算法 排序算法指给混乱数组排序的算法。常见的有:冒泡排序,选择排序 冒泡排序: 冒泡排序指在数组…

python异常机制

当代码出现异常后底下代码都不会被执行了,也就是程序崩溃了。当然能避免异常的话尽量避免但是有的时候这个是没有办法避免的。 异常处理 (注:异常处理是从上往下处理,所以编写代码时要注意) 语法 try:可能出现异常…