通过 Ollama、Langchain 实现 RAG

RAG 是什么

RAG 在 Langchain 上的定义是,作为大语言模型最常用的场景就是问答系统,可以针对特别来源数据做问题回答,就是私有数据,这就是 RAG,英文全称是Retrieval Augmented Generation。就是对现有模型数据的增广,大语言模型都是在公众数据上训练,而且只是拿到了某一个时间点之前的数据。我查了一下 GPT,他最新的数据是 2023年 12 月,数据还是很新的。但是对于一些私有数据,模型肯定是没有的,对数据的增广就很有必要。

RAG 架构

RAG主要包括两个主要部分,首先是索引,从源头获取数据并进行索引的流程,例如从 PDF 获取数据,这通常在离线进行。第二步是搜索和生成,在运行时接收用户查询语句,从索引中检索相关数据,然后传递给模型。其实这个很像 ES 的全文检索,只是 ES 没有那么高级,ES 用的是分词,通过匹配进行查找。而 RAG 这里的分词用的是向量数据库,查找方式是相似度。

索引
  1. 首先导入文件,通过文件 Loader 可以导入 PDF、Word 等。
  2. 切分,将大文档进行切分,切分文档对索引和模型都有好处,搜索大文档对性能是很大的挑战,对于模型而言,模型的上下文是有限的,短小的上下文肯定更好,虽然现在模型的上下文都已经很大了。
  3. Embedding, 将切分的文档进行 embedding,向量化。
  4. 存储,要将索引进行保存,以便后续进行搜索。

在这里插入图片描述

搜索并生成

最后,根据用户输入的查询语句向量化后,在向量数据库中进行查询匹配,并将数据库的返回的结果和用户的查询语句一起发送给模型。
在这里插入图片描述

下面我们通过一个例子实现 chatpdf,用 langchain 加 ollama 进行实现RAG,运行在 Mac 上,性能可以接受。

安转依赖
conda create --name rag python=3.10
conda activate rag
pip install langchain
pip install streamlit
pip install chromadb
pip install pypdf
运行 chatpdf

模型用的 qwen:7b,需要把 ollama 运行起来。

from langchain.chains import RetrievalQA
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain.callbacks.manager import CallbackManager
from langchain_community.llms import Ollama
from langchain_community.embeddings.ollama import OllamaEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader
from langchain.prompts import PromptTemplate
from langchain.memory import ConversationBufferMemory
import streamlit as st
import os
import timeif not os.path.exists('files'):os.mkdir('files')if not os.path.exists('jj'):os.mkdir('jj')if 'template' not in st.session_state:st.session_state.template = """You are a knowledgeable chatbot, here to help with questions of the user. Your tone should be professional and informative.Context: {context}History: {history}User: {question}Chatbot:"""
if 'prompt' not in st.session_state:st.session_state.prompt = PromptTemplate(input_variables=["history", "context", "question"],template=st.session_state.template,)
if 'memory' not in st.session_state:st.session_state.memory = ConversationBufferMemory(memory_key="history",return_messages=True,input_key="question")
if 'vectorstore' not in st.session_state:st.session_state.vectorstore = Chroma(persist_directory='jj',embedding_function=OllamaEmbeddings(base_url='http://localhost:11434',model="qwen:7b"))
if 'llm' not in st.session_state:st.session_state.llm = Ollama(base_url="http://localhost:11434",model="qwen:7b",verbose=True,callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),)# Initialize session state
if 'chat_history' not in st.session_state:st.session_state.chat_history = []st.title("PDF Chatbot")# Upload a PDF file
uploaded_file = st.file_uploader("Upload your PDF", type='pdf')for message in st.session_state.chat_history:with st.chat_message(message["role"]):st.markdown(message["message"])if uploaded_file is not None:if not os.path.isfile("files/"+uploaded_file.name+".pdf"):with st.status("Analyzing your document..."):bytes_data = uploaded_file.read()f = open("files/"+uploaded_file.name+".pdf", "wb")f.write(bytes_data)f.close()loader = PyPDFLoader("files/"+uploaded_file.name+".pdf")data = loader.load()# Initialize text splittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1500,chunk_overlap=200,length_function=len)all_splits = text_splitter.split_documents(data)# Create and persist the vector storest.session_state.vectorstore = Chroma.from_documents(documents=all_splits,embedding=OllamaEmbeddings(model="qwen:7b"))st.session_state.vectorstore.persist()st.session_state.retriever = st.session_state.vectorstore.as_retriever()# Initialize the QA chainif 'qa_chain' not in st.session_state:st.session_state.qa_chain = RetrievalQA.from_chain_type(llm=st.session_state.llm,chain_type='stuff',retriever=st.session_state.retriever,verbose=True,chain_type_kwargs={"verbose": True,"prompt": st.session_state.prompt,"memory": st.session_state.memory,})# Chat inputif user_input := st.chat_input("You:", key="user_input"):user_message = {"role": "user", "message": user_input}st.session_state.chat_history.append(user_message)with st.chat_message("user"):st.markdown(user_input)with st.chat_message("assistant"):with st.spinner("Assistant is typing..."):response = st.session_state.qa_chain(user_input)message_placeholder = st.empty()full_response = ""for chunk in response['result'].split():full_response += chunk + " "time.sleep(0.05)# Add a blinking cursor to simulate typingmessage_placeholder.markdown(full_response + "▌")message_placeholder.markdown(full_response)chatbot_message = {"role": "assistant", "message": response['result']}st.session_state.chat_history.append(chatbot_message)else:st.write("Please upload a PDF file.")

启动chatpdf

streamlit run app.py

上传 PDF,输入问题,就可以和模型对话PDF 中的内容了。
在这里插入图片描述

RAG 是数据增广,也可以说是数据过滤,按照今天大模型的发展,上下文的长度已经卷到200 万个汉字的无损上下文,那么 RAG 会不会以后就不需要了,每次对话都把文档带上,让我们拭目以待。

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

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

相关文章

如何使用cuda进行图像矫正

普通矫正 相机矫正我们经常会用到,如果没有gpu加速,实际上矫正会很吃力,我们先用普通的矫正 cv::Mat undistort(cv::Mat img, cv::Mat K, cv::Mat D, int w, int h, float scale 0.6){cv::Mat Knew K.clone();//Knew K.copy()if (scale !…

解决向MySQL中导入文件中的 数据时出现的问题~

SQL语句如下所示: load data infile C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/data1.txt into table user fields terminated by , lines terminated by "\n" (name,sex,age,address,email,id,phone);报错1: The MySQL server is run…

Spring Boot 实现定时任务

前言 在实际开发中,我们经常需要处理一些周期性或定时的任务,比如每天凌晨进行数据统计、报表生成,或者每隔一段时间清理缓存等。Spring Boot 集成了 Quartz 和 Spring 自带的 TaskScheduler 等多种定时任务框架,使得实现定时任务变得非常方便。本文将通过一个详细的示例,…

使用scikit-learn中的SVC类实现垃圾邮件分类

scikit-learn中的SVC类不支持直接动态调整学习率。SVC类使用的核函数(例如,线性核、RBF核等)本身没有学习率参数。 但是,可以通过以下两种间接方式在训练过程中实现类似的效果: 使用GridSearchCV或RandomizedSearchCV…

Docker - 网络

目录 1. docker 网络命令 2.docker 的网络模式 1. docker 网络命令 # 查看 docker 的网络有哪些 docker network ls# 查看网络的详细信息 docker inspect $networkname# 创建 docker 网络 docker network create --driver $type $network_name# 删除 docker 网络 docker net…

强化学习(二)马尔科夫决策过程 MDP

文章目录 1. 什么是马尔科夫过程2. 强化学习与MDP的关系3. 价值函数的贝尔曼方程3.1 状态价值函数的贝尔曼方程3.2 动作价值函数的贝尔曼方程3.3 价值函数递推关系的转换 4. 最优价值函数5. MDP计算最优值函数实例 1. 什么是马尔科夫过程 马尔科夫过程(Markov Deci…

leetcode热题HOT 74. 搜索二维矩阵

一、问题描述: 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则&…

【网络编程】UDP实现回显服务器

一.网络编程的基本术语. 客户端 客户端是为用户提供本地服务的程序,通常位于用户设备上。也称为用户端,是相对于服务器而言的。它主要指安装在用户设备上的程序,这些程序能够与服务器进行通信,从而获取服务或者执行特定功能。在…

Spark安装教程

Spark安装教程 文章目录 Spark安装教程1. 检查jdk版本2. 获取Spark版本安装资源3.环境变量4.配置文件5. 重启Hadoop集群(使配置生效)6. 启动Spark集群6.1 查看Spark服务6.2 访问Spark WEB UI 7. 启动 Spark-Shell 测试 Scala 交互式环境8. 测试Spark On Yarn9.关闭Spark集群 1.…

OpenHarmony实战开发-Grid和List内拖拽交换子组件位置。

介绍 本示例分别通过onItemDrop()和onDrop()回调,实现子组件在Grid和List中的子组件位置交换。 效果图预览 使用说明: 拖拽Grid中子组件,到目标Grid子组件位置,进行两者位置互换。拖拽List中子组件,到目标List子组件…

java面向对象.day23(多态)

一些基础介绍: 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(一般是父类或有关系的类) 多态存在的条件 有继承关系 子类重写父类方法 父类引用…

Hbase 伪分布式安装 - UbuntuServer2204

Hbase 伪分布式安装 - UbuntuServer2204 安装伪分布Hadoop 安装 zookeeper mkdir /export/data/zookeeper/data -p mkdir /export/data/zookeeper/log -pcd /export/softpackages/ tar -xvf apache-zookeeper-3.8.4-bin.tar.gzmv apache-zookeeper-3.8.4-bin /export/server…

STM32-ADC(独立模式、双重模式)

ADC简介 18个通道:外部信号源就是16个GPIO回。在引脚上直接接模拟信号就行了,不需要侄何额外的电路。引脚就直接能测电压。2个内部信号源是内部温度传感器和内部参考电压。 逐次逼近型ADC: 它是一个独立的8位逐次逼近型ADC芯片,这个ADC0809是…

性能测试 Jmeter 非 GUI 模式 -CLI 命令详解

我们在使用Jmeter做性能测试的时候,大部分同学用的是图形化界面进行脚本编写和执行性能测试的。但是其实真正在公司执行性能测试的时候,我们基本上不会用图形化界面去执行测试,这是因为工具渲染这些图形本身会让Jmeter结果存在很多不稳定的因…

FMEA赋能可穿戴设备:打造安全可靠的未来科技新宠!

在科技日新月异的今天,可穿戴设备已成为我们生活中不可或缺的一部分。它们以其便携性、智能化和个性化的特点,深受消费者喜爱。然而,随着可穿戴设备市场的快速扩张,其安全性和可靠性问题也日益凸显。为了确保产品质量,…

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题

旧版本模式: # 以下inputTag任选其一,其他注释掉 inputTag driver.find_element_by_id("value") # 利用ID查找inputTags driver.find_element_by_class_name("value") # 利用类名查找inputTag driver.find_element_by_name(&q…

微信小程序全局配置

全局配置文件及常用的配置项 小程序根目录下的 app.json 文件是小程序的全局配置文件。常用的配置项如下: ① pages 记录当前小程序所有页面的存放路径 ② window 全局设置小程序窗口的外观 ③ tabBar 设置小程序底部的 tabBar 效果 ④ style 是否启用新版的组件样…

java实现根据sql动态下载数据到excel

需求 由于生产数据库不能直接连接下载数据,所以需要在监控系统上做一个根据sql动态查询并下载数据的功能。 实现思路 写一个接口,传入需要查询的数据库信息和sql,将查询的接口导出到Excel中 实现细节 入参 Data public class ExportDat…

递推算法4(c++)

判断整除 题目描述 一个给定的正整数序列,在每个数之前都插入号或−号后计算它们的和。比如序列:1、2、4共有8种可能的序列: (1) (2) (4) 7 (1) (2) (-4) -1 (1) (-2) (4) 3 (1) (-2) (-4) -5 (-1) (2) (4) 5 (-1) (2…

Mint Ubuntu 使用 docker compose 创建容器

1.安装 docker docker-compose sudo apt install docker.io sudo apt-get install docker-compose sudo usermod -aG docker $USER sudo systemctl daemon-reload sudo systemctl restart docker 2.配置国内 docker 镜像源 修改/etc/docker/daemon.json,增加或者…