通过 Ollama、Langchain 实现 RAG

news2024/11/22 16:34:07

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 time

if 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 splitter
            text_splitter = RecursiveCharacterTextSplitter(
                chunk_size=1500,
                chunk_overlap=200,
                length_function=len
            )
            all_splits = text_splitter.split_documents(data)

            # Create and persist the vector store
            st.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 chain
    if '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 input
    if 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 typing
                message_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.coloradmin.cn/o/1601202.html

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

相关文章

树和二叉树(一)

一、树 非线性数据结构,在实际场景中,存在一对多,多对多的情况。 树( tree)是n (n>0)个节点的有限集。当n0时,称为空树。 在任意一个非空树中,有如下特点。 1.有且仅有一个特定的称为根的节点…

公园高速公路景区校园IP网络广播音柱SIP音柱

公园高速公路景区校园IP网络广播音柱SIP音柱 适用于学校、车站、教堂、工厂、仓库、公园停车场及露天市场高速公路等场所播放录制语音文件或背景音乐节目,专业一体化音箱设计,高强度防水设计,符合IP54防护等认证,数字化产品&…

一个开源的全自动视频生成软件MoneyPrinterTurbo

只需提供一个视频 主题 或 关键词 ,就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐,然后合成一个高清的短视频。 一:功能特性 完整的 MVC架构,代码 结构清晰,易于维护,支持 API 和 Web界面…

用Scrapy抓取当当网站数据

setting.py实验目的及要求: 【实验目的】 通过本实验了解Scrapy爬虫框架;熟练掌握Scrapy的基本使用方法和常用技巧。 【实验要求】 使用Scrapy框架,抓取网站商品信息(京东、淘宝、当当等任选一个),并将结…

软考 系统架构设计师系列知识点之大数据设计理论与实践(8)

接前一篇文章:软考 系统架构设计师系列知识点之大数据设计理论与实践(7) 所属章节: 第19章. 大数据架构设计理论与实践 第3节 Lambda架构 19.3.3 Lambda架构介绍 1. 批处理层 2. 加速层 对加速层批处理视图建立索引&#xff0c…

如何将Oracle 中的部分不兼容对象迁移到 OceanBase

本文总结分析了 Oracle 迁移至 OceanBase 时,在出现三种不兼容对象的情况时的处理策略以及迁移前的预检方式,通过提前发现并处理这些问题,可以有效规避迁移过程中的报错风险。 作者:余振兴,爱可生 DBA 团队成员&#x…

【网络编程】如何创建一个自己的并发服务器?

hello !大家好呀! 欢迎大家来到我的网络编程系列之如何创建一个自己的并发服务器,在这篇文章中,你将会学习到在Linux内核中如何创建一个自己的并发服务器,并且我会给出源码进行剖析,以及手绘UML图来帮助大家…

基于Docker构建CI/CD工具链(十)总结

我们用九篇文章简单的介绍了使用Docker构建CICD工具链,希望对你的工作有所帮助。 基于Docker构建CI/CD工具链(一)构建基础工具镜像 基于Docker构建CI/CD工具链(二)快速搭建Gitlab代码库 基于Docker构建CI/CD工具链&…

【DM8】ODBC

官网下载ODBC https://www.unixodbc.org/ 上传到linux系统中 /mnt下 [rootstudy ~]#cd /mnt [rootstudy mnt]# tar -zxvf unixODBC-2.3.12.tar.gz [rootstudy mnt]# cd unixODBC-2.3.12/ [rootstudy unixODBC-2.3.12]# ./configure 注意:若是报以上错 则是gcc未安…

[计算机效率] 网站推荐:格式转换类

4.2 格式转换类 在日常办公和学习中,我们经常需要将不同格式的文件进行转换,特别是PDF文件,因其跨平台、易阅读的特性而备受青睐。然而,PDF文件的编辑和转换往往是一个棘手的问题。今天,我为大家推荐一系列优质的文件…

笔试题2 -- 字符串数组中指定字符串间的最短距离

字符串数组中指定字符串间的最短距离 文章目录 字符串数组中指定字符串间的最短距离题目还原解法一:暴力遍历 (HashVector法)解法二:算法改进 (双指针法)总结 题目链接: 数组中两个字符串的最小距离 – 牛客网 题目还原 给定一个字符串数组s…

速卖通、阿里国际站自养买家账号补单测评核心问题

补单在跨境电商中扮演着重要的角色,卖家们了解到补单可以快速增加产品的销量、评论数量,提升排名,从而打造爆款产品。产品的购买率和评价对于转化率和平台排名至关重要! 当排名不断提高,带来的流量也会增加&#xff0…

机器学习和深度学习--李宏毅(笔记与个人理解)Day17

Day 17Convolutional Neyral Network (CNN) 卷积神经网络一般都用在image 上面比较多一些,所以课程的例子大多数也都是image Image Classification the same size how about for pc? 这里对于tensor 张量这个概念,我还是比较奇怪,在我认为一…

java混淆的公司有哪些

一些提供 Java 混淆服务的公司包括: PreEmptive Solutions:PreEmptive Solutions 提供了一系列用于保护 Java 和 .NET 应用程序的工具,包括混淆、代码压缩、加密和漏洞检测等功能。 DexGuard:DexGuard 是 Guardsquare 公司推出的…

ubuntu磁盘文件损坏不能启动的修复方法

目录 1.错误现象2.解决 1.错误现象 今天早上启动虚拟机中的ubuntu发生如下错误,不能正常启动 2.解决 根据上面的提示可以运行以下命令修复: e2fsck /dev/sda1 #根据提示输入y reboot重启后ubuntu系统正常.

HR面试潜台词_弹性工作不强制考勤=做不完就要加班 扁平管理化=没有升职空间 原则上不鼓励加班=

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞…

【Leetcode每日一题】 递归 - 二叉树的所有路径(难度⭐)(59)

1. 题目解析 题目链接:257. 二叉树的所有路径 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 针对二叉树路径的求解问题,我们可以采用深度优先遍历(DFS)的策略来寻找所…

【LAMMPS学习】八、基础知识(3.3)使用分布式网格

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

筑牢个人信息安全防线,海云安受邀参加武汉“名家论坛”国家安全教育日专题讲座

近日,武汉“名家论坛”国家安全教育日专题讲座活动《“刷脸”有风险,如何保护我们的个人信息安全?》在武汉图书馆报告厅举办,海云安副总工程师李博士受邀参加本次活动。 活动以线下讲座、线上直播的形式,结合“普法讲座…

【数据结构1-基本概念和术语】

这里写自定义目录标题 0.数据,数据元素,数据项,数据对项,数据结构,逻辑结构,存储结构1.结构1.1逻辑结构1.2存储结构1.2.1 顺序结构1.2.2链式结构 1.3数据结构1.3.1基本数据类型1.3.2抽象数据类型1.3.2.1一个…