langchain框架轻松实现本地RAG

news2025/1/18 11:09:54

一 什么是RAG?

      RAG(Retrieval-Augmented Generation)是一种结合了检索和生成模型的方法,主要用于解决序列到序列的任务,如问答、对话系统、文本摘要等。它的核心思想是通过从大量文档中检索相关信息,然后利用这些信息来增强生成模型的输出。

原理如下图:

二 RAG实现思路

  RAG实现思路分为准备数据与应用检索两阶段,如图:

阶段一 数据准备阶段

  1. 数据提取:对多种格式(如 PDF、Word、Markdown、数据库和 API 等)的数据进行处理,包括过滤、压缩、格式化等,使其成为统一的范式。
  2. 分块(chunking):将初始文档分割成合适大小的块,在不丢失语义的前提下,尽量保持句子或段落的完整性。可以根据换行、句号、问号、感叹号等进行切分,或以其他合适的原则进行分割。最终将语料分割成 chunk 块,以便在检索时获取相关性最高的 top_n 块。
  3. 向量化(embedding):使用嵌入模型将文本数据转化为向量矩阵。常用的 embedding 模型有很多,例如 moka-ai/m3e-base、ganymedenil/text2vec-large-chinese 等,也可以参考 huggingface 推出的嵌入模型排行榜。向量的质量会直接影响到后续检索的效果。
  4. 数据入库:将向量化后的数据构建索引,并写入向量数据库。适用于 RAG 场景的向量数据库包括 facebookresearch/faiss(本地)、chroma、elasticsearch、milvus 等。可以根据业务场景、硬件、性能需求等因素综合考虑,选择合适的数据库。

阶段二 应用阶段

  1. 问题向量化:使用与数据准备阶段相同的嵌入模型,将用户的提问转化为向量。
  2. 数据检索:通过计算查询向量与向量数据库中存储向量的相似性得分,采用相似性检索的方式从数据库中召回与提问最相关的知识。常见的相似性计算方法包括余弦相似性、欧氏距离、曼哈顿距离等。
  3. 获取索引数据:获取检索到的相关数据。
  4. 注入 prompt:将用户查询和检索到的相关知识整合成一个提示模板。prompt 中通常包括任务描述、背景知识(即检索得到的相关内容)、任务指令(一般为用户提问)等。根据任务场景和大模型性能,也可以在 prompt 中适当加入其他指令以优化大模型的输出。
  5. LLM 生成答案:将增强后的提示输入到大型语言模型(LLM)中,让模型生成相应的答案。

三 用Python代码实现RAG

使用langchain框架用python代码实现,代码如下:

import os
import faiss
from langchain.retrievers import ContextualCompressionRetriever
from langchain_community.vectorstores import FAISS
from langchain_core.prompts import PromptTemplate
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.llms.ollama import Ollama
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_text_splitters import RecursiveCharacterTextSplitter
import config as cfg
from log_util import LogUtil
from auto_directory_loader import AutoDirectoryLoader
from BCEmbedding.tools.langchain import BCERerank



doc_path = cfg.load_doc_dir

# 在线 embedding model
embedding_model_name = 'maidalun1020/bce-embedding-base_v1'

model1_path = r'F:\ai\ai_model\maidalun1020_bce_embedding_base_v1'
model2_path = r'F:\ai\ai_model\maidalun1020_bce_reranker_base_v1'

# 本地模型路径
embedding_model_kwargs = {'device': 'cuda:0'}
embedding_encode_kwargs = {'batch_size': 32, 'normalize_embeddings': True}


embeddings = HuggingFaceEmbeddings(
    model_name=model1_path,
    model_kwargs=embedding_model_kwargs,
    encode_kwargs=embedding_encode_kwargs
)

reranker_args = {'model': model2_path, 'top_n': 5, 'device': 'cuda:0'}

reranker = BCERerank(**reranker_args)

# 检查FAISS向量库是否存在
if os.path.exists(cfg.faiss_index_path):
    # 如果存在,从本地加载
    LogUtil.info("FAISS index exists. Loading from local path...")

    vectorstore = FAISS.load_local(cfg.faiss_index_path, embeddings, allow_dangerous_deserialization=True)
    LogUtil.info("FAISS index exists. Loading from local path...")

else:
    # 如果不存在,加载txt文件并创建FAISS向量库
    LogUtil.info("FAISS index does not exist. Loading txt file and creating index...")

    loader = AutoDirectoryLoader(doc_path, glob="**/*.txt")
    docs = loader.load()

    LogUtil.info(f"Loaded documents num:{len(docs)}")

    # 从文档创建向量库
    # 文本分割
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=cfg.chunk_size, chunk_overlap=cfg.chunk_overlap)
    documents = text_splitter.split_documents(docs)
    LogUtil.info(f"Text splits num :{len(documents)}", )

    # 创建向量存储
    vectorstore = FAISS.from_documents(documents, embeddings)
    LogUtil.info("create db ok.")

    # 保存向量库到本地
    vectorstore.save_local(cfg.faiss_index_path)

    LogUtil.info("Index saved to local ok.")

# 将索引搬到 GPU 上
res = faiss.StandardGpuResources()
gpu_index = faiss.index_cpu_to_gpu(res, 0, vectorstore.index)
vectorstore.index = gpu_index

retriever = vectorstore.as_retriever(search_type="mmr", search_kwargs={"k": 10})
test_ask="宴桃园豪杰三结义有谁参加了?"
# 调试查看结果
retrieved_docs = retriever.invoke(test_ask)
for doc in retrieved_docs:
    print('++++++单纯向量库提取++++++++')
    print(doc.page_content)

compression_retriever = ContextualCompressionRetriever(
    base_compressor=reranker, base_retriever=retriever
)

response = compression_retriever.get_relevant_documents(test_ask)

print("============================================compression_retriever")
print(response)
print("---------------------end")


# 定义Prompt模板
prompt_template = """
问题:{question}

相关信息:
{retrieved_documents}

请根据以上信息回答问题。
"""

prompt = PromptTemplate(
    input_variables=["question", "retrieved_documents"],
    template=prompt_template,
)


# 创建LLM模型
llm = Ollama(model="qwen2:7b")


def format_docs(all_docs):
    txt = "\n\n".join(doc.page_content for doc in all_docs)
    print('+++++++++使用bce_embedding + bce-reranker 上下文内容++++++')
    print(txt)
    return txt


rag_chain = (
        {"retrieved_documents": compression_retriever | format_docs, "question": RunnablePassthrough()}
        | prompt
        | llm
        | StrOutputParser()
)

r = rag_chain.invoke(test_ask)
print("++++++加 LLM模型处理最终结果++++++++")
print(r)


 在上面代码中我准备了一些文档,上传到向量库,其中就有三国演义的,并提出了问题:宴桃园豪杰三结义有谁参加了?运行后回答也与文档一致,测试结果正确,并在不同的环节输出相应的结果,如下图:

第一步,直接向量库检索,相近最近的10条内容如下:

经过 bce-embedding与bce_reranker两在模型的处理,结果也是准确的

 再提交给LLM处理后的效果

 本地环境:win10系统,本地安装了ollama 并使用的是阿里最新的qwen2:7b,其实qwen:7b测试结果也是准确的。另外还使用了bce-embedding作为嵌入模型,之前测试使用过Lam2+nomic-embed-text做了很多测试发现中文无论怎么调试,都不是很理想,回答的问题总是在胡说八道的感觉。RAG应用个人感觉重点资料输入这块也很重要,像图片里的文字非得要ocr技术,这一点发现有道的qanything做得非常好,以后看来要花点时间查看qanything的源代码好好恶补一下自己这一块。

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

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

相关文章

Unity热更方案HybridCLR+YooAsset,纯c#开发热更,保姆级教程,从零开始

文章目录: 一、前言二、创建空工程三、接入HybridCLR四、接入YooAsset五、搭建本地资源服务器Nginx六、实战七、最后 一、前言 unity热更有很多方案,各种lua热更,ILRuntime等,这里介绍的是YooAssetHybridCLR的热更方案&#xff0…

丝滑流畅!使用kimi快速完成论文仿写

学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 今天的分享,我们将带大家探索一种新的学术写作技巧——使用Kimi进行论文仿写。本文将深入解析如何利用Kimi的智能辅助功能,提高论文写作的效率和质量&#xff0c…

mac显示隐藏的.git文件

打开终端 输入命令 defaults write com.apple.finder AppleShowAllFiles YES killall Finder

CTF常用sql注入(二)报错注入(普通以及双查询)

0x05 报错注入 适用于页面无正常回显,但是有报错,那么就可以使用报错注入 基础函数 floor() 向下取整函数 返回小于或等于传入参数的最大整数。换句话说,它将数字向下取整到最接近的整数值。 示例: floor(3.7) 返回 3 floor(-2…

适用于 Windows 11/10/8/7/Vista/XP 的最佳免费分区软件

无论您使用的是 SSD、机械磁盘还是任何类型的 RAID 阵列,硬盘驱动器都是 Windows 计算机中不可或缺的组件。在将文件保存到全新磁盘之前,您应该初始化它,创建分区并使用文件系统格式化。在运行计算机一段时间后,您需要收缩、扩展、…

软件性能测试有哪几种测试方法?专业性能测试报告出具

软件性能测试是指对软件系统在特定负载条件下的性能进行评估和验证的过程,目的是确保软件在正常使用的情况下能够满足用户的要求,并在稳定的性能水平下运行,在软件开发过程中起到了至关重要的作用,可以确保软件产品的质量和可靠性…

LTSPICE仿真电路:(十九)磁珠的一些简单仿真

1.作用 简单来说就是用来滤波的,将高频信号转化为热量滤除掉,低频有用信号正常通过 2.参数 上图几个参数比较简单,就是字面上的意思,更重要的就是频率阻抗图 不同曲线代表不同型号的磁珠,实际上除了额定电流外&#…

WEB01MySQL安装和数据库

第一天、WEB课程 web课程主要讲三部分内容 数据库 数据库介绍 什么是数据库 数据存储的仓库,其本质也是一个文件系统 数据库会按照特定的格式对数据进行存储,用户可以对数据库中的数据进行增加,修改,删除及查询操作。 数据库…

航空数据管控系统-②项目分析与设计:任务2:使用Git或SVN管理项目(可选任务,只介绍Git安装)

任务描述 1、安装Git 2、注册GitHub 3、配置本地库 4、配置远程库 5、使用Git管理项目 任务指导 分为以下几个部分完成: 学会Git的安装,帐号注册本地存储库的管理自己创建一个项目,项目名称为自己的名字,上传到代码仓库&#xff…

秋招突击——设计模式补充——单例模式、依赖倒转原则、工厂方法模式

文章目录 引言正文依赖倒转原则工厂方法模式工厂模式的实现简单工厂和工厂方法的对比 抽线工厂模式最基本的数据访问程序使用工厂模式实现数据库的访问使用抽象工厂模式的数据访问程序抽象工厂模式的优点和缺点使用反射抽象工厂的数据访问程序使用反射配置文件实现数据访问程序…

iPad卡在白苹果开不了机怎么办?3种解决办法!

iPad开机卡在白苹果?iPad Air 黑屏重启白苹果?iPad Pro 莫名关机,开机白苹果无法启动?iPad mini 摔落、泡水等,开机一直显示白苹果,iPad出现这些情况怎么办? 无论是使用iPad、iPad Air、iPad P…

WCCI 2024第三弹:忍者表演惊艳全场,盛大晚宴不容错过

WCCI 2024第三弹:忍者表演惊艳全场,盛大晚宴不容错过! 会议之眼 快讯 会议介绍 IEEE WCCI(World Congress on Computational Intelligence)2024,即2024年IEEE世界计算智能大会,于6月30日至7月…

【第17章】MyBatis-Plus自动维护DDL

文章目录 前言一、功能概述二、注意事项三、代码示例四、实战1. 准备2. ddl配置类3. 程序启动4. 效果(数据库) 总结 前言 在MyBatis-Plus的3.5.3版本中,引入了一项强大的功能:数据库DDL(数据定义语言)表结构的自动维护。这一功能…

安全事件响应管理系统好用?10项功能不可或缺

网络安全事件的发生,往往意味着一家企业的生产经营活动将受到重大影响,甚至会面临法律层面的违规处罚。因此,企业必须提前准备好响应网络安全事件的措施,并制定流程清晰、目标明确的事件响应计划。而为了有效提升企业的网络安全事…

企业数据API平台:获取企业多维度信息

数据API平台是指提供一系列预先定义的接口、协议与工具,允许不同应用程序或系统之间进行数据交换和通信的平台。这些接口被称为数据API(Data Application Programming Interface),是数据管理系统或应用程序提供的一组开放式接口。…

【CSAPP】-linklab实验

目录 实验目的与要求 实验原理与内容 实验步骤 实验设备与软件环境 实验过程与结果(可贴图) 实验总结 实验目的与要求 1.了解链接的基本概念和链接过程所要完成的任务。 2.理解ELF目标代码和目标代码文件的基本概念和基本构成 3.了解ELF可重定位目…

Cloudflare 推出一款免费对抗 AI 机器人的可防止抓取数据工具

上市云服务提供商Cloudflare推出了一种新的免费工具,可防止机器人抓取其平台上托管的网站以获取数据以训练AI模型。 一些人工智能供应商,包括谷歌、OpenAI 和苹果,允许网站所有者通过修改他们网站的robots.txt来阻止他们用于数据抓取和模型训…

Movable antenna 早期研究

原英文论文名字Historical Review of Fluid Antenna and Movable Antenna 最近,无线通信研究界对“流体天线”和“可移动天线”两种新兴天线技术的发展引起了极大的关注,这两种技术因其前所未有的灵活性和可重构性而极大地提高了无线应用中的系统性能。…

推荐 2个功能强大的黑科技工具,真的会让你直呼卧槽

Waifu2X Waifu2x 是一个基于深度学习的开源项目,主要用于处理二次元动漫风格的图像。它使用卷积神经网络(CNN)进行超分辨率处理和降噪,能够将图像放大2倍或更多,同时显著提高清晰度和减少噪声。Waifu2x 特别针对日系漫…

如何在TikTok上获得更多观看量:12个流量秘诀

TikTok作为热门海外社媒,在跨境出海行业中成为新兴的推广渠道,但你知道如何让你的TikTok赢得更多关注次数吗?如果您正在寻找增加 TikTok 观看次数的方法,接下来这12种策略,你需要一一做好! 1. 在内容中添加…