【AIGC】基于检索增强技术(RAG)构建大语言模型(LLM)应用程序

本文涉及的产品
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
交互式建模 PAI-DSW,每月250计算时 3个月
模型训练 PAI-DLC,100CU*H 3个月
简介: 【5月更文挑战第7天】基于检索增强技术(RAG)构建大语言模型(LLM)应用程序实践

[toc]


在之前的博客文章中,我们已经描述了嵌入是如何工作的,以及RAG技术是什么。本节我们我们将使用 LangChain 库以及 RAG 和嵌入技术在 Python 中构建一个简单的 LLM 应用程序。

我们将使用 LangChain 库在 Python 中构建一个简单的 LLM 应用程序。LangChain是一个流行的库,它使构建这样的应用程序变得非常容易。

我们的 RAG 应用程序将使用私有数据扩展 LLM 的知识。在这种情况下,它将是一个包含一些文本的 PDF 文件。

也可以通过使用 OpenAI 代理并通过将特定文件上传到 OpenAI 的服务器来扩展其知识库来实现类似的目标。但是,这种方法需要将我们的机密数据存储在 OpenAI 的服务器上,这可能并不总是符合我们的隐私偏好。

1.安装条件

在一开始,我们必须安装应用程序将使用的所有必需模块。让我们在终端的项目目录中编写此命令

pip install langchain-community==0.0.11 pypdf==3.17.4 langchain==0.1.0 python-dotenv==1.0.0 langchain-openai==0.0.2.post1 faiss-cpu==1.7.4 tiktoken==0.5.2 langchainhub==0.1.14

让我们创建一个“data”目录并将 PDF 文件放入其中。 我们还必须在项目目录中创建一个 main.py 文件,我们将在其中存储应用程序的整个代码。

在 main.py 文件中,我们将创建用于存储逻辑的 main() 函数。该文件将如下所示:

def main():
  print("Hello World!")

if __name__ == "__main__": 
  main()

2.导入PDF文件

我们将使用LangChain提供的名为PyPDFLoader的文档加载器。

from langchain_community.document_loaders import PyPDFLoader

pdf_path = "./data/2210.03629.pdf"

def main():
  loader = PyPDFLoader(file_path=pdf_path)
  documents = loader.load()
  print(documents) 

if __name__ == "__main__": 
  main()

首先,我们应该创建一个 PyPDFLoader 对象的实例,我们将路径传递给文件。下一步是简单地调用此对象的 load 函数,并将加载的文件保存在 documents 变量中。它将是一个由 Document 对象组成的数组,其中每个对象都是我们文件的一页的表示形式。

print() 函数应该输出一个类似于这样的数组:

[Document(page_content='[...]', metadata={'source': pdf_path, page: 1}), Document(page_content='[...]', metadata={'source': pdf_path, page: 2}), ...]

3.切割文件

我们不想将整个文档作为上下文发送到 LLM。为什么?在关于RAG的文章中对此进行了更详细的描述。为了拆分文档,我们将使用 LangChain 提供的一个名为 CharacterTextSplitter 的类,我们可以从 langchain 库中导入它:

from langchain.text_splitter import CharacterTextSplitter

然后我们可以创建一个实例并调用 split_documents() 函数,将加载的文档作为参数传递。

def main():
  loader = PyPDFLoader(file_path=pdf_path) 
  documents = loader.load() 
  text_splitter = CharacterTextSplitter( chunk_size=1000, chunk_overlap=50, separator="\n" ) 
  docs = text_splitter.split_documents(documents)

让我们简要描述一下这里发生了什么。

首先,我们将创建一个 CharacterTextSplitter 对象,该对象采用多个参数:

  • chunk_size - 定义以令牌为单位的单个块的最大大小。
  • chunk_overlap - 定义块之间的重叠大小。这有助于通过确保块不会以扭曲其含义的方式拆分来保留拆分文本的含义。
  • separator - 定义将用于描述块的分隔符。

在 docs 变量中,我们将得到一个 Document 对象数组 - 与 PyPDFLoader 类的 load() 函数相同。

4.准备环境变量

下一步是将这些块转换为数字向量,并将它们存储在向量数据库中。这个过程叫做嵌入,也有一篇关于它的博文,所以我们现在不会详细介绍它。

对于嵌入过程,我们需要一个外部嵌入模型。为此,我们将使用 OpenAI 嵌入。为此,我们必须生成一个 OpenAI API 密钥。
但在此之前,我们必须创建一个 .env 文件,用于存储此密钥。

现在,我们需要在 platform.openai.com/docs/overview 页面上创建一个帐户。 之后,我们应该通过创建一个新的密钥在 platform.openai.com/api-keys 页面上生成一个 API 密钥。

复制密钥并将其粘贴到 .env 文件中,如下所示:

OPENAI_API_KEY=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

让我们通过导入 load_dotenv 函数将环境变量加载到我们的项目中:

from dotenv import load_dotenv

并在 main 函数的开头调用它:

def main(): 
    load_dotenv()
    loader = PyPDFLoader(file_path=pdf_path) 
    documents = loader.load() 
    text_splitter = CharacterTextSplitter( chunk_size=1000, chunk_overlap=50, separator="\n" ) 
    docs = text_splitter.split_documents(documents)

5.直线嵌入功能

首先,我们必须导入 OpenAIEmbeddings 类:

from langchain_openai import OpenAIEmbeddings

我们应该创建这个类的实例。让我们将其分配给 'embeddings' 变量,如下所示:

embeddings = OpenAIEmbeddings()

6.设置向量数据库

我们已经加载并准备了我们的文件,我们还为嵌入模型创建了一个对象实例。我们现在已准备好将块转换为数字向量并将它们保存在向量数据库中。我们将使用 FAISS 矢量数据库将所有数据保存在本地。Facebook AI 相似度搜索 (Faiss) 是 Facebook AI 设计的一款工具,用于对密集向量进行有效的相似性搜索和聚类。

首先,我们需要导入 FAISS 实例:

from langchain_community.vectorstores.faiss import FAISS

并实现转换和保存嵌入的过程:

def main(): 
    load_dotenv() 
    loader = PyPDFLoader(file_path=pdf_path) 
    documents = loader.load() 
    text_splitter = CharacterTextSplitter( chunk_size=1000, chunk_overlap=50, separator="\n" ) 
    docs = text_splitter.split_documents(documents) 
    embeddings = OpenAIEmbeddings() 
    vectorstore = FAISS.from_documents(docs, embeddings)    
    vectorstore.save_local("vector_db")

我们在代码中添加了两行。第一行采用我们的拆分块 (docs) 和嵌入模型将块从文本转换为数字向量。之后,我们将转换后的数据保存在本地的“vector_db”目录中。

7.创建提示

为了准备提示,我们将使用“langchain”中心。我们将从那里提取一个名为“langchain-ai/retrieval-qa-chat”的提示。这个提示是专门为我们的案例设计的,允许我们从提供的上下文中向模型询问事物。在引擎盖下,提示如下所示:

Answer any use questions based solely on the context below:
<context> 
{context}
</context>

让我们从“langchain”库导入一个"hub":

from langchain import hub

然后,只需使用“pull()”函数从中心检索此提示并将其存储在变量中:

retrieval_qa_chat_prompt = hub.pull("langchain-ai/retrieval-qa-chat")

8.设置大语言模型

接下来我们需要的是一个大型语言模型——在我们的例子中,它将是 OpenAI 模型之一。同样,我们需要一个 OpenAI 密钥,但我们已经将它与嵌入一起设置,因此我们不需要再做一次。

让我们继续导入模型:

from langchain_openai import ChatOpenAI, OpenAIEmbeddings

并将其分配给我们 main 函数中的一个变量:

llm = ChatOpenAI()

9.从数据库检索上下文数据

我们已经完成了向量数据库、嵌入和 LLM(大型语言模型)的准备工作。现在,我们需要使用链条连接所有东西。为此,我们需要“langchain”提供的两种类型的链。

第一个是 'create_stuff_documents_chain',我们需要从 'langchain' 库中导入它:

from langchain.chains.combine_documents import create_stuff_documents_chain

接下来,传递我们的大型语言模型 (LLM) 并提示它。

combine_docs_chain = create_stuff_documents_chain(llm, retrieval_qa_chat_prompt)

此函数返回一个 LCEL Runnable 对象,该对象需要上下文参数。运行它将如下所示:

combine_docs_chain.invoke({
   "context": docs, "input": "What is REACT in machine learning meaning?"})

10.仅检索相关数据作为上下文

它会起作用,但在这种情况下,我们将传递所有块 - 整个文档 - 作为上下文。在我们的例子中,文件有 33 页,这个上下文太大,我们可能会遇到这样的错误:

openai.BadRequestError: Error code: 400 - {'error': {'message': "This model's maximum context length is 4097 tokens. However, your messages resulted in 33846 tokens. Please reduce the length of the messages.", 'type': 'invalid_request_error', 'param': 'messages', 'code': 'context_length_exceeded'}}

为了解决这个问题,我们只需要将与查询相关的信息作为上下文传递。我们将通过将此链与另一条链相结合来实现这一点,该链将仅从数据库中检索对我们重要的块,并自动将它们作为上下文添加到提示中。

让我们从“langchain”库中导入该链:

from langchain.chains import create_retrieval_chain

首先,我们需要将数据库准备为检索器,这将启用对与查询相关的块的语义搜索。

retriever = FAISS.load_local("vector_db", embeddings).as_retriever()

因此,我们加载我们的目录,其中存储转换为向量的块并将其传递给嵌入函数。最后,我们将其作为检索器返回。

现在,我们可以组合我们的链:

retrieval_chain = create_retrieval_chain(retriever, combine_docs_chain)

在后台,它将从数据库中检索相关块,并将它们作为上下文添加到我们的提示中。我们现在要做的就是使用我们的查询作为输入参数调用此链:

response = retrieval_chain.invoke({
   "input": "What is REACT in machine learning meaning?"})

作为响应,我们将收到一个包含三个变量的对象:

  • input - 我们的查询;

  • context - 我们作为上下文传递给提示的文档(块)数组;

  • answer - 由大型语言模型 (LLM) 生成的查询的答案。

10.LLM app 全部代码

我们用 .pdf 文件中的数据扩展了 LLM 模型的知识库。该模型现在能够根据我们在提示中提供的上下文来回答我们的问题。

from dotenv import load_dotenv
from langchain import hub
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores.faiss import FAISS

pdf_path = "./data/2210.03629.pdf"


def main():
    load_dotenv()

    loader = PyPDFLoader(file_path=pdf_path)
    documents = loader.load()

    text_splitter = CharacterTextSplitter(
        chunk_size=1000, chunk_overlap=50, separator="\n"
    )
    docs = text_splitter.split_documents(documents)

    embeddings = OpenAIEmbeddings()

    vectorstore = FAISS.from_documents(docs, embeddings)
    vectorstore.save_local("vector_db")

    retrieval_qa_chat_prompt = hub.pull("langchain-ai/retrieval-qa-chat")

    llm = ChatOpenAI()

    combine_docs_chain = create_stuff_documents_chain(llm, retrieval_qa_chat_prompt)

    retriever = FAISS.load_local("vector_db", embeddings).as_retriever()
    retrieval_chain = create_retrieval_chain(retriever, combine_docs_chain)

    response = retrieval_chain.invoke(
        {"input": "What is REACT in machine learning meaning?"}
    )

    print(response["answer"])


if __name__ == "__main__":
    main()

小结

遵守前面博客中的约定,输出一节基于RAG进行大语言模型构建的内容,我们共划分了10个小节分别进行了详细介绍,希望对初学者有很好的指导作用。

小编是一名热爱人工智能的专栏作者,致力于分享人工智能领域的最新知识、技术和趋势。这里,你将能够了解到人工智能的最新应用和创新,探讨人工智能对未来社会的影响,以及探索人工智能背后的科学原理和技术实现。欢迎大家点赞,评论,收藏,让我们一起探索人工智能的奥秘,共同见证科技的进步!

相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
目录
相关文章
|
3月前
|
人工智能 自然语言处理 数据库
基于RAG和LLM的水利知识问答系统研究
随着全球水资源紧张加剧,我国面临严峻的水资源管理挑战。《十四五规划》提出构建智慧水利体系,通过科技手段提升水情测报和智能调度能力。基于大语言模型(LLM)的水利智能问答系统,利用自然语言处理技术,提供高效、准确的水利信息查询和决策支持,助力水资源管理智能化。该系统通过RAG技术和Agent功能,实现了对水利知识的深度理解和精准回答,适用于水利知识科普、水务治理建议及灾害应急决策等多个场景,推动了水利行业的信息化和智能化发展。
|
3天前
|
人工智能 数据可视化 开发者
FlowiseAI:34K Star!集成多种模型和100+组件的 LLM 应用低代码开发平台,拖拽组件轻松构建程序
FlowiseAI 是一款开源的低代码工具,通过拖拽可视化组件,用户可以快速构建自定义的 LLM 应用程序,支持多模型集成和记忆功能。
41 14
FlowiseAI:34K Star!集成多种模型和100+组件的 LLM 应用低代码开发平台,拖拽组件轻松构建程序
|
2天前
|
人工智能 自然语言处理 搜索推荐
师资培训|AIGC教学评估体系构建与教学策略优化-某教育科技集团
近日,TsingtaoAI为某教育科技集团交付AIGC赋能教师教学创新课程,本课程围绕国内外最新AIGC技术的发展现状与具体应用场景,深入探讨如何借助智能分析、多模态交互和自动化数据处理,为教学过程“插上”数字化翅膀。课程不仅聚焦于工具与平台的实操演练,还呈现了丰富的本土高校成功案例与落地方法,让参加者充分掌握从课堂管理、作业布置、考试测评到学生个性化指导的全流程智能化改进思路。
22 12
|
1月前
|
开发框架 人工智能 安全
Promptic:轻量级 LLM 应用开发框架,提供完善的底层功能,使开发者更专注于构建上层功能
Promptic 是一个轻量级的 LLM 应用开发框架,支持通过一行代码切换不同的 LLM 服务提供商。它提供了类型安全的输出、流式支持、内置对话记忆、错误处理和重试等功能,帮助开发者专注于构建功能,而不是底层的复杂性。
78 6
Promptic:轻量级 LLM 应用开发框架,提供完善的底层功能,使开发者更专注于构建上层功能
|
1月前
|
机器学习/深度学习 存储 缓存
ORCA:基于持续批处理的LLM推理性能优化技术详解
大语言模型(LLMs)的批处理优化面临诸多挑战,尤其是由于推理过程的迭代性导致的资源利用不均问题。ORCA系统通过引入迭代级调度和选择性批处理技术,有效解决了这些问题,大幅提高了GPU资源利用率和系统吞吐量,相比FasterTransformer实现了最高37倍的性能提升。
165 26
|
1月前
|
弹性计算 自然语言处理 数据库
通过阿里云Milvus和LangChain快速构建LLM问答系统
本文介绍如何通过整合阿里云Milvus、阿里云DashScope Embedding模型与阿里云PAI(EAS)模型服务,构建一个由LLM(大型语言模型)驱动的问题解答应用,并着重演示了如何搭建基于这些技术的RAG对话系统。
|
2月前
|
自然语言处理 算法
RAG真能提升LLM推理能力?人大最新研究:数据有噪声,RAG性能不升反降
随着大型语言模型(LLM)在自然语言处理领域的广泛应用,检索增强生成(RAG)技术因能引入新知识和减少幻觉而受到关注。然而,RAG对LLM推理能力的实际提升效果仍存争议。中国人民大学的一项研究表明,RAG虽能辅助LLM推理,但在处理含噪信息和深度推理时面临挑战。为此,研究团队提出了DPrompt tuning方法,旨在解决噪声问题并提升RAG性能。
62 12
|
1月前
|
自然语言处理 资源调度 并行计算
从本地部署到企业级服务:十种主流LLM推理框架的技术介绍与对比
本文深入探讨了十种主流的大语言模型(LLM)服务引擎和工具,涵盖从轻量级本地部署到高性能企业级解决方案,详细分析了它们的技术特点、优势及局限性,旨在为研究人员和工程团队提供适合不同应用场景的技术方案。内容涉及WebLLM、LM Studio、Ollama、vLLM、LightLLM、OpenLLM、HuggingFace TGI、GPT4ALL、llama.cpp及Triton Inference Server与TensorRT-LLM等。
195 7
|
2月前
|
JSON 数据可视化 NoSQL
基于LLM Graph Transformer的知识图谱构建技术研究:LangChain框架下转换机制实践
本文介绍了LangChain的LLM Graph Transformer框架,探讨了文本到图谱转换的双模式实现机制。基于工具的模式利用结构化输出和函数调用,简化了提示工程并支持属性提取;基于提示的模式则为不支持工具调用的模型提供了备选方案。通过精确定义图谱模式(包括节点类型、关系类型及其约束),显著提升了提取结果的一致性和可靠性。LLM Graph Transformer为非结构化数据的结构化表示提供了可靠的技术方案,支持RAG应用和复杂查询处理。
188 2
基于LLM Graph Transformer的知识图谱构建技术研究:LangChain框架下转换机制实践
|
3天前
|
人工智能 搜索推荐 数据库
实时云渲染技术赋能AIGC,开启3D内容生态黄金时代
在AIGC技术革命的推动下,3D内容生态将迎来巨大变革。实时云渲染与Cloud XR技术将在三维数字资产的上云、交互及传播中扮演关键角色,大幅提升生产效率并降低门槛。作为云基础设施厂商,抓住这一机遇将加速元宇宙的构建与繁荣。AIGC不仅改变3D内容的生成方式,从手工转向自动生成,还将催生更多3D创作工具和基础设施,进一步丰富虚拟世界的构建。未来,通过文本输入即可生成引人注目的3D环境,多模态模型的应用将极大拓展创作的可能性。

热门文章

最新文章