通过RAG架构LLM应用程序

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

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

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

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

1.安装条件

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

代码语言:shell

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() 函数。该文件将如下所示:

代码语言:shell

def main():print("Hello World!")if __name__ == "__main__": main()
2.导入PDF文件

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

代码语言:shell

from langchain_community.document_loaders import PyPDFLoaderpdf_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() 函数应该输出一个类似于这样的数组:

代码语言:shell

[Document(page_content='[...]', metadata={'source': pdf_path, page: 1}), Document(page_content='[...]', metadata={'source': pdf_path, page: 2}), ...]
3.切割文件

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

代码语言:shell

from langchain.text_splitter import CharacterTextSplitter

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

代码语言:shell

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 文件中,如下所示:

代码语言:shell

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

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

代码语言:shell

from dotenv import load_dotenv

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

代码语言:shell

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 类:

代码语言:shell

from langchain_openai import OpenAIEmbeddings

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

代码语言:shell

embeddings = OpenAIEmbeddings()
6.设置向量数据库

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

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

代码语言:shell

from langchain_community.vectorstores.faiss import FAISS

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

代码语言:shell

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”的提示。这个提示是专门为我们的案例设计的,允许我们从提供的上下文中向模型询问事物。在引擎盖下,提示如下所示:

代码语言:shell

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

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

代码语言:python

from langchain import hub

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

代码语言:python

retrieval_qa_chat_prompt = hub.pull("langchain-ai/retrieval-qa-chat")
8.设置大语言模型

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

让我们继续导入模型:

代码语言:shell

from langchain_openai import ChatOpenAI, OpenAIEmbeddings

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

代码语言:python

llm = ChatOpenAI()
9.从数据库检索上下文数据

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

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

代码语言:python

from langchain.chains.combine_documents import create_stuff_documents_chain

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

代码语言:python

combine_docs_chain = create_stuff_documents_chain(llm, retrieval_qa_chat_prompt)

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

代码语言:python

combine_docs_chain.invoke({"context": docs, "input": "What is REACT in machine learning meaning?"})
10.仅检索相关数据作为上下文

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

代码语言:shell

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”库中导入该链:

代码语言:python

from langchain.chains import create_retrieval_chain 

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

代码语言:python

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

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

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

代码语言:python

retrieval_chain = create_retrieval_chain(retriever, combine_docs_chain)

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

代码语言:python

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

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

  • input - 我们的查询;
  • context - 我们作为上下文传递给提示的文档(块)数组;
  • answer - 由大型语言模型 (LLM) 生成的查询的答案。
10.LLM app 全部代码

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

代码语言:shell

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 FAISSpdf_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个小节分别进行了详细介绍,希望对初学者有很好的指导作用。

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

如何系统的去学习大模型LLM ?

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的 AI大模型资料 包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

在这里插入图片描述

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

在这里插入图片描述

四、AI大模型商业化落地方案

img

阶段1:AI大模型时代的基础理解

  • 目标:了解AI大模型的基本概念、发展历程和核心原理。
  • 内容
    • L1.1 人工智能简述与大模型起源
    • L1.2 大模型与通用人工智能
    • L1.3 GPT模型的发展历程
    • L1.4 模型工程
      - L1.4.1 知识大模型
      - L1.4.2 生产大模型
      - L1.4.3 模型工程方法论
      - L1.4.4 模型工程实践
    • L1.5 GPT应用案例

阶段2:AI大模型API应用开发工程

  • 目标:掌握AI大模型API的使用和开发,以及相关的编程技能。
  • 内容
    • L2.1 API接口
      - L2.1.1 OpenAI API接口
      - L2.1.2 Python接口接入
      - L2.1.3 BOT工具类框架
      - L2.1.4 代码示例
    • L2.2 Prompt框架
      - L2.2.1 什么是Prompt
      - L2.2.2 Prompt框架应用现状
      - L2.2.3 基于GPTAS的Prompt框架
      - L2.2.4 Prompt框架与Thought
      - L2.2.5 Prompt框架与提示词
    • L2.3 流水线工程
      - L2.3.1 流水线工程的概念
      - L2.3.2 流水线工程的优点
      - L2.3.3 流水线工程的应用
    • L2.4 总结与展望

阶段3:AI大模型应用架构实践

  • 目标:深入理解AI大模型的应用架构,并能够进行私有化部署。
  • 内容
    • L3.1 Agent模型框架
      - L3.1.1 Agent模型框架的设计理念
      - L3.1.2 Agent模型框架的核心组件
      - L3.1.3 Agent模型框架的实现细节
    • L3.2 MetaGPT
      - L3.2.1 MetaGPT的基本概念
      - L3.2.2 MetaGPT的工作原理
      - L3.2.3 MetaGPT的应用场景
    • L3.3 ChatGLM
      - L3.3.1 ChatGLM的特点
      - L3.3.2 ChatGLM的开发环境
      - L3.3.3 ChatGLM的使用示例
    • L3.4 LLAMA
      - L3.4.1 LLAMA的特点
      - L3.4.2 LLAMA的开发环境
      - L3.4.3 LLAMA的使用示例
    • L3.5 其他大模型介绍

阶段4:AI大模型私有化部署

  • 目标:掌握多种AI大模型的私有化部署,包括多模态和特定领域模型。
  • 内容
    • L4.1 模型私有化部署概述
    • L4.2 模型私有化部署的关键技术
    • L4.3 模型私有化部署的实施步骤
    • L4.4 模型私有化部署的应用场景

学习计划:

  • 阶段1:1-2个月,建立AI大模型的基础知识体系。
  • 阶段2:2-3个月,专注于API应用开发能力的提升。
  • 阶段3:3-4个月,深入实践AI大模型的应用架构和私有化部署。
  • 阶段4:4-5个月,专注于高级模型的应用和部署。
这份完整版的大模型 LLM 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

😝有需要的小伙伴,可以Vx扫描下方二维码免费领取🆓

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自己手写一个单向链表【C风格】

//单链表 #include <iostream> #define MAX_SIZE 20 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0typedef int ElemType;//元素的类型 typedef int Status;//返回状态typedef struct Node {ElemType data;//链表中保存的数据struct Node* next;//指向下…

【CSP CCF记录】201909-1 小明种苹果

题目 过程 #include<bits/stdc.h> using namespace std; int N,M; long long tree[1010]; int main() {cin>>N>>M;long long result0,max0;//result剩余苹果&#xff0c;max最大疏果个数 int id0;//id最大疏果的果树编号 for(int i1;i<N;i){long long b0…

构建php环境

目录 php简介 官网php安装包 选择下载稳定版本 &#xff08;建议使用此版本&#xff0c;文章以此版本为例&#xff09; 安装php解析环境 准备工作 安装依赖 zlib-devel 和 libxml2-devel包。 安装扩展工具库 安装 libmcrypt 安装 mhash 安装mcrypt 安装php 选项含…

Gin框架学习笔记(六)——gin中的日志使用

gin内置日志组件的使用 前言 在之前我们要使用Gin框架定义路由的时候我们一般会使用Default方法来实现&#xff0c;我们来看一下他的实现&#xff1a; func Default(opts ...OptionFunc) *Engine {debugPrintWARNINGDefault()engine : New()engine.Use(Logger(), Recovery())…

uniapp微信小程序解决type=“nickname“获取昵称,v-model绑定值为空问题!

解决获取 type"nickname"值为空问题 文章目录 解决获取 type"nickname"值为空问题效果图Demo解决方式通过表单收集内容通过 uni.createSelectorQuery 效果图 开发工具效果图&#xff0c;真机上还会显示键盘输入框 Demo 如果通过 v-model 结合 blur 获取不…

【Linux】写时拷贝技术COW (copy-on-write)

文章目录 Linux写时拷贝技术(copy-on-write)进程的概念进程的定义进程和程序的区别PCB的内部构成 程序是如何被加载变成进程的&#xff1f;写时复制&#xff08;Copy-On-Write, COW&#xff09;写时复制机制的原理写时拷贝的场景 fork与COWvfork与fork Linux写时拷贝技术(copy-…

VUE3 学习笔记(十)查看vue版本

命令&#xff1a; npm list vue(空) (在项目的根目录下执行以下命令即可查看项目所使用的vue版本) npm list vue version(空) npm info vue (全局查看vue版本号&#xff0c;详细) npm list vue -g(全局查看vue版本号&#xff0c;简单) npm view vue version(查看项目依赖的vue…

开源博客项目Blog .NET Core源码学习(26:App.Hosting项目结构分析-14)

后台管理页面的系统管理下主要包括用户管理、角色管理、按钮管理和菜单管理&#xff0c;其中创建用户时要指定角色&#xff0c;创建角色时需指定菜单权限&#xff0c;按钮管理也是基于各菜单项进行设置&#xff0c;只有菜单管理相对独立&#xff0c;因此本文学习并分析App.Host…

蓝桥杯【第15届省赛】Python B组 32.60 分

F 题列表越界访问了……省一但没什么好名次 测评链接&#xff1a;https://www.dotcpp.com/oj/train/1120/ C 语言网真是 ** 测评&#xff0c;时间限制和考试的不一样&#xff0c;E 题给我整时间超限&#xff1f; A&#xff1a;穿越时空之门 100&#x1f3c6; 【问题描述】 随…

使用梦畅闹钟,结合自定义bat、vbs脚本等实现定时功能

梦畅闹钟-每隔一段时间运行一次程序 休息五分钟bat脚本&#xff08;播放音乐视频&#xff0c;并锁屏&#xff09; chcp 65001 echo 回车开始休息5分钟 pause explorer "https://www.bilibili.com/video/BV1RT411S7Tk/?p47" timeout /t 3 /nobreak rundll32.exe use…

什么是SSL证书?如何选择SSL证书?

在浏览网站的时候&#xff0c;你会不会有这样一些疑问。 为什么有的网站是http://开头&#xff0c;有的却是https://&#xff1f;它们有什么区别吗&#xff1f; 经常访问的网站&#xff0c;浏览器突然提示“安全证书过期”&#xff0c;提醒你不要浏览该网址&#xff1f; 这一切…

Debug-010-git stash的用法及使用场景

问题原因&#xff1a; 其实也不是最近&#xff0c;就是之前就碰到过这个问题&#xff0c;那就是我正在新分支开发新功能&#xff0c;开发程度还没有到可以commit的程度&#xff0c;我不想提交(因为有些功能没有完全实现&#xff0c;而且没有自测的话很容易有问题&#xff0c;提…

ICML 2024 时空数据(Spatial-Temporal)论文总结

2024ICML&#xff08;International Conference on Machine Learning&#xff0c;国际机器学习会议&#xff09;在2024年7月21日-27日在奥地利维也纳举行 &#xff08;好像ICLR24现在正在维也纳开&#xff09;。 本文总结了ICML 24有关时空数据(Spatial-temporal) 的相关论文…

Golang并发编程-协程goroutine任务取消(Context)

文章目录 前言一、单个任务的取消二、 所有任务取消三、Context的出现Context的定义Context使用 总结 前言 在实际的业务种&#xff0c;我们可能会有这么一种场景&#xff1a;需要我们主动的通知某一个goroutine结束。比如我们开启一个后台goroutine一直做事情&#xff0c;比如…

【小程序八股文】系列之篇章二 | 小程序的核心机制

【小程序八股文】系列之篇章二 | 小程序的核心机制 前言三、微信小程序原理与运行机制简述一下微信小程序的原理微信小程序的双线程的理解为什么不采用浏览器多线程模式&#xff1f;为什么是双线程&#xff1f;&#xff08;出发点&#xff1a;安全&#xff0c;快速&#xff0c;…

Express 的 req 和 res 对象

新建 learn-express文件夹&#xff0c;执行命令行 npm init -y npm install express 新建 index.js const express require(express); const app express();app.get(/, (req, res, next) > {res.json(return get) })app.post(/, (req, res, next) > {res.json(retur…

论文精读-SRFormer Permuted Self-Attention for Single Image Super-Resolution

论文精读-SRFormer: Permuted Self-Attention for Single Image Super-Resolution SRFormer:用于单图像超分辨率的排列自注意 Params&#xff1a;853K&#xff0c;MACs&#xff1a;236G 优点&#xff1a; 1、参考SwinIR的RSTB提出了新的网络块结构PAB&#xff08;排列自注意力…

sky walking日志采集以及注意事项

文章目录 1&#xff0c;sky walking日志采集功能概述2&#xff0c;采集log4j2日志3&#xff0c;采集logback日志4&#xff0c;效果展示5&#xff0c;注意事项 1&#xff0c;sky walking日志采集功能概述 在介绍Sky walking日志采集功能之前&#xff0c;最好在系统学习一遍日志…

【医学AI|顶刊精析|05-25】哈佛医学院·告别切片局限:3D病理如何革新癌症预后

小罗碎碎念 先打个预防针&#xff0c;我写这篇推文用了两个多小时&#xff0c;这就意味着要读懂这篇文章不太容易&#xff0c;我已经做好反复阅读的准备了。不过&#xff0c;风险之下&#xff0c;亦是机会&#xff0c;读懂的人少&#xff0c;这个赛道就越值得押宝。 在正式阅…

【C语言】8.C语言操作符详解(3)

文章目录 10.操作符的属性&#xff1a;优先级、结合性10.1 优先级10.2 结合性 11.表达式求值11.1 整型提升11.2 算术转换11.3 问题表达式解析11.3.1 表达式111.3.2 表达式211.3.3 表达式311.3.4 表达式411.3.5 表达式5: 11.4 总结 10.操作符的属性&#xff1a;优先级、结合性 …