【深度学习总结】使用PDF构建RAG:结合Langchain和通义千问

【深度学习总结】使用PDF构建RAG:结合Langchain和通义千问

使用平台:趋动云,注册送算力

前言

在大型语言模型(LLMs)应用领域,我们面临着大量挑战,从特定领域知识的匮乏到信息准确性的窘境,以及可能生成虚假内容。检索增强生成(RAG)通过引入外部知识库等补充信息源,成为解决这些难题的有效策略。事实证明,在需要持续更新或特定领域应用的知识密集型场景中,RAG 尤其有效。与其他方法相比,RAG 的一个显著优势在于无需为特定任务重新培训 LLM。最近,RAG 因其在会话助手等应用中的成功应用而备受瞩目。

RAG构成了一种将输入与相关支持文档的语料库相结合的技术。这些文档被合并到输入提示中,并联合输入到文本生成器中,从而产生最终的输出。这种RAG的这种机制在需要适应不断变化的信息环境的场景中找到了特殊的效用,因为llm所依赖的参数化知识本质上是静态的。通过RAG,语言模型可以直接访问最新的信息,而不需要再训练,促进了生成可靠的、基于检索的输出。本质上,RAG通过检索证据提高了LLM响应的准确性、可控性和相关性,从而证明了在快速发展的环境中解决问题,并有效地缓解了错误信息生成和性能退化的问题。

RAG的一个典型应用程序如下图所示。
在这里插入图片描述

在这里,一个用户向ChatGPT提出了一个关于最近一个被广泛讨论的新闻的问题。鉴于ChatGPT依赖于训练前的数据,它最初缺乏提供最新发展的能力。RAG通过从外部数据库中获取和整合知识来弥补这一信息差距。在这种情况下,它会收集与用户查询相关的相关新闻文章。这些文章,结合最初的问题,形成了一个全面的提示,使llm能够生成一个知情的答案。典型的RAG遵循了一个传统的过程,包括索引、检索和生成,这也被描述为一个“检索“。

索引:首先以不同的格式清理和提取原始数据,如PDF、HTML、Word和标记,然后将其转换为统一的纯文本格式。为了适应语言模型的上下文限制,文本被分割成更小的、可理解的块。然后使用嵌入模型将块编码到向量表示中,并存储在向量数据库中。这一步对于在后续的检索阶段实现有效的相似性搜索至关重要。

检索:在收到用户查询后,RAG系统使用在索引阶段使用的相同的编码模型来将查询转换为向量表示。然后计算查询向量和索引语料库中的块向量之间的相似性得分。系统对与查询相似性最大的前k块进行优先排序和检索。这些数据块随后在提示符中被用作扩展的上下文。

生成:所提出的查询和所选择的文档被合成成一个连贯的提示,一个大型语言模型负责制定一个响应。模型的回答方法可能根据特定任务的标准而有所不同,允许它利用其固有的参数知识或限制其对所提供文档中包含的信息的响应。在正在进行的对话的情况下,任何现有的对话历史都可以集成到提示符中,使模型能够有效地参与多回合的对话交互

教程

PDF文件

使用的是民用飞机维修的PDF文件,可以私信我获取,你也可以用自己的。

准备

  • 通义千问的API-Key
  • 运行环境:将如下内容存入requirements.txt,然后运行:pip install -r requirements.txt
python-dotenv==1.0.1 # For reading environment variables stored in .env file
langchain==0.2.2
langchain-community==0.2.3
dashscope
unstructured==0.14.4 # Document loading
# onnxruntime==1.17.1 # chromadb dependency: on Mac use `conda install onnxruntime -c conda-forge`
# For Windows users, install Microsoft Visual C++ Build Tools first
# install onnxruntime before installing `chromadb`
chromadb==0.5.0 # Vector storage
tiktoken==0.7.0  # For embeddings 

构建RAG

先导入包:

from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.schema import Document
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings
from dotenv import load_dotenv
import os
import shutil
import dashscope
from dashscope import Generation
from langchain.prompts import ChatPromptTemplate
from http import HTTPStatus

然后将PDF数据转换为向量存储起来:

# Load environment variables. Assumes that project contains .env file with API keys
load_dotenv()
# 设置镜像,便于下载后面的HuggingFaceEmbeddings
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
# huggingface下载地址
os.environ["HF_HOME"] = "/gemini/code/huggingface"
# huggingface下载地址
os.environ["TRANSFORMERS_CACHE"] = "/gemini/code/huggingface"

os.environ["SENTENCE_TRANSFORMERS_HOME"] = "/gemini/code/huggingface/bce-embedding-base_v1"

# 向量存放位置
CHROMA_PATH = "chroma"
# 存放数据
DATA_PATH = "data/books"
dashscope.api_key = "你的通义千问api key"
print(os.getenv('DASHSCOPE_API_KEY'))
def prepare_db():
    # 处理读个pdf
    pdf_paths = ["data/books/M1.pdf",
                 "data/books/M2-航空器维修R1.pdf",
                 "data/books/M3-飞机结构和系统R1.pdf",
                 "data/books/M4-直升机结构和系统.pdf",
                 "data/books/M5-航空涡轮发动机R1.pdf",
                 "data/books/M6-活塞发动机及其维修.pdf",
                 "data/books/M7-航空器维修基本技能.pdf",
                 "data/books/M8-航空器维修实践R1.pdf"]
    documents = []
    count = 0
    for pdf_path in pdf_paths:

        loader = PyPDFLoader(pdf_path)
        doc = loader.load()
        documents.extend(doc)
        count += 1
        print(f"处理第{count}本")

    print(len(documents))

    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=300,
        chunk_overlap=100,
        length_function=len,
        add_start_index=True,
    )
    chunks = text_splitter.split_documents(documents)
    print(f"Split {len(documents)} documents into {len(chunks)} chunks.")

    document = chunks[10]
    print(document.page_content)
    print(document.metadata)

    if os.path.exists(CHROMA_PATH):
        shutil.rmtree(CHROMA_PATH)
    # 将文本保存为向量存储
    model_name = "maidalun1020/bce-embedding-base_v1"
    model_kwargs = {'device': 'cuda'}
    encode_kwargs = {'normalize_embeddings': False}
    embeddings = HuggingFaceEmbeddings(
        model_name=model_name,
        model_kwargs=model_kwargs,
        encode_kwargs=encode_kwargs,
        cache_folder="/gemini/code/huggingface/",
    )
    # Create a new DB from the documents.
    db = Chroma.from_documents(
        chunks, embeddings, persist_directory=CHROMA_PATH
    )
    db.persist()
    print(f"Saved {len(chunks)} chunks to {CHROMA_PATH}.")

然后调用通义千问的API,用户输入问题,然后根据问题从向量库中查找相关的内容,跟问题结合起来,一起喂给通义千问:

def query():
    model_name = "maidalun1020/bce-embedding-base_v1"
    model_kwargs = {'device': 'cuda'}
    encode_kwargs = {'normalize_embeddings': False}
    embeddings = HuggingFaceEmbeddings(
        model_name=model_name,
        model_kwargs=model_kwargs,
        encode_kwargs=encode_kwargs,
        # 模型缓存路径
        cache_folder="/gemini/code/huggingface/",
    )
    # 改成你的保存的路径
    db = Chroma(persist_directory="./chroma/aae4fae7-3477-4094-8a7d-c5df8be2223a", embedding_function=embeddings)
	# 提示模板
    PROMPT_TEMPLATE = """
    仅根据下列文本回答问题:
    {context}
    """
    while True:
        query = input('请输入问题:')
        results = db.similarity_search_with_relevance_scores(query, k=5)
        if len(results) == 0:
            print(f"Unable to find matching results.")
            return
        # 拼接成输入给大模型的内容
        context_text = "\n\n---\n\n".join([doc.page_content for doc, _score in results])
        messages = [
            {'role': 'system', 'content': PROMPT_TEMPLATE.format(context=context_text)},
            {'role': 'user', 'content': f"请回答如下问题:{query}"}
        ]
        print(messages)
        responses = Generation.call(Generation.Models.qwen_max, 
                                    api_key=os.getenv('DASHSCOPE_API_KEY'),
                                    messages=messages, 
                                    result_format='message')
        # 如果你不确定responses的结果,可以打印处理
        # print(responses.output)
        sources = [doc.metadata.get("source", None) for doc, _score in results]
        if responses.status_code == HTTPStatus.OK:
            whole_message = responses.output["choices"][0]["message"]["content"]
        else:
            whole_message = "error"
            print('Failed request_id: %s, status_code: %s, code: %s, message:%s' %
                (responses.request_id, responses.status_code, responses.code,
                responses.message))
        formatted_response = f"Response: {whole_message}\nSources: {sources}"
        print(formatted_response)

参考链接

langchain-rag-tutorial

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GB28181系列三:GB28181流媒体服务器ZLMediaKit

我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、ZLMediaKit介绍 二、 ZLMediaKit安装、运行(Ubuntu) 1、安装 2、运行 3、配置 三、ZLMediaKit使用 一、ZLMediaKit介绍 ZLMediaKit是一个基于C11的高性能运营级流媒体服务框架,项目地址&#xf…

React 第十七节 useMemo用法详解

概述 useMemo 是React 中的一个HOOK,用于根据依赖在每次渲染时候缓存计算结果; 大白话就是,只有依赖项发生变化时候,才会重新渲染为新计算的值,否则就还是取原来的值,有点类似 vue 中的 computed 计算属性…

若依前后端分离版集成ShardingSphere-补充版代码演示

拉取项目&#xff1a;https://gitee.com/y_project/RuoYi-Vue。前后端分离版本新建数据库&#xff0c;字符集选择utf8mb4。导入mysql文件。 主pom文件中引入依赖 <!-- 分库分表引擎 --><dependency><groupId>org.apache.shardingsphere</groupId><…

Postman接口测试:全局变量/接口关联/加密/解密

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 全局变量和环境变量 全局变量&#xff1a;在postman全局生效的变量&#xff0c;全局唯一 环境变量&#xff1a;在特定环境下生效的变量&#xff0c;本环境内唯一 …

基于PHP的民宿预订管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的民宿预订管理系统 一 介绍 此民宿预订管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。(附带配套设计文档) 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册…

Elasticsearch:使用 Open Crawler 和 semantic text 进行语义搜索

作者&#xff1a;来自 Elastic Jeff Vestal 了解如何使用开放爬虫与 semantic text 字段结合来轻松抓取网站并使其可进行语义搜索。 Elastic Open Crawler 演练 我们在这里要做什么&#xff1f; Elastic Open Crawler 是 Elastic 托管爬虫的后继者。 Semantic text 是 Elasti…

NVM:安装配置使用(详细教程)

文章目录 一、简介二、安装 nvm三、配置 nvm 镜像四、配置环境变量五、使用教程5.1 常用命令5.2 具体案例 六、结语 一、简介 在实际的开发和学习中可能会遇到不同项目的 node 版本不同&#xff0c;而出现的兼容性问题。 而 nvm 就可以很好的解决这个问题&#xff0c;它可以在…

【HarmonyOS】HarmonyOS 和 Flutter混合开发 (一)之鸿蒙Flutter环境安装

【HarmonyOS】HarmonyOS 和 Flutter混合开发 &#xff08;一&#xff09;之鸿蒙Flutter环境安装 一、前言 flutter作为开源适配框架方案&#xff0c;已经在Android&#xff0c;IOS&#xff0c;Web&#xff0c;Window四大平台进行了适配&#xff0c;一套代码&#xff0c;可以同…

期权懂|期权新手入门知识:个股期权标的资产的作用

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 期权新手入门知识&#xff1a;个股期权标的资产的作用 个股期权标的资产的作用主要体现在以下几个方面‌&#xff1a; &#xff08;1&#xff09;基本面影响‌&#xff1a; 标的资…

Unity超优质动态天气插件(含一年四季各种天气变化,可用于单机局域网VR)

效果展示&#xff1a;https://www.bilibili.com/video/BV1CkkcYHENf/?spm_id_from333.1387.homepage.video_card.click 在你的项目中设置enviro真的很容易&#xff01;导入包裹并按照以下步骤操作开始的步骤&#xff01; 1. 拖拽“EnviroSky”预制件&#xff08;“environme…

【算法】【优选算法】链表

目录 一、链表常用技巧与操作总结二、2.两数相加三、24.两两交换链表中的节点3.1 迭代3.2 递归 四、143.重排链表五、23.合并K个升序链表5.1 堆5.2 分治5.3 暴力枚举 六、25.K个⼀组翻转链表 一、链表常用技巧与操作总结 技巧&#xff1a; 画图解题。使用虚拟头结点。像有插入…

【面试】Redis 常见面试题

一、介绍一下什么是 Redis&#xff0c;有什么特点? Redis 是一个高性能的 key-value 内存数据库。 不同于传统的 MySQL 这样的关系型数据库&#xff0c;Redis 主要使用内存存储数据&#xff08;当然也支持持久化存储到硬盘上&#xff09;&#xff0c;并非是使用 “表” 这样…

【Linux】NET9运行时移植到低版本GLIBC的Linux纯内核板卡上

背景介绍 自制了一块Linux板卡(基于全志T113i) 厂家给的SDK和根文件系统能够提供的GLIBC的版本比较低 V2.25/GCC 7.3.1 这个版本是无法运行dotnet以及dotnet生成的AOT应用的 我用另一块同Cortex-A7的板子运行dotnet的报错 版本不够&#xff0c;运行不了 而我的板子是根本就识…

MySQL Explain 分析SQL语句性能

一、EXPLAIN简介 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句&#xff0c;从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。 &#xff08;1&#xff09; 通过EXPLAIN&#xff0c;我们可以分析出以下结果&#xff1a; 表的读取顺序数据读取…

vue3实现商城系统详情页(前端实现)

目录 写在前面 预览 实现 图片部分 详情部分 代码 源码地址 总结 写在前面 笔者不是上一个月毕业了么&#xff1f;找工作没找到&#xff0c;准备在家躺平两个月。正好整理一下当时的毕业设计&#xff0c;是一个商城系统。还是写篇文章记录下吧 预览 商品图片切换显示…

uniapp 微信小程序 功能入口

单行单独展示 效果图 html <view class"shopchoose flex jsb ac" click"routerTo(要跳转的页面)"><view class"flex ac"><image src"/static/dyd.png" mode"aspectFit" class"shopchooseimg"&g…

6.1 初探MapReduce

MapReduce是一种分布式计算框架&#xff0c;用于处理大规模数据集。其核心思想是“分而治之”&#xff0c;通过Map阶段将任务分解为多个简单任务并行处理&#xff0c;然后在Reduce阶段汇总结果。MapReduce编程模型包括Map和Reduce两个阶段&#xff0c;数据来源和结果存储通常在…

聚观早报 | 百度回应进军短剧;iPad Air将升级OLED

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 12月18日消息 百度回应进军短剧 iPad Air将升级OLED 三星Galax S25 Ultra配色细节 一加Ace 5系列存储规格 小米…

CH582F BLE5.3 蓝牙核心板开发板 60MHz RAM:32KB ROM:448KB

CH582F BLE5.3 蓝牙核心板开发板 60MHz RAM:32KB ROM:448KB 是一款基于南京沁恒&#xff08;WCH&#xff09;推出的高性能、低功耗无线通信芯片CH582F的开发板。以下是该开发板的功能和参数详细介绍&#xff1a; 主要特性 双模蓝牙支持&#xff1a; 支持蓝牙5.0标准&#xff0…

【软件工程复习】

第1章 软件工程概述 1.2软件工程 ​ 1983年IEEE给出的定义&#xff1a;“软件工程是 开发、运行、维护和修复软件的系统方法 ” 1.4软件生存期 软件开发和运行维护由三个时期组成&#xff1a; 软件定义时期软件开发时期运行维护时期 里程碑指可以用来标识项目进程状态的事…