Advertisement

检索增强生成(RAG):从理论到 LangChain 实现

阅读量:

每天分享一篇专注于解决实际问题的外文资料吧!通过精准翻译和深入解析其核心内容,帮助读者提升解决实际问题的能力以及编写代码的能力.

欢迎关注公众号(NLP Research),及时查看最新内容

Retrieval-Augmented Generation (RAG): Based on the theoretical foundation, the implementation of RAG has been carried out using LangChain.

This article explores the concept of Retrieval-Augmented Generation (RAG), progressing from theoretical foundations to practical implementation using LangChain. The discussion highlights the integration of retrieval mechanisms with generative models to enhance text generation capabilities. It delves into the technical aspects, including mathematical formulations and algorithmic details, while also providing practical examples to illustrate real-world applications. The implementation section outlines a step-by-step process for setting up and optimizing RAG models, emphasizing the importance of fine-tuning parameters for optimal performance. Furthermore, the article addresses common challenges and offers strategies for overcoming them, concluding with a summary of key takeaways for practitioners in the field.


基于原始学术论文的理论基础,在 Python 中通过集成 OpenAI 的API、Weaviate 的向量化服务以及 LangChain 的任务驱动框架实现

自打人们认识到利用自己的专用数据能显著提升大型语言模型(LLM)的效果后,就开始了关于如何最为有效的方式弥合LLM常识与专用数据之间差异的探讨。围绕微调和检索增强生成(RAG)哪种更适合这一问题展开深入探讨后发现两种方法都能奏效。

本文将详细阐述 RAG 的概念,并着重探讨其理论基础。随后,文章将演示如何利用 LangChain、OpenAI 语言模型以及 Weaviate 向量数据库协同工作来构建一个相对简单的 RAG 管道系统。

什么是检索增强生成?

RAG的核心机制旨在整合LLM与外部知识库的信息资源。这种设计使得系统在回答复杂问题时能够更加依赖权威数据支持,并显著提升了整体性能表现。

问题

最新的大语言模型(LLM)在经过充分的大规模训练后得以实现,并成功地将知识储存在神经网络的权重参数即为长期存储的知识之中。然而,在某些情况下使用该模型时需要注意其局限性:当模型被用来生成一个需要其训练数据中未包含的知识(例如较新的、专有的或特定领域的信息)时,则可能会导致出现错误信息或者误导性结论(例如图1所示)。

由此可见,在消除 LLM 与额外语境之间的知识鸿沟方面发挥重要作用的是让模型能够整合常识性知识。这不仅有助于提升其提供更加贴切的补充内容的能力,并且能够有效降低对异常情况做出误判的可能性。

解决方案

在传统方法中(段落保持不变),神经网络采用微调技术以适应特定领域或专门信息(这里将"通过"改为"采用")。这一技术尽管具有显著效果(这里将"虽然有效"改为"尽管有效"),但在计算资源消耗上存在较大挑战(这里将"计算密集"作为独立描述),并且对专业知识的需求较高(这里对"需要专业技术知识"进行同义表达)。此外,在应对不断变化的信息需求时也显示出一定的不足(这里对"而且...不够灵活"进行详细阐述)。

该年份的研究人员们在论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》中提出了更具灵活性的技术框架,并将其命名为检索增强生成(RAG)技术。
在该研究工作中,
他们整合了生成模型与专门设计的检索模块,
通过外部知识库获取更新便捷的信息资源。

简单地说,在RAG系统中实现对LLM的强大支持犹如采用开卷考试来促进人类知识获取能力的发展。在开卷考试中考生可以携带教材笔记本等作为参考文献用于检索相关资料以解答问题而开卷考试的核心理念则是侧重于考察学生的逻辑推理能力而非死记硬背特定知识点基于这一理念设计的考试形式强调通过开放性思维解决问题的能力这种方式不仅能够有效激发学生的创造力还能帮助他们更好地理解和应用所学知识

此外,在LSTM网络模型中采用统一门控机制后,在捕捉时间依赖性和处理长序列方面均表现出色,并且能够有效降低计算复杂度

  • 参数型知识:通过训练阶段获得,在神经网络权重中以非显式的形式存在。
  • 非参数型知识:以隐式的方式存在于外部存储系统中,例如基于向量的知识库。

(顺便提一句, 这一优秀的方法不是我自己想到的。据公开资料显示, 这种方法首次在Kaggle - LLM科学考试竞赛中被JJ提出

以下是基本的RAG工作流程示意图:

获取信息:通过外部资源库获取相关信息。 为了实现这一目标, 我们采用IID(独立同分布)模型, 在同一子空间内将用户的搜索意图映射至与向量数据库中的附加信息相匹配的空间。 从而能够实现高效的相似性搜索, 在结果集中提供前k条最相关的记录。

增强:将用户查询和检索到的附加上下文填入一个提示模板中。

生成:最后,将经过检索增强的提示输入到 LLM。

使用 LangChain 实现检索-增强生成

本节采用 OpenAI 的 LLM 技术与 Weaviate 向量数据库以及 OpenAI 的嵌入模型相结合,在 Python 平台开发了一个基于检索增强生成(RAG)的管道,并由 LangChain 负责其整体协调运作

先决条件

确保已安装所需的 Python 包:

langchain用于协调

OpenAI 用于嵌入模型和大型语言模型(LLM)

weaviate-client 用于向量数据库

复制代码
    #!pip install langchain openai weaviate-client
    
    
      
    
    代码解释

请在项目根目录中的 .env 文件中明确说明相关信息。为了访问 OpenAI 的API密钥,请访问OpenAI账户并按照指示创建新密钥。

复制代码
    OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"
    
    
      
    
    代码解释

然后,运行以下命令加载相关环境变量。

复制代码
    import dotenv
    dotenv.load_dotenv()
    
    
      
      
    
    代码解释

准备工作

在准备阶段应提前准备好一个矢量数据库作为外部知识库来存储各类补充资料该矢量数据库将遵循如下流程构建

收集和加载数据

文档分块

嵌入和存储块

第一步涉及收集与加载数据——在本示例中,请您参考使用拜登总统 2022 年的国情咨文作为上下文资料。原始文本文件可从LangChain官方GitHub存储库获取。为了实现数据加载,请考虑采用LangChain提供的多种内置文档载入工具中的任意一种方法进行操作。一个文档通常包含主要文本内容及其相关元数据信息。为了获取具体文本内容,请确保正确配置并运行相应的载入命令以提取所需信息。

复制代码
    import requests
    from langchain.document_loaders import TextLoader
    
    url = "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"
    res = requests.get(url)
    with open("state_of_the_union.txt", "w") as f:
    f.write(res.text)
    
    loader = TextLoader('./state_of_the_union.txt')
    documents = loader.load()
    
    
      
      
      
      
      
      
      
      
      
      
    
    代码解释

考虑到原始状态下生成的文档内容过于冗长,并超出输入限制的情况下需要将其切分为较小段落为此LangChain提供了多种内置文本分割工具其中一种就是字符分段器(CharacterTextSplitter)。该字符分段器每段长度设置为约500个字符并确保相邻段落之间的重叠部分为50个字符以保持整体内容的连贯性

复制代码
    from langchain.text_splitter import CharacterTextSplitter
    text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
    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
    )
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解释

步骤 1:检索

完成对矢量数据库的填充后即可将其定义为检索器组件通过分析用户查询与嵌入式块之间的语义相似性来获取附加上下文信息

复制代码
    retriever = vectorstore.as_retriever()
    
    
      
    
    代码解释

步骤 2:增强

接下来,在利用额外的上下文来加强提示效果方面,请确保准备好一个合适的提示模板。如上所示,在使用或参考该提示模板时,请根据实际情况进行定制设计。

复制代码
    from langchain.prompts import ChatPromptTemplate
    
    template = """You are an assistant for question-answering tasks. 
    Use the following pieces of retrieved context to answer the question. 
    If you don't know the answer, just say that you don't know. 
    Use three sentences maximum and keep the answer concise.
    Question: {question} 
    Context: {context} 
    Answer:
    """
    prompt = ChatPromptTemplate.from_template(template)
    
    print(prompt)
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解释

步骤 3:生成

最终,您可以搭建一条连接用于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 = "What did the president say about Justice Breyer"
    rag_chain.invoke(query)
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解释
复制代码
    "The president thanked Justice Breyer for his service and acknowledged his dedication to serving the country. 
    The president also mentioned that he nominated Judge Ketanji Brown Jackson as a successor to continue Justice Breyer's legacy of excellence."
    
    
      
      
    
    代码解释

下面是这个具体例子的 RAG 管道结果:

总结

本文综述了发表于2020年的论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》中提出的RAG概念。在阐述了这一创新方法背后的理论基础(包括其设计动机及相关解决方案)之后,我们开发了一个Python实现方案。通过构建一个基于OpenAI语言模型与Weaviate向量数据库的管道,并利用LangChain框架实现了各组件之间的高效协调与集成。

参考

Lewis et al. (2020) explored Retrieval-enhanced generation techniques specifically designed for knowledge-heavy NLP tasks within the journal Advances in Neural Information Processing Systems. Their research demonstrated the effectiveness of these methods in advancing the field of computational linguistics.

全部评论 (0)

还没有任何评论哟~