|
为什么要使用RAG?
当下领先的大语言模型(LLMs)通过大规模数据训练来掌握广泛的普遍知识,这些知识存储在其神经网络的权重中。然而,如果要求LLM生成涉及其训练数据以外的知识(如最新、专有或特定领域信息),就会出现事实上的错误(称为"幻觉")。
通过使用微调(fine-tuning)或是检索增强生成(RAG)方式都可解决这一问题。但通常使用微调通常需要耗费大量计算资源、成本高昂,且需要丰富的微调经验。此外Fine tuning需要代表性的数据集且量也有一定要求,且Fine
tuning 并不适合于在模型中增加全新的知识或应对那些需要快速迭代新场景的情况。本文介绍的是另外一种方式,通过RAG的方式检索数据信息,这种方式成本低且可以快速地实现。
检索增强生成(RAG)是一个概念,它旨在为大语言模型(LLM)提供额外的、来自外部知识源的信息,提高 AI 应用回复的质量及可靠性。这样,LLM 在生成更精确、更贴合上下文的答案的同时,也能有效减少产生误导性信息的可能。RAG主要解决了 LLM 常见挑战,如提供虚假信息、过时信息和非权威信息等问题。
在论文《知识密集型 NLP 任务的检索增强生成》中,介绍了一种新的技术。检索增强生成(Retrieval-Augmented
Generation,RAG)。这篇论文提出了一种新的模型架构,通过结合检索和生成两个阶段,解决了知识密集型NLP任务中的挑战。RAG有效利用外部知识库来增强模型性能,通过这种方式可以让LLM可以更易于查询到外部知识信息。RAG和LLM之间存在着互补关系。RAG可以被视为一种扩展了功能的LLM,它通过引入额外的检索步骤,使得LLM能够有效利用外部知识。这两种技术结合使用,可以在许多复杂的自然语言处理任务中取得更好的效果,为开发更强大的NLP系统提供了新的可能性。 检索:当接收到用户查询时,使用检索索引找到最相关的文档。具体来讲,对用户输入的查询信息Embedding转化为向量,再到向量数据库中检索其他匹配的上下文信息。通过这种相似性搜索,可以找到向量数据库中最匹配的相关数据。
增强:将向量数据库中检索到的信息与用户查询信息放到我们自定义的提示模板中。 生成:最后将上面经过检索以及增强后的提示内容输入到LLM中,LLM根据上述信息生成最终结果。
其中向量数据库里存储的是外部知识,通过嵌入模型将非结构化数据存储向量数据库中。具体流程如下图所示:加载:加载指定的数据,不同的文件可以通过不同的文档加载器完成。
拆分:通过文本拆分器将内容拆分成小块内容。这对于索引数据和将数据传递到模型都很有用,因为大块内容更难搜索,并且不适合模型的有限上下文窗口。
嵌入:利用Embedding技术可以将高维度的数据(例如文字、图片、 音频)映射到低维度空间,即把图片、音频和文字最终转化为向量来表示。其中,向量是一组数值,可以表示一个点在多维空间中的位置。
存储:需要一个向量数据库用来存储和索引分割后的向量,便于日后快速的检索数据。 LangChain 是一个开源的工具包,目标是帮助开发者快速构建 AI 应用程序。它提供了一系列的功能,如模型托管、数据管理和任务自动化等。通过LangChain我们可以快速地搭建一个RAG应用。
在这一部分,我们将展示如何利用Python 结合 OpenAI 的大语言模型、Weaviate的向量数据库以及 OpenAI 的嵌入模型来实现一个检索增强生成(RAG)流程。在这个过程中,我们将使用 LangChain 来进行整体编排。
准备好向量数据库,向量数据库(Vector Database)是一种以向量为基础的数据存储和查询系统,它利用向量空间模型来表示和查询数据。通过向量数据库将我们自己指定的资料转换为向量并写入到数据库。具体步骤如下:iii. 对分块内容进行嵌入,并存储这些块 importrequestsfromlangchain.document_loadersimportTextLoaderurl="https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"res=requests.get(url)withopen("state_of_the_union.txt","w")asf:f.write(res.text)loader=TextLoader('./state_of_the_union.txt')documents=loader.load()fromlangchain.text_splitterimportCharacterTextSplittertext_splitter=CharacterTextSplitter(chunk_size=500,chunk_overlap=50)chunks=text_splitter.split_documents(documents) fromlangchain.embeddingsimportOpenAIEmbeddingsfromlangchain.vectorstoresimportWeaviateimportweaviatefromweaviate.embeddedimportEmbeddedOptionsclient=weaviate.Client(embedded_options=EmbeddedOptions())vectorstore=Weaviate.from_documents(client=client,documents=chunks,embedding=OpenAIEmbeddings(),by_text=False) - Part 2 使用向量库中的数据检索用户提出的问题
retriever=vectorstore.as_retriever() fromlangchain.promptsimportChatPromptTemplatetemplate="""Youareanassistantforquestion-answeringtasks.Usethefollowingpiecesofretrievedcontexttoanswerthequestion.Ifyoudon'tknowtheanswer,justsaythatyoudon'tknow.Usethreesentencesmaximumandkeeptheanswerconcise.Question:{question}Context:{context}Answer:"""prompt=ChatPromptTemplate.from_template(template)print(prompt)生成:通过RAG链,可以通过将检索器、提示模板与LLM 相结合。下面的RAG链会对用户提出的问题先进行向量检索,再将检索后的数据和提示模板结合,最终LLM根据上述信息生成答案。
fromlangchain.chat_modelsimportChatOpenAIfromlangchain.schema.runnableimportRunnablePassthroughfromlangchain.schema.output_parserimportStrOutputParserllm=ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)rag_chain=({"context":retriever,"question":RunnablePassthrough()}|prompt|llm|StrOutputParser())query="WhatdidthepresidentsayaboutJusticeBreyer"rag_chain.invoke(query)其中rag_chain是核心部分,在这一步中构建了使用GPT-3.5大模型,并通过prompt增强问题后去向量数据库中检索答案的RAG链。
上面例子中,我们对LLM提出问题:”总统对布雷耶大法官是如何评价的“。LLM通过向量库检索后回复:"总统对布雷耶法官的服务表示感谢,并赞扬了他对国家的贡献。"
"总统还提到,他提名了法官凯坦吉·布朗·杰克逊来接替布雷耶法官,以延续后者的卓越遗产。"
总结 在基于 LLM实现的问答系统中使用 RAG 有三方面的好处:
确保 LLM 可以回答最新,最准确的内容。并且用户可以访问模型内容的来源,确保可以检查其声明的准确性并最终可信。
通过将 LLM建立在一组外部的、可验证的事实数据之上,该模型将信息提取到其参数中的机会更少。这减少了 LLM 泄露敏感数据或“幻觉”不正确或误导性信息的机会。
- RAG 还减少了用户根据新数据不断训练模型并随着数据的变化更新训练参数的需要。通过这种方式企业可以减低相关财务成本。
|