万字详解,和你用RAG+LangChain实现chatpdf

像chatgpt这样的大语言模型(LLM)可以回答很多类型的问题,但是,如果只依赖LLM,它只知道训练过的内容,不知道你的私有数据:如公司内部没有联网的企业文档,或者在LLM训练完成后新产生的数据。(即使是最新的GPT-4 Turbo,训练的数据集也只更新到2023年4月)所以,如果我们开发一个聊天机器人,可以与自己的文档对话,让LLM基于文档的信息回答我们的问题,是一件很有意义的事情。

本次我们会基于RAG的原理,通过LangChain来实现与pdf文档对话。

本次用到的文档放在这里的docs目录:https://github.com/fireshort/langchain-chat-with-your-data 我们这次会以吴恩达教授CS229(斯坦福的机器学习课程)的pdf为例子。

什么是RAG?

RAG是Retrieval-augmented generation(检索增强生成)的简称,它结合了检索和生成的能力,为文本序列生成任务引入额外的外部知识(通常是私有的或者是实时的数据),就是用外部信息来增强LLM的知识。RAG 将传统的语言生成模型与大规模的外部知识库相结合,使模型在生成响应或文本时可以动态地从这些知识库中检索相关信息。这种结合方法旨在增强模型的生成能力,使其能够产生更为丰富、准确和有根据的内容,特别适合需要具体细节或外部事实支持的场合。

RAG一般分为下面几步:

检索:对于给定的输入(问题),模型首先使用检索系统从大型文档集合中查找相关的文档或段落。这个检索系统通常基于密集向量搜索。

上下文编码:找到相关的文档或段落后,模型将它们与原始输入(问题)一起放到Prompt里。

生成:使用编码的上下文信息,模型生成输出(答案)。这通常通过大模型完成。

在这里插入图片描述

RAG原理

使用LangChain实现

RAG看起来还是比较抽象,我们接下来会用LangChain实现,可以细分为下面5步:

在这里插入图片描述

  1. Document Loading:文档加载器把 Documents 加载为以 LangChain 能够读取的形式。
  2. Splitting:文本分割器把 Documents 切分为指定大小的、语义上有意义的块,一般称为“文档块”或者“文档片”。
  3. Storage:将上一步中分割好的“文档块”以“嵌入”(Embedding)的形式存储到向量数据库(Vector DB)中,形成一个个的“嵌入片”。
  4. Retrieval:应用程序从存储中检索分割后的文档(例如通过比较余弦相似度,找到与输入问题类似的嵌入片)。
  5. Output:把问题和相似的文档块传递给语言模型(LLM),使用包含问题、检索到的文档块的提示生成答案。

注意,最新版的openai库与当前的LangChain不兼容,要安装0.28.1版的openai库。

!pip install openai==0.28.1

要先用.env文件来初始化环境变量。

关于如何用.env文件初始化环境变量和LangChain的入门教程,推荐阅读专栏《基于LangChain的LLM应用开发》:https://juejin.cn/column/7290751135904038953

from langchain.document_loaders import PyPDFLoader
from langchain.memory import ConversationBufferMemory
from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chat_models import AzureChatOpenAI
from langchain.chains import ConversationalRetrievalChain# 用.env文件初始化环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())  # read local .env file

文档加载

为了创建一个与pdf文档对话的应用,首先要将pdf文档加载为LangChain可以使用的格式。LangChain提供了文档加载器来完成这件事。LangChain有超过80种不同类型的文档加载器。

文档加载器把各种不同来源的数据格式转换成标准化的格式:Document类,包括page_content(文档内容)和关联的metadata(元数据,如果是pdf的话会包括来源和页码{‘source’: ‘docs/cs229_lectures/MachineLearning-Lecture01.pdf’, ‘page’: 0});如果是其他的文档类型,如Notion则没有页码)

需要先安装pypdf库:! pip install pypdf

# 加载文档
pdffiles = ["docs/cs229_lectures/MachineLearning-Lecture01.pdf","docs/cs229_lectures/MachineLearning-Lecture01.pdf",  # 故意重复以模拟杂乱数据"docs/cs229_lectures/MachineLearning-Lecture02.pdf","docs/cs229_lectures/MachineLearning-Lecture03.pdf"
]
docs = []
for file_path in pdffiles:loader=PyPDFLoader(file_path)docs.extend(loader.load())print(f"The number of docs:{len(docs)}")
# print(docs[0])

这里故意重复加载第一章的pdf,目的是为了演示如何处理重复数据。在实际的工程中,即使经过数据清洗,很多时候也难以避免重复数据。

文档分割

文档已经加载了,但是这些文档仍然相当大,我们需要将加载的文本分割成更小的块,以便进行嵌入和向量存储。这一步很重要,因为我们对文档检索,只需要检索最相关的内容,没必要加载整个巨大的文档,一般只需要得到与主题相关的段落或句子就够了。

这一步看似简单,

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

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

相关文章

141.【Git版本控制-本地仓库-远程仓库-IDEA开发工具全解版】

Git-深入挖掘 (一)、Git分布式版本控制工具1.目标2.概述(1).开发中的实际常见(2).版本控制器的方式(3).SVN (集中版本控制器)(4).Git (分布版本控制器)(5).Git工作流程图 (二)、Git安装与常用命令1.Git环境配置(1).安装Git的操作(2).Git的配置操作(3).为常用的指令配置别名 (可…

想成为网络安全工程师该如何学习?

一、网络安全应该怎么学? 1.计算机基础需要过关 这一步跟网安关系暂时不大,是进入it行业每个人都必须掌握的基础能力。 计算机网络计算机操作系统算法与数据架构数据库 Tips:不用非要钻研至非常精通,可以与学习其他课程同步进行。 2.渗透技…

.mat格式文件是什么?及将png,jpg,bmp,gif,tiff,psd等格式图片转为.mat格式(附代码)

很多深度学习网络的输入要求为.mat格式,当然也可以直接修改输入数据的代码,比如修改为使用OpenCV读取图片等,但有些网络修改起来比较麻烦,且.mat数据有很多优势,所以部分网络最好还是用默认的.mat格式数据 目录 一、.…

Gossip协议理解

概述 Gossip协议,又称epidemic协议,基于流行病传播方式的节点或进程之间信息交换的协议,在分布式系统中被广泛使用。 在1987年8月由施乐-帕洛阿尔托研究中心发表ACM上的论文《Epidemic Algorithms for Replicated Database Maintenance》中…

OpenStack云计算平台

目录 一、OpenStack 1、简介 2、硬件需求 3、网络 二、环境搭建 1、安全 2、主机网络 3、网络时间协议(NTP) 4、OpenStack包 5、SQL数据库 6、消息队列 7、Memcached 一、OpenStack 1、简介 官网:https://docs.openstack.org/2023.2/ OpenStack系统由…

RPA机器人如何解决非银企直联网银账户的数据自动采集?

数字时代来临,随着全球信息化水平的不断提升,企业们纷纷向自动化办公、数字化转型靠拢。财务部门作为一个企业的重要部门,承担着管理和监控公司所有项目的重要职责,因而一直被视为企业数字化转型的重要突破口。 由于企业经营理念和…

第二十章多线程

线程简介 java语言提供了并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发运行。 一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进程…

C语言错误处理之“非局部跳转<setjmp.h>头文件”

目录 前言 setjmp宏 longjmp函数 使用方法: 实例:测试setjmp与longjmp的使用 前言 通常情况下,函数会返回到它被调用的位置,我们无法使用goto语句改变它的返回的方向,因为goto语句只能跳转到同一函数内的某个标号…

python与机器学习1,机器学习的一些基础知识概述(完善ing)

目录 1 AI ,ML,DL,NN 等等概念分类 1.1 人工智能、机器学习、深度学习、神经网络之间的关系: 1.2 人工智能的发展 2 ML机器学习的分类:SL, USL,RL 2.1 机器学习的分类 2.2 具体的应用举例 2.3 数据分类 3 关于阈值θ和偏移量b的由来 4 不同的激…

中小型工厂如何进行数字化转型

随着科技的快速发展和市场竞争的日益激烈,中小型工厂面临着诸多挑战。为了提高生产效率、降低成本、优化资源配置,数字化转型已成为中小型工厂发展的必经之路。中小型工厂如何进行数字化转型呢? 一、明确数字化转型目标 在进行数字化转型之前…

【Linux下基本指令——(1)】

Linux下基本指令——(1) 一. ls 指令1.1.语法:1.2.功能:1.3.常用选项:1.4.举例:1.5.Xshell7展示 二. pwd 命令2.1.语法: 2.2.功能:2.3.常用选项:2.4.Xshell7展示 三. cd 指令3.1.语法…

0004Java程序设计-ssm基于微信小程序的校园第二课堂

文章目录 摘 要目录系统设计开发环境 编程技术交流、源码分享、模板分享、网课分享 企鹅🐧裙:776871563 摘 要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。…

3D模型纹理集合并【Python|C#】

使用 Substance Painter 时,将模型的各个部分分成不同的纹理集非常有用。 这可以帮助遮罩,或者只是保持层栈干净。 不幸的是,Painter 无法将多个纹理集中的所有贴图导出为单个图集,即使在创建单独对象的 UV 时考虑到了这一点。 显…

SpringCloud实用-OpenFeign整合okHttp

文章目录 前言正文一、OkHttpFeignConfiguration 的启用1.1 分析配置类1.2 得出结论,需要增加配置1.3 调试 二、OkHttpFeignLoadBalancerConfiguration 的启用2.1 分析配置类2.2 得出结论2.3 测试 附录附1:本系列文章链接附2:OkHttpClient 增…

Spring Security 6.x 系列(6)—— 显式设置和修改登录态信息

一、前言 此篇是对上篇 Spring Security 6.x 系列(5)—— Servlet 认证体系结构介绍 中4.9章节显式调用SecurityContextRepository#saveContext进行详解分析。 二、设置和修改登录态 2.1 登录态存储形式 使用Spring Security框架,认证成功…

六、Lua运算符

文章目录 一、Lua 运算符(一)算术运算符(二)关系运算符(三)逻辑运算符(四)其他运算符 二、运算符优先级 一、Lua 运算符 运算符是一个特殊的符号,用于告诉解释器执行特定…

MSB3541 Files 的值“<<<<<<< HEAD”无效。路径中具有非法字符。

MSB3541 Files 的值“<<<<<<< HEAD”无效。路径中具有非法字符。 一般来说出现这个问题是因为使用git版本控制工具合并代码出现了问题&#xff0c;想要解决也很简单。 如图点击错误后定位到文件&#xff0c;发现也没有什么问题。 根据错误后边的提示&a…

P9242 [蓝桥杯 2023 省 B] 接龙数列(dp+最长接龙序列+分类)

1. 计算0~9为结尾的最长子串长度 2. 对于每个数字&#xff0c;比较其开头可连接子串长度1 与 原来以其末位为末尾的子串长度 3. 更新以其末位为末尾的子串长度 #include<iostream> #include<string.h>using namespace std;// 相当于记录…

如何运行C/C++程序

一、在线运行C/C 码曰 - 让代码在云端多飞一会&#xff1a;这是一个支持C/C&#xff0c;Java&#xff0c;Python等多种语言的在线编程&#xff0c;编译运行&#xff0c;粘贴分享的平台。你可以在这里输入你的代码&#xff0c;点击运行按钮&#xff0c;就可以看到输出结果。你也…

leetcode 283. 移动零

代码&#xff1a; class Solution {public void swap(int[] nums,int m,int n){int tmpnums[m];nums[m]nums[n];nums[n]tmp;}public void moveZeroes(int[] nums) {int cur0;int dest-1;int nnums.length;for(;cur<n;cur){if(nums[cur]!0){dest;swap(nums,cur,dest);}}} } …