深入研究 RAG 流程中的关键组件

我们已经看到了整个RAG流程,并获得了第一手的实践经验,您可能会对RAG流程中一些组件的使用和目的存在很多疑惑,比如RunnablePassthrough。在本节中,我们将进一步了解这些关键组件。

RAG的核心模型思想是将一个复杂的任务分解为多个小而简单的任务组合,分而治之的策略在处理大型和复杂问题时非常有用。让我们先来看一个非常简单的RAG流水线:


from langchain_core.runnables import Runnable, RunnableSequence# 定义第一个任务:输出 "hello"
class TaskA(Runnable):def invoke(self, input, context=None):return input + " a"# 定义第二个任务:输出 "beautiful"
class TaskBeautiful(Runnable):def invoke(self, input, context=None):return input + " beautiful"class TaskDay(Runnable):def invoke(self, input, context = None):return input + " day!"
# 创建任务实例
task_a = TaskA()
task_beautiful = TaskBeautiful()
task_day = TaskDay()# 使用"|"操作符重载Runnable
rag_chain = task_a | task_beautiful | task_day
output = rag_chain.invoke("what")
print(output)

上面代码的输出是"what a beautiful day"。可以看到Runnable类重载了"|"操作符,我们可以将Runnable的实例组合在一起,并且最后一个Runnable实例的输出成为下一个Runnable实例的输入。同时,我们需要确保每个Runnable实例提供invoke接口,以便数据在连接的Runnable实例之间传递。

回到RAG流程中使用的组件,RunnablePassThrough实际上类似于以下代码:


class DoNothing(Runnable):def invoke(self, input, context=None):return input

让我们看一个例子:


passthrough = RunnablePassthrough()
input_data = {"msg": "this is a test"}
output_data = passthrough.invoke(input_data)
print(output_data)

运行上面的代码将输出: {‘msg’: ‘this is a test’}

RunnablePassthrough通常在管道中用作占位符或连接器,以连接两个功能管道,但它实际上可以对其输入数据进行一些简单的更改:


# 原始数据
input_data = {"message": "Hello, World!", "status": "initial"}passthrough = RunnablePassthrough.assign(result = lambda x: "processed")# 使用输入数据调用
output_data = passthrough.invoke(input_data)print(output_data)

这里我们需要确保输入数据是字典形式,且assign的参数为lambda表达式,运行上述代码得到以下结果:


{'message': 'Hello, World!', 'status': 'initial', 'result': 'processed'}

Runnable对象可以像下面这样将几个函数链接在一起:


def task1(input1):return f"task1:{input1}"def task2(input1):return f"task2:{input1}"def context(input):return f"context: {input}"rag_chain = RunnablePassthrough().assign(context=context) | task1 | task2
res = rag_chain.invoke({"invoke": "input for invoke"})
print(res)

invoke调用将数据发送到RunnablePassthrough对象,数据未更改地输出,然后数据将发送到task1,task1的输出将作为task2的输入。运行上述代码的结果为:


task2:task1:{'invoke': 'input for invoke', 'context': "context: {'invoke': 'input for invoke'}"}

另一个需要了解的组件是RunnableMap,它允许我们将多个Runnable对象组合在一起,可以并行或顺序运行。RunnableMap对象就像一个字典,字典中的键就像分支或步骤,可以在相同输入上独立运行。当我们需要多个步骤或函数独立处理相同输入时,这非常有用。让我们来看一个示例:


from langchain_core.runnables import Runnable, RunnableMap# 定义第一个任务:输出 "task1"
class Task1(Runnable):def invoke(self, input, context=None):return f"task1 for {input}"class Task2(Runnable):def invoke(self, input, context=None):return f"task2 for {input}"
pipeline = RunnableMap({"task1": Task1(),"task2": Task2(),
})input_data = "input data"
output_data = pipeline.invoke(input_data)
print(output_data)

传递给RunnableMap的映射中每个键的值都应实现invoke接口,pipeline.invoke调用将并行触发映射中每个值的invoke调用。上述代码的输出为:


{'task1': 'task1 for input data', 'task2': 'task2 for input data'}

最后一个我们需要了解的组件是RunnableParallel,它类似于RunnableMap,它们之间可能有一些细微差别,但在此不重要。我们可以将RunnableParallel视为RunnableMap,值得注意的一点是RunnableParallel的assign。让我们来看代码示例:


from langchain_core.runnables import Runnable, RunnableParallel, RunnableMap
import time
# 定义第一个任务:输出 "a"
class TaskA(Runnable):def invoke(self, input, context=None):time.sleep(1)return input + " a"# 定义第二个任务:输出 "beautiful"
class TaskBeautiful(Runnable):def invoke(self, input, context=None):time.sleep(2)return input + " beautiful"class TaskDay(Runnable):def invoke(self, input, context = None):time.sleep(3)return input + " day"
# 创建任务实例class TaskAssign(Runnable):def invoke(self, input, context = None):time.sleep(3)print(f"input: {input}")return {**input}start = time.time()
parallel_tasks = RunnableParallel({"taskA": TaskA(),"taskBeautiful": TaskBeautiful(),"TaskDay": TaskDay(),
}).assign(taskAssign=TaskAssign())
output = parallel_tasks.invoke("what")
print(f"output for rag run parallelly: {output}")
end = time.time()
print(f"time for rag run parallel: {end - start}" )

上面代码的输出为:


input: {'taskA': 'what a', 'taskBeautiful': 'what beautiful', 'TaskDay': 'what day'}
output for rag run parallelly: {'taskA': 'what a', 'taskBeautiful': 'what beautiful', 'TaskDay': 'what day', 'taskAssign': {'taskA': 'what a', 'taskBeautiful': 'what beautiful', 'TaskDay': 'what day'}}
time for rag run parallel: 6.011621713638306

从输出可以看出,在RunnableParallel中使用assign时,它会首先执行传递给RunnableParallel的映射中的任务,然后使用结果字典作为TaskAssign的参数,最终输出为RunnableParallel的字典和一个键为"TaskAssign"的条目,值为TaskAssign的返回结果。

最后,让我们重新构建上一节的RAG流水线,如下所示:


def task_from_docs(input):print(f"task from docs: {input}")print(f"input['context']: {input['context']}")return lambda x: format_docs(input["context"])rag_chain_from_docs = (RunnablePassthrough.assign(context=(task_from_docs))
)rag_chain_with_source = RunnableParallel({"context": retriver,"question": RunnablePassthrough(),
}).assign(answer=rag_chain_from_docs)
'''
rag_chain_with_source的invoke将并行触发retriver、RunnablePassthrough的invoke,
然后将得到的字典结果发送到rag_chain_from_docs流水线,再将该字典发送到task_from_docs函数,并将
输出作为字典中的"context"键的值
'''
res = rag_chain_with_source.invoke("How does RAG compare with fine-tuning")
print(f"context of res {res['context']}")
print(f"question of res {res['question']}")#res将用作调用rag_chain_from_docs的参数,并将其传递给task_from_docs调用,
#task_from_docs将提取字典中context的值并传递给format_docsrag_chain = rag_chain_with_source | prompt | llm | StrOutputParser()
response = rag_chain.invoke("How does RAG compare with fine-tuning")
print(f"final rag response: {response}")

上面代码运行后所得结果如下:

Retrieval-Augmented Generation (RAG) and fine-tuning are two different approaches to enhancing the capabilities of Large Language Models (LLMs). RAG combines the strengths of LLMs with internal data, allowing organizations to access and utilize their own data effectively. It enhances the accuracy and relevance of responses by fetching specific information from databases in real time, thus expanding the model's knowledge beyond its initial training data. RAG is particularly useful for organizations that need to leverage their proprietary data or the latest information that was not included in the model's training set.On the other hand, fine-tuning involves adjusting the weights and biases of a pre-trained model based on new training data. This process permanently alters the model's behavior and is suitable for teaching the model specialized tasks or adapting it to specific domains. However, fine-tuning can be complex and costly, especially as data sources evolve, and it may lead to issues like overfitting.In summary, RAG is more about integrating real-time data retrieval to enhance model responses, while fine-tuning is about permanently modifying the model based on new data. Each approach has its advantages and limitations, and the choice between them depends on the specific needs and resources of the organization.
``基于上述知识,我们可以轻松理解代码。rag_chain_with_source的invoke将生成一个带有context和question键的字典,context的值为retriver.invoke("How does RAG compare with fine-tuning")的结果,question的值为RunnablePassthrough().invoke("How does RAG compare with fine-tuning")的结果,即原始字符串本身。然后带有context和question的字典作为task_from_docs的输入。在task_from_docs中,取出context键的值传递给format_docs,task_from_docs的输出将发送给prompt函数。prompt的输出将生成一个带有问题和上下文的提示,提示发送到ChatGPT以获得最终返回结果。

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

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

相关文章

绿宝石二十载:如何打破国外在高端电容市场的垄断?

【哔哥哔特导读】作为本土电容器企业,绿宝石凭借二十年的技术创新与市场深耕,在高端电容市场取得了显著突破。从铝电解电容器到叠层式固态电容器,绿宝石是如何做到的? 在当今竞争激烈的电子元器件市场中,技术创新、定…

JS中DOM和BOM

DOM DOM(文档对象模型)是一个跨平台和语言独立的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。在网页浏览器中,DOM 通常表示 HTML 或 XML 文档的对象模型。DOM 将网页内容视为节点树,其中每个节点都…

从配置anaconda到配置pycharm

Anaconda 是全球领先的数据科学与机器学习平台,专为开发者、数据分析师设计。通过 Anaconda,可以轻松管理数据环境、安装依赖包,快速启动数据分析、机器学习项目。 丰富的 Python 数据科学库:Anaconda 集成了常用的 Python 数据科…

JAVA开源项目 影城管理系统 计算机毕业设计

本文项目编号 T 045 ,文末自助获取源码 \color{red}{T045,文末自助获取源码} T045,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 用…

无人机测绘遥感技术算法概述!

一、数据采集算法 航线规划算法 根据测绘任务需求,利用地理信息系统(GIS)和遥感技术,对无人机进行航线规划。 考虑地形、气候、障碍物等因素,优化飞行路径,确保数据采集的完整性和准确性。 传感器控制算…

剪绳子小游戏 #线上游玩 #介绍 #部分代码截图展示

自制的割绳子小游戏。 线上游玩地址:戳Rain的剪绳子游戏。 不得不承认做了很久。。。 简单介绍一下。。。 割绳子游戏机制 物理引擎 《割绳子》的核心在于其高度逼真的物理引擎。游戏中的所有物体,包括糖果、绳索、气球、弹簧等,都遵循…

分享一波 百度 C++ 服务器开发面试

之前有粉丝反馈说,有没有 C 服务器开发的面试呀? 还真有,最近有 C 同学被百度从简历池捞起来面试了,目前经历了一二面,我把比较通用的面试问题抽离出来跟大家分享一波。 这次主要面试涵盖的知识点: MySQ…

使用ref对父子组件进行操作

子组件 <template><view><button v-if"option.isShow" click"buttonClick">子组件关闭按钮</button></view> </template><script>export default {data() {return {option: {num: 0}}},methods: {// 父组件调用…

【从零开始的LeetCode-算法】3289. 数字小镇中的捣蛋鬼

数字小镇 Digitville 中&#xff0c;存在一个数字列表 nums&#xff0c;其中包含从 0 到 n - 1 的整数。每个数字本应 只出现一次&#xff0c;然而&#xff0c;有 两个 顽皮的数字额外多出现了一次&#xff0c;使得列表变得比正常情况下更长。 为了恢复 Digitville 的和平&…

ros入门:服务通信(c++)

ros服务通信的原理类似于RPC&#xff0c;其实现原理如下图所示 实验目标 创建一个客户端和一个服务端客户端向服务端发送两个参数num1和num2服务端接收到客户端的两个参数num1和num2&#xff0c;并计算出num1num2的求和结果&#xff0c;最后返回给客户端客户端接收服务端的计算…

域控操作二十四:主域故障辅域接替

模拟环境&#xff1a;上海DC1故障无法开机&#xff0c;导致只有一个DNS的电脑无法上网&#xff08;实际可以添加DC2但是为了实验就不说了&#xff09; FSMO还在DC1上 使用powershell把角色迁移到DC2 ntdsutil roles connections connect to server DC2SHA.whbk.cn quitSeize …

网络安全认证的证书有哪些?

在网络安全领域&#xff0c;专业认证不仅是个人技术能力的象征&#xff0c;也是职业发展的重要推动力。随着网络安全威胁的日益严峻&#xff0c;对网络安全专业人才的需求也在不断增长。本文将介绍一些网络安全认证的证书&#xff0c;帮助有志于从事网络安全行业的人士了解并选…

【MIT-OS6.S081笔记1】xv6环境搭建

最近开始做一个操作系统的神课MIT-OS6.S081&#xff0c;我做的是老版本的2020版本的&#xff0c;环境使用的是VirtualBox的Ubuntu系统&#xff0c;在这里记录一下学习的过程。首先需要搭建一下环境&#xff0c;参考官网Tools Used in 6.S081&#xff0c;这个知乎文章也写得很好…

html练习2

实现下列图片的效果 代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>* {margin: 0;padding: 0;}#menu {background-color: #0c0048;width: 100%;height: 50px;margin: auto;…

ViT面试知识点

文章目录 VITCLIPBlipSAMFast TransformerYOLO系列问题 BatchNorm是对一个batch-size样本内的每个特征做归一化&#xff0c;LayerNorm是对每个样本的所有特征做归一化。 Layer Normalization&#xff08;层归一化&#xff0c;简称LayerNorm&#xff09;是一种在深度学习中常用…

意大利名模 Vittoria Ceretti

1998年出生&#xff0c;相貌一般&#xff0c;身材高&#xff0c;世界著名的维多利亚秘密花园时装秀入选模特之一&#xff0c;但愿她没上过萝莉岛。

Java - 免费图文识别_Java_免费_图片转文字_文字识别_spring ai_spring ai alibaba

本文主要是介绍借助阿里云免费的大模型额度来做高质量的图转文识别&#xff0c;图片转文字&#xff0c;或者文字识别都可以使用&#xff0c;比传统的OCR模式要直接和高效很多 。 本文使用的技术是spring ai qwen vl 。 Qwen vl有 100万Token 免费额度&#xff0c;可以用来免费…

MR30分布式IO模块与高效PLC协同

在现代工业自动化领域中&#xff0c;数据采集与控制系统扮演着至关重要的角色。其中&#xff0c;可编程逻辑控制器&#xff08;PLC&#xff09;和分布式IO模块&#xff08;Distributed I/O Modules&#xff09;是这一领域的两大核心组件。本文将详细介绍MR30分布式IO模块与PLC如…

深基坑结构施工安全在自动化监测不知道怎么布设测点?不知道用什么设备?

01 基坑监测背景 随着我国城市建设的发展&#xff0c;基坑规模和开挖深度不断增加。在基坑开挖过程中&#xff0c;如何尽快的在第一时间了解基坑的变形情况&#xff0c;并动态评估基坑的结构安全&#xff0c;避免事故的发生。与其它监测方法相比&#xff0c;实现自动化监测、信…

一张图简单讲述Mamba的演进过程

这张图表提供了 RNN&#xff08;1986&#xff09;、LSTM&#xff08;1997&#xff09;、Transformer&#xff08;2017&#xff09;和 Mamba&#xff08;2024&#xff09;四种不同的神经网络架构在训练阶段、测试阶段和额外问题方面的对比。可以看出&#xff0c;Mamba 作为一种最…