·

一文带你了解大模型的RAG(检索增强生成) | 概念理论介绍+ 代码实操(含源码)

Published at 2024-08-27 11:29:26Viewed 199 times
Professional article
Please reprint with source link

针对大型语言模型效果不好的问题,之前人们主要关注大模型再训练、大模型微调、大模型的Prompt增强,但对于专有、快速更新的数据却并没有较好的解决方法,为此检索增强生成(RAG)的出现,弥合了LLM常识和专有数据之间的差距。

今天给大家分享的这篇文章,将介绍RAG的概念理论,并带大家利用LangChain进行编排,OpenAI语言模型、Weaviate 矢量数据库(也可以自己搭建Milvus向量数据库)来实现简单的 RAG 管道。

什么是RAG?

RAG的全称是Retrieval-Augmented Generation,中文翻译为检索增强生成。它是一个为大模型提供外部知识源的概念,这使它们能够生成准确且符合上下文的答案,同时能够减少模型幻觉。

知识更新问题

最先进的LLM会接受大量的训练数据,将广泛的常识知识存储在神经网络的权重中。然而,当我们在提示大模型生成训练数据之外的知识时,例如最新知识、特定领域知识等,LLM的输出可能会导致事实不准确,这就是我们常说的模型幻觉。如下图所示:

因此,弥合大模型的常识与其它背景知识之间的差距非常重要,以帮助LLM生成更准确和更符合背景的结果,同时减少幻觉。

解决方法

传统的解决方法是通过微调神经网络模型来适应特定领域的专有信息。尽管这种技术很有效,但它属于计算密集型的,并且需要技术专业知识,使其难以灵活地适应不断变化的信息。

2020 年Lewis等人,在知识密集型 NLP 任务中,提出了一种更灵活的技术,称为检索增强生成(RAG)[参考论文:https://arxiv.org/abs/2005.11401]。在本文中,研究人员将生成模型与检索器模块相结合,以提供来自外部知识源的附加信息,并且这些信息可以很方便的进行更新维护。

简单来说,RAG 对于LLM来说就像学生的开卷考试一样。在开卷考试中,学生可以携带参考材料,例如课本或笔记,可以用来查找相关信息来回答问题。开卷考试背后的想法是,测试的重点是学生的推理能力,而不是他们记忆特定信息的能力。

同样,事实知识与LLM的推理能力分离,并存储在外部知识源中,可以轻松访问和更新:

  • 「参数知识」:在训练期间学习到的知识,隐式存储在神经网络的权重中。
  • 「非参数知识」:存储在外部知识源中,例如向量数据库。

一般的 RAG 工作流程如下图所示:

「检索(Retrive)」 根据用户请求从外部知识源检索相关上下文。为此,使用嵌入模型将用户查询嵌入到与向量数据库中的附加上下文相同的向量空间中。这允许执行相似性搜索,并返回矢量数据库中最接近的前 k 个数据对象。

「增强(Augment)」 用户查询和检索到的附加上下文被填充到提示模板中。

「生成(Generate)」 最后,检索增强提示被馈送到 LLM。

LangChain实现RAG

上面介绍了RAG产生和工作原理,接下来将展示如何使用LangChain,结合 OpenAI LLM 、Weaviate 矢量数据库在 Python 中实现 RAG Pipeline。

基础环境准备

1、安装所有需要依赖的相关python包,其中包括用于编排的langchain、大模型接口openai、矢量数据库的客户端 weaviate-client。

pip install langchain openai weaviate-client

2、申请OpenAI的账户,要获取 OpenAI API 密钥,如下图所示:

3、在项目根目录创建.env文件,用来存放相关配置文件,如下图所示。

4、在main目录中,加载配置文件信息,这里用到了python-dotenv包。

向量数据库

接下来,你需要准备一个矢量数据库作为保存所有附加信息的外部知识源。该矢量数据库是通过以下步骤填充的:1)加载数据;2)数据分块;3)数据块存储。

「加载数据」:这里选择了一篇斗破苍穹的小说,作为文档输入 。文档是txt文本,要加载文本这里使用 LangChain 的 TextLoader。

from langchain.document_loaders import TextLoader
loader = TextLoader('./斗破苍穹.txt')
documents = loader.load()

「数据分块」:因为文档在其原始状态下太长(将近5万行),无法放入大模型的上下文窗口,所以需要将其分成更小的部分。LangChain 内置了许多用于文本的分割器。这里使用 chunk_size 约为 1024 且 chunk_overlap 为128 的 CharacterTextSplitter 来保持块之间的文本连续性。

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size=1024, chunk_overlap=128)
chunks = text_splitter.split_documents(documents)

「数据块存储」:要启用跨文本块的语义搜索,需要为每个块生成向量嵌入,然后将它们与其嵌入存储在一起。要生成向量嵌入,可以使用 OpenAI 嵌入模型,并使用 Weaviate 向量数据库来进行存储。通过调用 .from_documents(),矢量数据库会自动填充块。

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Weaviate
import weaviate
from weaviate.embedded import EmbeddedOptions

client = weaviate.Client(
  embedded_options = EmbeddedOptions()
)

vectorstore = Weaviate.from_documents(
    client = client,    
    documents = chunks,
    embedding = OpenAIEmbeddings(),
    by_text = False
)

RAG实现

「第一步:数据检索」 将数据存入矢量数据库后,就可以将其定义为检索器组件,该组件根据用户查询和嵌入块之间的语义相似性获取相关上下文。

retriever = vectorstore.as_retriever()

「第二步:提示增强」 完成数据检索之后,就可以使用相关上下文来增强提示。在这个过程中需要准备一个提示模板。可以通过提示模板轻松自定义提示,如下所示。

from langchain.prompts import ChatPromptTemplate
template = """你是一个问答机器人助手,请使用以下检索到的上下文来回答问题,如果你不知道答案,就说你不知道。问题是:{question},上下文: {context},答案是:
"""
prompt = ChatPromptTemplate.from_template(template)

「第三步:答案生成」 利用 RAG 管道构建一条链,将检索器、提示模板和 LLM 链接在一起。定义了 RAG 链,就可以调用它了。

from langchain.chat_models import ChatOpenAI
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

rag_chain = (
    {"context": retriever,  "question": RunnablePassthrough()} 
    | prompt 
    | llm
    | StrOutputParser() 
)

query = "萧炎的表妹是谁?"
res=rag_chain.invoke(query)
print(f'答案:{res}')

总的来说,RAG的生成过程如下图所示:

总结

本文介绍了 RAG 的概念及其背后的一些理论,本文通过Python、LangChain将其实现,在此过程中使用了 OpenAI的ChatGPT接口(可以自己搭建chatGLM3)、Weaviate矢量数据库(可以自己搭建Milvus )、OpenAI 嵌入模型实现了 RAG 管道。


原文链接:https://blog.csdn.net/m0_59596990/article/details/135310933

0 人喜欢

Comments

There is no comment, let's add the first one.

弦圈热门内容

center h1 in the middle of screen(示例提问)

How can I center horizontally and vertically a text? I don't want to use position absolute because I try with it and my other div getting worse. Is there another way to do that ?div { height: 400px; width: 800px; background: red; }<div> <h1>This is title</h1> </div>

写给新诗的入门者的几条建议

 我来为大家推荐几个诗人帮助大家更好地入门和学习新诗。八十年代是个文学热潮,其中诗歌发展尤为迅速,有笑话说:“一板砖下去砸晕十个大学生,九个都是诗人。”相应地,朦胧诗人在大众的世界里流传开来。  相信有许多朋友了解新诗是从海子和顾城开始的,那么在这之后,当然可以深耕这几位诗人,也可以去了解其他的诗人。我个人是非常喜欢穆旦的,而且我认为穆旦是一位非常值得后来者学习的大诗人。相较于以朦胧诗和后朦胧诗出名的一代人,穆旦处在中国新诗草创和形成的时期,语言的张力和新意象的创造都是十分直接和有力的,造成的影响也是多样的,这对于后来者的学习很有益处。而且穆旦在吸收西方现代诗歌营养的同时,也在吸收转化拜伦雪莱等浪漫主义诗人的手法,他的几首诗剧(《神魔之争》《森林治魅——祭胡康河上的白骨》等)我都喜欢,而且写的很好也很动人。晚年的穆旦的作品达到了返璞归真的境界,言语朴实,但是寄意深远。或许晚年的穆旦和旧诗更为亲切,读者入门也更简单。总之,在新诗形象的塑造、意象的表达以及技巧的展示中,穆旦毫无疑问都是上等的,再进一步讲,穆旦诗中隐现的民族、苦难的民众、分裂的祖国、迷惘的自我这一系列形 ...

Aurélien Géron人工智能入门教材:Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow

这是本手把手教你入门人工智能的教材,作者是Aurélien Géron。这本书是本畅销书,非常火,被翻译成了多国语言。本书的作者也把自己的这本书免费上传到自己的网站上,不知道现在还是不是,反正我当时下了😇。我一个做算术几何的,当初之所以会关注人工智能,一方面是当时人工智能挺火的,就连算术几何领域也有专家跟计算机科学家们合作,比如Geordie Williamson以及著名的Peter Scholze。Peter Scholze弄了个Liquid Tensor Experiment(液体张量实验),用于所谓的自动定理证明,而这个实验源自于Scholze跟Dustin Clausen在解析几何方面的合作,即将代数几何应用于解析几何。扯远了,回到正题。这本教材可以说图文并茂,配有丰富的插图,并且讲解非常通俗易懂,对初学者非常友好,基本上就需要有点数学分析的基础就可以读了。而且书中还会附上代码过程,给你随时练手,毕竟这个跟编程紧密结合的学科,还是需要编程实践才好学懂的。现在我把这本书分享给对人工智能感兴趣的人。PS:这本书总共八百多页,而且插图很多,因此体积较大。我将其分成三个压缩包分卷上传。 ...

初二,在学交代同调李代数,下一步怎么办?

知乎提问:很抱歉用这个吸引目光的标题骗人进来,但我的确很需要帮助目前我的情况是标题上提到的交代什么的学了,但是和体验卡似的,学完两三周内见题直接秒(有点夸张,但都会基本上差不多),之后就连自己在书上写的过程都看不懂了…再加上课内也没法不管主要问题其实就是时间不够加自控力不足,也就是如何更好自控和如何协调数学与课内的关系(数学扔掉是每个链都有上界的非空偏序集没有极大元,但我课内在我们学校排名才前10%左右,就这个成绩还是考前暂时不学数学备考的结果,更何况我父母要求的中考目标换算到我们学校差不多要排名前3%)总结就是数学和课内分配问题,但我数学扔不下,课内又有强制目标目前想到的解决方法有丘班,但我高数数分什么的记忆性强的全忘了(点明某三角函数的一堆积分,我得现场推),用的书又不深(同济高数+普林斯顿的两本),真要考丘班得消耗半个学期才基本上能保证应该没问题(如果只按0试(好像是一试还是什么)的难度没有较大幅度变动的话)还有生产一篇学术垃圾之后和校方交涉,但这个问题更多求点更靠谱的解决方法,谢谢!(又发了一遍是因为之前发到想法去了...我好蠢)我的回答:说实话所谓的丘班根本不是给普通家庭的学 ...

数学入门应该看哪些书?有什么入门书后看了以后能让人爱上数学?

知乎提问:有什么数学方面的入门书能让人看了后会爱上数学的?参加工作很长一段时间了,但对数学的认识和应用都一直处于很初级的水平(初中时的水平吧)。我知道这个数学世界很精彩,也很迷人,也许我会爱上它而不能自拔,但我先得找到一道进入这个世界的门我的回答:如果你对微分几何感兴趣,可以尝试读Loring W Tu微分几何经典入门教材:An Introduction to ManifoldsLoring W Tu微分几何教材:Differential Geometry Connections, Curvature, and Characteristic Classes。如果你对自己的能力比较自信可以先读陈省身的《微分几何讲义》,我以前初三高一的时候就是先看的这本书,后来才看的Loring W Tu。关于Loring W Tu的这两本书,先读第一本,第一本只需要有数分高代的基础就完全够了。有了第一本的基础后,可以读第二本。把这两本读懂后可以读 Jürgen Jost黎曼几何与几何分析教材:Riemannian Geometry and Geometric Analysis。我当初高二的时候就是因为读 ...

最近有人反馈网站卡、打不开,我自己也试过这种情况,已再次对弦圈进行优化

最近这段时间,由于使用弦圈的人数比以前多了,尤其是同一时间使用的人数,这就导致网站加载起来会比较卡,甚至有时候出现502错误,也就是打不开网站。遇到这种问题,一般等一等刷新一下就过去了,但是还是对用户体验造成了不好的影响。昨天开始受到反馈后,我再次进行了测试,发现打开文章的速度确实比打开首页的速度要慢,也就是说弦圈部分页面的加载速度确实有问题,需要优化。接着首页打开的速度其实也慢了一些了。于是我重新优化了一下那些加载比较慢的页面的代码,然后还重新优化了一下后端的一些代码。经过今天的再次优化,目前我打开弦圈的页面,感觉也比之前顺畅了一些。不过目前服务器的配置确实有点吃不消了,CPU倒还好,主要是内存真的不够用了,可能卡主要也是内存不够的原因吧,我目前也在考虑换个内存更高的服务器。18:51更新:刚刚已经将弦圈的前端代码放到另一个内存更多的服务器上,在这个过程中一不小心让网站中断了一会儿。现在迁移已经全部完成!目前弦圈使用了两台服务器,一台2核4G用于前端,另一台2核2G用于后端,还有一台1核1G的云数据库。另外我还给域名挂上了CDN加速,目前来看应该比之前顺畅不少。

在已经掌握大学本科微积分、线代、概率的基础上怎么更进一步学习数学?

知乎提问:如题,我在准备考研数学中终于领略到了一些数学的美妙之处了,现在特别感兴趣,想等着考完试有时间再精进一下也为下一步的学习打打基础,那么请教各位大佬们我该去先去学哪些书呢?数学分析?高等代数?我作为一个普通工科生不太了解这些书的入门顺序,请各位数学大佬指点下,谢谢啦!!!我的回答:如果对微分几何感兴趣,可以尝试读 Loring W Tu微分几何经典入门教材:An Introduction to Manifolds 和 Loring W Tu微分几何教材:Differential Geometry Connections, Curvature, and Characteristic Classes。先读第一本,第一本最简单你的基础完全够了。有了第一本的基础后,可以读第二本。把这两本读懂后可以读 Jürgen Jost黎曼几何与几何分析教材:Riemannian Geometry and Geometric Analysis。如果对代数几何感兴趣,那就先入门交换代数,可以读Zariski交换代数经典教材Commutative Algebra系列(pdf可复制版)、Atiyah交换代数 ...

作为一个年轻的数学工作者,你们是如何独立于导师选定问题的?

知乎提问:感觉有意思的我做不动,我会做的又无趣(且无人关注)。那请问你们是如何自己选定一个有意思且做的动的问题的?我的回答:想要找问题,首先需要阅读很多相关的文献,但是这一步其实很多人都会做了,他们的问题是哪怕读了再多的文献,似乎也不知道有啥问题可做。其实在我看来原因无非那么几个第一是他们自以为自己掌握了正确的学习方法,看过的文献每一个细节都彻底弄懂弄透了,实际上他们连自己学的东西都没搞明白;第二是他们好高骛远,瞧不起一些比较基本的小问题,却不知道很多重要且有趣的理论往往来自于不经意间一些最简单的问题;第三就是科研能力问题了,这方面要展开太多可讲了,如数学成熟度不够、计算能力不足导致无法将脑海里的理论实现,或是想象力不足无法构想出一个一般性的理论,等等。这三点能做好,基本上就能脱离导师,独立自主做出研究成果了。其中第三点是最体现一个人数学天赋的地方了,不过其也是建立在第一点跟第二点的基础之上的。关于如何学习达到research level的程度,不是一两句话就能简单讲完的,可以参考我之前的文章和帖子,其实只要把第一点做好,且做到极致,第二点只要你调整好自己的心态就能做到。想学好数学不是 ...

基础数学几何方向应该如何学习?

前辈们好,本人是一名大二数学系学生,目前大致了解点集拓扑基本概念(但还没怎么做题),代数拓扑看过基本群和同伦型,复变和抽代这学期正在学。之所以问这个问题是因为之前看到中科大梁永祺老师的主页看到了这样一句话:让我感觉非常奇妙,也想见识一下这精华的部分(希望在大四毕业前能做到吧!😭),也激发了我学习代数与几何方向的想法。其中代数方向其实学习路径了解的差不多了,大致就是学完抽象代数后同调、交换和lie代数都可以学了,但几何方向还不甚了解,很多几何方向的课学校都是大三大四才有,甚至开不出来,因此只能自行学习。这个问题其实之前也问了不少前辈,但发现每个人的学习路径(有的是从微分几何上同调那边学,有的是先接触的代数拓扑等)都不一样,而几何方向又十分繁杂,理不清学习顺序,手头上有很多纸质书、电子书、网课等也无从下手;或者有些内容可能比较难且深入某个具体方向,以后不做这个方向可能根本不会用到,不知道该学多少合适。所以想多听取一点建议以便自己之后逐一尝试,例如:学习路径、参考书目、课程视频等等。谢谢各位!😘

雪的不遇者

作为过来人,迎接新客,咳嗽声总在暗地里起伏,瓷勺跌在了地上和空气一样冷淡,我的第二个爱人忘记了今天是什么名字,书啊迷惘的盐,是否意味我站在早晨之外向你们投来无主的目光,那颗心早晚都会走,像以前一样寻章摘句,获得古代传承的快感当一回宾客,接触那些表象的伪装丰富的伪装,六点钟的爱情喧哗这就是我们的日子,我们定义了爱既然你不存在,我同意你的消失在我们谈话的节奏趋于平稳之后,公交也已驶来,多好的机会,我想象着网状碎片藏在脸颊里,人总在落雪之后独立,而你不能独立我们去西伯利亚的天空,俄罗斯的忧郁丛生,深灰色必将成为主的语言一点一滴,在我的血脉里横流,小人曾梦忆,却不知城市有多衰老霜花,彩灯,麦克风,只占世界的诸多分之一,你总爱权衡可秤怎么能装下喜欢走丢的心?还没到来,远山也未拾起衣冠我们只是一个相册,城市深陷其中反复圈定,养一头温良的房子接纳雪的受难,你一直都很坚定这些如同名字一样模糊的骗局引诱我们在云层里分崩离析

关于目前各大平台引流实践的总结:如今各大平台都在封锁流量,在这么一个垄断的大背景下,小平台只能在夹缝中生存......

本文修改自我今天发推的几篇内容。以后我推特也懒得发再英文了,之前一直想搞国际化,国际化个der,我之前一直听信所谓的国外好赚钱的言论。其实真的尝试过才知道,国外也封锁你。现在弦圈的注册用户和流量仍然都是来自国内的,全靠社媒支撑着,SEO零流量,去tm的SEO,以后我也学小红书那样,把所有搜索引擎给屏蔽掉。 现在大家都在封锁自己的流量,不让你将流量引走,推特更是如此,发外链几乎零点击。现在各大社交平台,对引流管得最宽的唯有知乎了,可以给你随意发外链,而且对流量影响不大。 其他平台,如小红书、公众号,连外链都不能发,你只能发文本链接,公众号倒是可以填那个阅读原文,但谁会点? 不过即便是知乎,你发链接也仅仅只是为了引流罢了,知乎的外链有跳转页面,实测相当于屏蔽SEO。所以想要靠知乎发外链搞SEO的省省力吧,用处不大,而且外链本身就是引流的价值大于SEO,与其费时费力搞SEO,不如好好运营社媒。而在知乎上疯狂发外链引流,也不是高枕无忧的。偶尔在某些问题下回答,会引来某些无聊的人的恶意举报,一举报一个准,申诉都没用。 像那种“有什么有趣的网站推荐”、“有什么有深度的网站”,看似绝佳的网站宣传的问 ...

学习应该先追求深度还是广度?

知乎提问:学习应该先追求深度还是广度?我的回答:在我看来应该先追求广度,有了一定的广度再开始追求深度。因为选择深入哪个领域进行学习,是先需要广泛涉猎,对各个领域先有个初步的理解,接着再在这些领域中挑选一个进行深度学习。我当初学数学的时候,也是先大量的看各个数学分支的教材,广泛涉猎。然后挑选其中几个感兴趣的领域:微分几何和代数几何,开始着重学习。最后有了一定的数学成熟度,才开始全力追求深度,决定不仅是做代数几何,而且是代数几何中的算术几何。因此,比起一上来就追求深度,我认为先追求广度更加有效。因为任何一个领域都有成熟度这个概念,你没有一定的成熟度,过早的追求深度看似少走了很多弯路,但不过是拔苗助长。