用通俗易懂的方式讲解:一种全新的大模型检索增强生成方法

news2024/11/18 19:48:22

如何使大型语言模型更加事实、正确和可靠?

检索增强生成(RAG)是一种有效的方法,可以缓解大型语言模型的基本局限性,如幻觉和缺乏最新知识。

然而,如果您曾尝试过RAG,您会同意我所说的RAG易于原型设计,但很难达到理想的水平。

在本文中,我将讨论一篇关于自我RAG的新研究论文:Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection,该论文提出了一种改进RAG模型性能的新方法。

介绍 Self-RAG:一种新方法

RAG 效率在很大程度上依赖于诸如文本分块方法、嵌入和检索技术等因素。

当不加选择地检索固定数量的段落,或者获取与查询无关的内容时,可能会导致糟糕的响应,并降低 LLM 的多功能性。

在2023年10月,一篇名为“Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection”的新研究论文引入了一种创新框架。这个框架通过教导LLM何时检索来增强其一致性和性能。

实验证明,自我RAG(7B和13B参数)在各种任务上显著优于最先进的LLM(例如ChatGPT和Llama2-chat)以及检索增强模型。

让我们深入探讨吧!

用通俗易懂的方式讲解系列

  • 用通俗易懂的方式讲解:不用再找了,这是大模型最全的面试题库
  • 用通俗易懂的方式讲解:这是我见过的最适合大模型小白的 PyTorch 中文课程
  • 用通俗易懂的方式讲解:一文讲透最热的大模型开发框架 LangChain
  • 用通俗易懂的方式讲解:基于 LangChain + ChatGLM搭建知识本地库
  • 用通俗易懂的方式讲解:基于大模型的知识问答系统全面总结
  • 用通俗易懂的方式讲解:ChatGLM3 基础模型多轮对话微调)
  • 用通俗易懂的方式讲解:最火的大模型训练框架 DeepSpeed 详解来了
  • 用通俗易懂的方式讲解:这应该是最全的大模型训练与微调关键技术梳理
  • 用通俗易懂的方式讲解:Stable Diffusion 微调及推理优化实践指南
  • 用通俗易懂的方式讲解:大模型训练过程概述
  • 用通俗易懂的方式讲解:专补大模型短板的RAG
  • 用通俗易懂的方式讲解:大模型LLM Agent在 Text2SQL 应用上的实践
  • 用通俗易懂的方式讲解:大模型 LLM RAG在 Text2SQL 上的应用实践
  • 用通俗易懂的方式讲解:大模型微调方法总结
  • 用通俗易懂的方式讲解:涨知识了,这篇大模型 LangChain 框架与使用示例太棒了
  • 用通俗易懂的方式讲解:掌握大模型这些优化技术,优雅地进行大模型的训练和推理!

Self-RAG:教导LLM何时检索

自我反思式检索增强生成(Self-RAG)是一种新方法,它教导LLM在检索、生成和评论中以增强其响应的准确性和质量。

与传统的检索增强生成(RAG)方法相反,Self-RAG 根据需要检索信息,这意味着它可以根据遇到的查询多次检索或根本不检索。

它还从各个角度评估其响应,使用称为“反思标记”的特殊标记。这些标记允许LLM控制其行为,并在推理阶段根据特定任务要求进行定制。

Self-RAG 内部工作原理

Self-RAG 方法的核心思想是通过一种称为“自我反思标记”的东西来教导和控制大型语言模型(LLM)。这个过程发生在推理阶段,即LLM生成响应时。

以下是Self-RAG 的工作方式:

  • 检索:Self-RAG 首先确定将检索到的信息添加到响应是否有帮助。如果是,它会发出一个检索过程的信号,并要求外部检索模块找到相关文档。
  • 生成:如果不需要检索,Self-RAG 会像常规语言模型一样预测响应的下一个部分。如果需要检索,它首先评估检索到的文档是否相关,然后根据所发现的内容生成响应的下一个部分。
  • 评论:如果需要检索,Self-RAG 会检查它检索到的段落是否支持响应。它还评估响应的整体质量。

Self-RAG 的训练过程

Self-RAG 训练了两个模型,评论家和生成器,两者都使用反思标记扩展令牌词汇,并使用标准的下一个令牌预测目标进行训练。

  • 第一步 评论家数据创建:通过提示GPT-4生成反思标记,生成评论家的训练数据。
  • 第二步 评论家训练:在合成数据集上训练评论家模型。
  • 第三步 生成器数据创建:使用评论家和检索器生成生成器的训练数据。
  • 第四步 生成器训练:在RAG数据集上训练生成器,包括特殊标记,以教导模型何时进行检索或不检索。

实际应用:使用 Self-RAG

现在,让我们从理论方面转向 Self-RAG 的实际应用!

以下代码可以在免费的Colab笔记本实例上运行。

使用 Self-RAG 进行推理

Self-RAG 模型在基础模型 Llama-2-7b-hf 上进行了微调,并且可以在Hugging Face上获取。这使得从Hub下载模型并进行测试变得非常简单。

以下是如何使用 Self-RAG 进行推理的方法。

  1. 安装必要的包
!pip install vllm
!pip install torch
!pip install transformers, tokenizer, datasets, peft, bitsandbytes
!pip install accelerate>=0.21.0,<0.23.0  # 0.23.0将在使用deepspeed时导致不正确的学习率调度,可能是由https://github.com/huggingface/accelerate/commit/727d624322c67db66a43c559d8c86414d5ffb537引起的
!pip install peft>=0.4.0
!pip install evaluate>=0.4.0
!pip install tiktoken
  1. 运行推理

我们将使用研究团队推荐的vllm来加速推理。

# 导入必要的库
from vllm import LLM, SamplingParams

# 使用指定的模型和数据类型初始化LLM(大型语言模型)
model = LLM("selfrag/selfrag_llama2_7b", dtype="half")

# 为文本生成定义采样参数
sampling_params = SamplingParams(temperature=0.0, top_p=1.0, max_tokens=100, skip_special_tokens=False)

# 定义一个函数来格式化提示,包括指令和可选的检索段落
def format_prompt(input, paragraph=None):
  prompt = "### Instruction:\n{0}\n\n### Response:\n".format(input)
  if paragraph is not None:
    prompt += "[Retrieval]{0}".format(paragraph)
  return prompt

# 为模型生成响应的两个查询
query_1 = "Leave odd one out: twitter, instagram, whatsapp."
query_2 = "Can you tell me the difference between llamas and alpacas?"
queries = [query_1, query_2]

# 为查询生成响应
preds = model.generate([format_prompt(query) for query in queries], sampling_params)

# 打印每个查询的模型预测
for pred in preds:
  print("\n\nModel prediction: {0}".format(pred.outputs[0].text))

让我们分析一下 Self-RAG 的输出。

我们执行了两个查询,并观察到对于第一个查询,自我RAG直接生成响应,因为不需要检索信息。在第二个查询中,自我RAG显示出[Retrieve]标记,因为问题需要更多的事实信息。

使用您自己的数据运行 Self-RAG

在这里,我们将探讨两种使用您自己的数据与自我RAG进行交互的方法:

直接数据插入:最简单的方法是将您的数据直接插入到format_prompt函数的段落参数中。这样可以让自我RAG直接访问并将您的数据整合到其响应生成过程中。
基于嵌入的检索:对于更复杂的数据或直接插入不可行的情况,您可以为您的数据生成嵌入,并利用检索机制提取自我RAG所需的相关信息。这种方法使自我RAG能够根据查询的上下文选择性地检索和利用您的数据中的信息。
直接数据插入

对于需要外部事实支持的查询,您可以插入一个段落。

自我RAG可以在生成过程中随时检索和插入段落,并在它们被上下文标记特殊令牌所包围时识别它们。

基于嵌入的检索

您可以利用原始研究论文提供的脚本和代码将您自己的数据整合到自我RAG中。该过程包括三个主要步骤:

  1. 数据准备

将您的数据集准备为JSON或JSONL格式。每个实例应包含一个问题或一条指令,这将在检索过程中用作查询。

  1. 嵌入生成

使用GitHub存储库中提供的脚本为您的数据生成嵌入。这将将您的数据转换为数字表示,可以有效地通过检索机制处理。

cd retrieval_lm
CUDA_VISIBLE_DEVICES=0

python generate_passage_embeddings.py --model_name_or_path facebook/contriever-msmarco \
--output_dir [YOUR_OUTPUT_DIR] \
--passages [YOUR_PASSAGE_DATA] \
--shard_id 0 --num_shards 4 > ./log/nohup.my_embeddings 2>&1 &
  1. 运行自我RAG在您自己的数据上

将您生成的嵌入与自我RAG的检索模块结合起来,从您的数据中提取相关信息。然后,自我RAG将利用这些信息生成针对您特定查询的响应。

from passage_retriever import Retriever

retriever = Retriever({})
query = "YOUR_QUERY"
retriever.setup_retriever("facebook/contriever-msmarco", [YOUR_JSON_DATA_FILE], [YOUR_DATA_EMBEDDING], n_docs=5, save_or_load_index=False)
retrieved_documents = retriever.search_document(query, 5)
prompts = [format_prompt(query, doc["title"] +"\n"+ doc["text"]) for doc in retrieved_documents]
preds = model.generate(prompts, sampling_params)
top_doc = retriever.search_document(query, 1)[0]
print("Reference: {0}\nModel prediction: {1}".format(top_doc["title"] + "\n" + top_doc["text"], preds[0].outputs[0].text))

使用 Self-RAG 增强您的RAG流程

或者,您还可以使用Self-RAG方案训练一个新的预训练LLM,例如Mistral-7b。如果您使用hugging face transformers,您可以简单地在训练脚本script_finetune_7b.sh中更改model_name_or_path和tokenizer_name。

export CUDA_VISIBLE_DEVICES=0,1,2,3

MODEL_SIZE=7B
NUM_GPUS=4
BATCH_SIZE_PER_GPU=1
TOTAL_BATCH_SIZE=128
GRADIENT_ACC_STEPS=$(($TOTAL_BATCH_SIZE/$NUM_GPUS/$BATCH_SIZE_PER_GPU))
echo "Training llama model ${MODEL_SIZE} using $NUM_GPUS GPUs, $BATCH_SIZE_PER_GPU batch size per GPU, $GRADIENT_ACC_STEPS gradient accumulation steps"

CUDA_VISIBLE_DEVICES=0,1,2,3 accelerate launch \
    --mixed_precision bf16 \
    --num_machines 1 \
    --num_processes $NUM_GPUS \
    --use_deepspeed \
    --deepspeed_config_file stage3_no_offloading_accelerate.conf \
    finetune.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --use_flash_attn \
    --tokenizer_name meta-llama/Llama-2-7b-hf \
    --use_slow_tokenizer \
    --train_file full_output_1005.jsonl \
    --max_seq_length 2048 \
    --preprocessing_num_workers 16 \
    --per_device_train_batch_size $BATCH_SIZE_PER_GPU \
    --gradient_accumulation_steps $GRADIENT_ACC_STEPS \
    --learning_rate 2e-5 \
    --lr_scheduler_type linear \
    --warmup_ratio 0.03 \
    --weight_decay 0. \
    --num_train_epochs 3 \
    --output_dir output/self_rag_${MODEL_SIZE}/ \
    --with_tracking \
    --report_to tensorboard \
    --logging_steps 1 \
    --use_special_tokens

最后思考

RAG可能导致糟糕的响应。在该过程中添加特殊标记可以教导模型何时检索信息以及什么是相关的。

自我RAG是一种改进事实性而不牺牲大型语言模型创造性多样性的有趣方法。它展示了让LLM反思自身局限性并有选择地获取知识的好处。

论文中分享的模型经过了对150,000个实例进行的评论家训练。正如您所想象的那样,这是最具挑战性的任务,因为数据集需要对检索和非检索示例都具有多样性。很酷的是,完整的数据集和代码都在GitHub上完全共享,因此您也可以微调您选择的自定义LLM,例如Mistral-7b。

但是,请记住,训练和维护自我RAG模型需要更多的努力。如果您需要LLM提供高度可靠的响应,例如在金融领域,这可能是一个值得的选择。我也渴望看到关于如何增强RAG和解决LLM局限性的新研究。

参考文献

  1. https://levelup.gitconnected.com/upgrade-your-retrieval-augmented-generation-with-self-rag-bb30b2a0ffa4

  2. https://github.com/AkariAsai/self-rag

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

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

相关文章

【每日一题】4.LeetCode——环形链表

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&…

RK3568平台开发系列讲解(Linux系统篇)互斥锁使用

🚀返回专栏总目录 文章目录 一、互斥锁API二、使用互斥锁的步骤三、互斥锁使用规则四、使用案例沉淀、分享、成长,让自己和他人都能有所收获!😄 一、互斥锁API 在Linux中,你可以使用互斥锁(Mutex)来实现多线程或多进程之间的互斥访问。互斥锁用于确保在同一时间只有一…

24. 两两交换链表中的节点(力扣LeetCode)

文章目录 24. 两两交换链表中的节点题目描述解题思路只使用一个临时节点使用两个临时节点 24. 两两交换链表中的节点 题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff0…

STM32学习笔记(二) —— 调试串口

我们在调试程序时&#xff0c;经常会使用串口打印相关的调试信息&#xff0c;但是单片机串口不能直接与 PC 端的 USB 接口通讯&#xff0c;需要用到一个USB转串口的芯片来充当翻译的角色。我们使用的开发板上有这个芯片&#xff0c;所以在打印调试信息的时候直接使用USB线连接开…

每日一题——LeetCode1365.有多少小于当前数字的数字

方法一 暴力循环 对于数组里的没一个元素都遍历一遍看有多少元素小于当前元素 var smallerNumbersThanCurrent function(nums) {let n nums.length;let ret [];for (let i 0; i < n; i) {let count 0;for (let j 0; j < n; j) {if (nums[j] < nums[i]) {count…

【C语言】数组的应用:三子棋游戏

由于代码较长&#xff0c;为了增加可读性&#xff0c;我们把代码分别写到game.h&#xff0c;game.c&#xff0c;test.c&#xff0c;里面&#xff0c;其中game.h用来声明函数&#xff0c;实现函数功能的代码在game.c&#xff0c;测试游戏的代码在test.c 为了方便后续的更改&…

qt学习:http+访问百度智能云api实现车牌识别

目录 登录到百度智能云&#xff0c;找到文字识别 完成操作指引 开通 查看车牌识别的api文档 ​编辑​编辑 查看自己应用的api key 查看回应的数据格式 编程步骤 ui界面编辑 添加模块&#xff0c;头文件和定义变量 新建两个类&#xff0c;一个图像Image类&#xff0c…

深度学习之卷积神经网络进阶版

上一讲我们介绍了卷积神经网络和多层感知机&#xff0c;也就是全链接网络。他们在网络架构上是串行的结构&#xff0c;也就是在每一层与每一层之间&#xff0c;前面一层的输出&#xff0c;是后面一层的输入。 在神经网络里面&#xff0c;我们可能会有更加复杂的结构&#xff0…

Pycharm连接云算力远程服务器(AutoDL)训练深度学习模型全过程

前言&#xff1a;在上一篇windows搭建深度学习环境中&#xff0c;我试图使用笔记本联想小新air14的mx350显卡训练一个图像检测的深度学习模型&#xff0c;但是训练时长大概需要几天时间远超我的预期&#xff0c;所以我便选择租用GPU进行训练&#xff0c;在对多家平台对比后找到…

[BT]小迪安全2023学习笔记(第19天:Web开发-.NET项目)

第19天 名词解释 .NET 是一种由Microsoft开发的软件框架&#xff0c;用于构建和运行Windows操作系统上的应用程序。它提供了一个广泛的工具和库集合&#xff0c;支持多种编程语言&#xff0c;包括C#、VB.NET、F#等。.NET的主要目标是提供一种一致的开发平台&#xff0c;使开发…

《HTML 简易速速上手小册》第1章:HTML 入门(2024 最新版)

文章目录 1.1 HTML 简介与历史&#xff08;&#x1f609;&#x1f310;&#x1f47d;踏上神奇的网页编程之旅&#xff09;1.1.1 从过去到现在的华丽蜕变1.1.2 市场需求 —— HTML的黄金时代1.1.3 企业中的实际应用 —— 不只是个网页1.1.4 职业前景 —— 未来属于你 1.2 基本 H…

SQL注入:二次注入

SQL注入系列文章&#xff1a; 初识SQL注入-CSDN博客 SQL注入&#xff1a;联合查询的三个绕过技巧-CSDN博客 SQL注入&#xff1a;报错注入-CSDN博客 SQL注入&#xff1a;盲注-CSDN博客 目录 什么是二次注入&#xff1f; 二次注入演示 1、可以注册新用户 2、可以登录->…

数据湖技术之平台建设篇2

数据湖技术之平台建设篇1&#xff0c;主要介绍了湖仓平台建设的前三个主要工作&#xff0c;本次主要继续上次的建设工作介绍&#xff0c;聊一聊一站式湖仓服务平台的相关管理能力建设以及针对小文件的处理。 一. 一站式湖仓服务平台的相关管理能力 主要是将相关能力落地到平台…

day03-今日佳人功能实现

课程说明 首页功能说明系统架构说明实现今日佳人功能实现推荐用户的列表接口增加缓存功能整合前端联调测试 1、首页 在用户登录成功后&#xff0c;就会进入首页&#xff0c;首页中有今日佳人、推荐好友、探花、搜附近等功能。 2、系统架构 在开发完SSO系统中的登录功能后&…

【Spring实战】31 Spring Boot3 集成 Gateway 微服务网关

文章目录 1. 定义2. 功能3. 示例代码1) 创建一个业务服务2&#xff09;创建一个网关服务3&#xff09;启动服务4&#xff09;验证 4. 代码参考结语 1. 定义 Spring Cloud Gateway 是一个基于 Spring Framework 的开源网关服务&#xff0c;用于构建微服务架构中的 API 网关。它…

SpringCloud LoadBalancer

SpringCloud LoadBalancer 1.什么是LoadBalancer LoadBalancer&#xff08;负载均衡器&#xff09;是一种网络设备或软件机制&#xff0c;用于分发传入的网络流量负载请求到多个后端目标服务器上&#xff0c;从而实现系统资源的均衡利用和提高系统的可用性和性能。 负载均衡器…

前端工程化之:webpack1-7(入口和出口)

前置知识 node 环境下 "./" 代表的意思&#xff1a; 模块化代码中&#xff0c;比如 require("./") &#xff0c;表示当前 js 文件所在的目录。在路径处理中&#xff0c; "./" 表示 node 运行目录。__dirname&#xff1a;所有情况下&#xff0c;…

Python tkinter (8) ——Spinbox控件

Python的标准Tk GUI工具包的接口 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— Button标签 Python tkinter (3) —— Entry标签 Python tkinter (4) —— Text控件 Python tkinter (5) 选项按钮与复选框 Pyt…

数据结构【图的遍历】

数据结构之图 图的类型定义和存储结构图的遍历遍历的定义图的特点图常用的遍历深度优先搜索 DFS&#xff08;DepthFirstSearch&#xff09;算法实现算法效率分析 广度优先搜索 BFS&#xff08;BreadthFirstSearch&#xff09;算法实现算法效率分析 DFS与BFS算法效率比较 图的类…

iOS_Xcode_LLDB调试常用命令

文章目录 结构常用命令&#xff1a;1、流程控制&#xff1a;2、常用命令3、进程信息&#xff1a;4、寄存器&#xff1a;register5、镜像&#xff1a;image6、内存&#xff1a;memory7、符号断点&#xff1a;breakpoint8、内存断点&#xff1a;watchpoint9、Tips&#xff1a; 结…