【datawhale组队学习】RAG技术 - TASK02

教程地址:https://github.com/datawhalechina/all-in-rag/
感谢datawhale的教程,以下笔记大部分内容来自该教程

文章目录

  • 基于LangChain框架的RAG实现
    • 初始化设置
    • 数据准备
    • 索引构建
    • 查询与检索
    • 生成集成
  • 低代码(基于LlamaIndex)

conda activate all-in-rag
# 假设当前在 all-in-rag 项目的根目录下
cd code/C1
#运行代码
python 01_langchain_example.py

在这里插入图片描述
输出的参数

  • content: 这是最核心的部分,即大型语言模型(LLM)根据你的问题和提供的上下文生成的具体回答。
  • additional_kwargs: 包含一些额外的参数,在这个例子中是 {‘refusal’: None},表示模型没有拒绝回答。
  • response_metadata: 包含了关于LLM响应的元数据。
  • token_usage: 显示了本次调用消耗的token数量,包括完成(completion_tokens)、提示(prompt_tokens)和总量(total_tokens)。
  • model_name: 使用的LLM模型名称,当前是 deepseek-chat。
  • system_fingerprint, id, service_tier, finish_reason, logprobs: 这些是更详细的API响应信息,例如 finish_reason: ‘stop’ 表示模型正常完成了生成。
  • id: 本次运行的唯一标识符。
  • usage_metadata: 与 response_metadata 中的 token_usage 类似,提供了输入和输出token的统计。

如果没有魔法,且下载模型失败
在shell中从huggingface下载模型

export HF_ENDPOINT=https://hf-mirror.com
hf download --local-dir ./bge-small-zh-v1.5  BAAI/bge-small-zh-v1.5 

在使用的时候显示指定位置在哪个路径。

基于LangChain框架的RAG实现

初始化设置

import os
# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
from dotenv import load_dotenv
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_core.prompts import ChatPromptTemplate
from langchain_deepseek import ChatDeepSeek# 加载环境变量
load_dotenv()

数据准备

  1. 加载原始文档: 先定义Markdown文件的路径,然后使用TextLoader加载该文件作为知识源
markdown_path = "../../data/C1/markdown/easy-rl-chapter1.md"
loader = TextLoader(markdown_path)
docs = loader.load()
  1. 文本分块 (Chunking): 为了便于后续的嵌入和检索,长文档被分割成较小的、可管理的文本块(chunks)。这里采用了递归字符分割策略,使用其默认参数进行分块。当不指定参数初始化 RecursiveCharacterTextSplitter() 时,其默认行为旨在最大程度保留文本的语义结构:
  • 默认分隔符与语义保留: 按顺序尝试使用一系列预设的分隔符 [“\n\n” (段落), “\n” (行), " " (空格), “” (字符)] 来递归分割文本。这种策略的目的是尽可能保持段落、句子和单词的完整性,因为它们通常是语义上最相关的文本单元,直到文本块达到目标大小。
  • 保留分隔符: 默认情况下 (keep_separator=True),分隔符本身会被保留在分割后的文本块中。
  • 默认块大小与重叠: 使用其基类 TextSplitter 中定义的默认参数 chunk_size=4000(块大小)和 chunk_overlap=200(块重叠)。这些参数确保文本块符合预定的大小限制,并通过重叠来减少上下文信息的丢失。
text_splitter = RecursiveCharacterTextSplitter()
texts = text_splitter.split_documents(docs)

索引构建

初始化中文嵌入模型+构建向量存储
HugginfaceEmbeddings+InMemoeyVectorStore
初始化中文嵌入模型: 使用HuggingFaceEmbeddings加载之前在初始化设置中下载的中文嵌入模型。配置模型在CPU上运行,并启用嵌入归一化 (normalize_embeddings: True)。

embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5",model_kwargs={'device': 'cpu'},#配置模型在CPU上运行encode_kwargs={'normalize_embeddings': True}#启用嵌入归一化
)

构建向量存储: 将分割后的文本块 (texts) 通过初始化好的嵌入模型转换为向量表示,然后使用InMemoryVectorStore将这些向量及其对应的原始文本内容添加进去,从而在内存中构建出一个向量索引。

vectorstore = InMemoryVectorStore(embeddings)
vectorstore.add_documents(texts)

查询与检索

索引构建完毕后,便可以针对用户问题进行查询与检索:
定义用户查询: 设置一个具体的用户问题字符串。

question = "文中举了哪些例子?"

在向量存储中查询相关文档: 使用向量存储的similarity_search方法,根据用户问题在索引中查找最相关的 k (此处示例中 k=3) 个文本块。

retrieved_docs = vectorstore.similarity_search(question, k=3)

准备上下文: 将检索到的多个文本块的页面内容 (doc.page_content) 合并成一个单一的字符串,并使用双换行符 (“\n\n”) 分隔各个块,形成最终的上下文信息 (docs_content) 供大语言模型参考。

docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs)

使用 “\n\n” (双换行符) 而不是 “\n” (单换行符) 来连接不同的检索文档块,主要是为了在传递给大型语言模型(LLM)时,能够更清晰地在语义上区分这些独立的文本片段。双换行符通常代表段落的结束和新段落的开始,这种格式有助于LLM将每个块视为一个独立的上下文来源,从而更好地理解和利用这些信息来生成回答。

生成集成

最后一步是将检索到的上下文与用户问题结合,利用大语言模型(LLM)生成答案:

  • 构建提示词模板: 使用ChatPromptTemplate.from_template创建一个结构化的提示模板。此模板指导LLM根据提供的上下文 (context) 回答用户的问题 (question),并明确指出在信息不足时应如何回应。
prompt = ChatPromptTemplate.from_template("""请根据下面提供的上下文信息来回答问题。
请确保你的回答完全基于这些上下文。
如果上下文中没有足够的信息来回答问题,请直接告知:“抱歉,我无法根据提供的上下文找到相关信息来回答此问题。”上下文:
{context}问题: {question}回答:"""

配置大语言模型: 初始化ChatDeepSeek客户端,配置所用模型 (deepseek-chat)、生成答案的温度参数 (temperature=0.7)、最大Token数 (max_tokens=2048) 以及API密钥 (从环境变量加载)。

llm = ChatDeepSeek(model="deepseek-chat",temperature=0.7,max_tokens=2048,api_key=os.getenv("DEEPSEEK_API_KEY")
)

调用LLM生成答案并输出: 将用户问题 (question) 和先前准备好的上下文 (docs_content) 格式化到提示模板中,然后调用ChatDeepSeek的invoke方法获取生成的答案。

answer = llm.invoke(prompt.format(question=question, context=docs_content))
print(answer)
# 文本分块
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,      # 增大块大小,每个块约1000字符chunk_overlap=200,    # 增大重叠部分,保持上下文连贯性separators=["\n\n", "\n", " ", ""]  # 自定义分割符)

调整chunksize和chunk_overlap

在这里插入图片描述

print(answer.content)#获取回答

在这里插入图片描述

参数调整对输出的影响

  1. chunk_size 的影响:
  • 较小的chunk_size(如 500):文本块更细碎,检索到的信息可能更精准但不完整
  • 较大的chunk_size(如 2000):文本块更完整,上下文信息更丰富,但可能包含冗余内容
  1. chunk_overlap 的影响:
  • 较小的chunk_overlap(如 50):文本块独立性强,可能丢失跨块的上下文关联
  • 较大的chunk_overlap(如 300):增强了块之间的连贯性,适合处理有连续逻辑的文本,但会增加冗余

低代码(基于LlamaIndex)

在RAG方面,LlamaIndex提供了更多封装好的API接口,这无疑降低了上手门槛,下面是一个简单实现:

import os
# os.environ['HF_ENDPOINT']='https://hf-mirror.com'
from dotenv import load_dotenv
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings 
from llama_index.llms.deepseek import DeepSeek
from llama_index.embeddings.huggingface import HuggingFaceEmbeddingload_dotenv()
#环境设置
#模型配置
Settings.llm = DeepSeek(model="deepseek-chat", api_key=os.getenv("DEEPSEEK_API_KEY"))
## 设置使用 DeepSeek 的聊天模型作为语言模型
Settings.embed_model = HuggingFaceEmbedding("BAAI/bge-small-zh-v1.5")
## 设置使用 BAAI 的中文小型嵌入模型进行文本向量化documents = SimpleDirectoryReader(input_files=["../../data/C1/markdown/easy-rl-chapter1.md"]).load_data()
## 从指定路径加载 Markdown 文档内容
index = VectorStoreIndex.from_documents(documents)
# 将文档内容转换为向量索引,便于后续的相似性搜索
query_engine = index.as_query_engine()
# 创建查询引擎,用于处理自然语言查询
print(query_engine.get_prompts()) # 打印使用的提示词模板
print(query_engine.query("文中举了哪些例子?")) # 执行查询并打印结果

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

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

相关文章

Mitt 事件发射器完全指南:200字节的轻量级解决方案

简介 Mitt 是一个轻量级的事件发射器库,体积小巧(约 200 字节),无依赖,支持 TypeScript。它提供了简单而强大的事件发布/订阅机制,适用于组件间通信、状态管理等场景。 特点 🚀 超轻量级&…

数据库锁与死锁-笔记

一、概述 数据库是一个共享资源,可以供给多个用户使用。运行多个用户同时使用一个数据库的数据系统统称多用户数据库系统。例如,飞机订票数据库系统。在这样的一个系统中,在同一时刻并发运行的事务数可达数百上千个。 当多个用户并发地存取数据库时就会产生多个事务同时存…

渗透艺术系列之Laravel框架(二)

任何软件,都会存在安全漏洞,我们应该将攻击成本不断提高!​**——服务容器与中间件的攻防博弈**​本文章仅提供学习,切勿将其用于不法手段!一、服务容器的"依赖注入陷阱"1.1 接口绑定的"影子服务"…

官网SSO登录系统的企业架构设计全过程

第一阶段:架构愿景与业务架构设计 (Architecture Vision & Business Architecture) 任何架构的起点都必须是业务目标和需求。 1.1 核心业务目标 (Business Goals) 提升用户体验:用户一次登录,即可无缝访问集团下所有子公司的官网和应用&a…

2025世界机器人大会:中国制造“人形时代”爆发

2025世界机器人博览会8月8日在北京亦庄开幕,主题为“让机器人更智慧,让具身体更智能”,汇聚全球200余家企业、1500余件展品,其中首发新品超100款,人形机器人整机企业参展数量创同类展会之最。 除了机器人本体外&#…

Oracle 库定期备份表结构元数据信息至目标端备份脚本

一、背景描述当前 xxx 项目 Oracle 11g RAC 库缺少 DG,并且日常没有备份,存在服务器或存储损坏,数据或表结构存在丢失风险,在和项目组同步后,项目组反馈可对该数据库定期备份相关结构信息,如存在数据丢失&a…

wps安装后win系统浏览窗口无法查看

前提需要有安装office软件,PDF一般默认是浏览器,如果设置浏览器不行,就安装Adobe Acrobat DC软件1、按winR键,输入regedit,进入注册表2、找到路径:\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Current…

Qt 中最经典、最常用的多线程通信场景

实现步骤创建工作类 (Worker):在工作线程中处理数据的对象。创建线程对象 (QThread):用来托管工作对象。连接信号槽:主线程 -> 工作线程:连接一个主窗口发出的信号到工作对象的槽,用于传递数据。工作线程 -> 主线…

【CV 目标检测】Fast RCNN模型①——与R-CNN区别

3.Fast RCNN模型 相比于R-CNN,Fast RCNN模型主要在以下三个方面进行了改进: 提高训练和预测速度 R-CNN首先从测试图中提取2000个候选区域,然后将这2000个候选区域分别输入到预训练好的CNN中提取特征。由于候选区域有大量的重叠,这…

Zookeeper学习

要精通 ZooKeeper,需要掌握其核心原理、数据模型、分布式协调机制、典型应用场景、运维管理与性能调优等方面的知识。以下是系统化的知识体系:✅ 一、ZooKeeper 基础原理ZooKeeper 是什么 分布式协调服务,提供一致性、高可用的元数据管理核心…

用TestComplete打造高效CI/CD测试流程

传统的UI测试往往受限于图形界面渲染,导致执行速度慢、资源占用高,难以适应持续集成/持续交付(CI/CD)管道的需求。自动化UI测试平台TestComplete的智能质量附加组件通过无头测试技术,为开发团队提供了一种更高效、更可…

C++ 浅拷贝 和深拷贝的知识点讲解

好问题 👍,这个就是理解 delete 的关键前置知识。 我从 C语言基础 出发,像教科书一样,从零讲给你听。1. 什么是“拷贝”? 在 C 中,当你有一个对象 A,然后写: Device_Info a; Device…

Arkts加载网页url的pdf发票黑屏问题

使用模拟器会闪退,连接真机预览正常import { HMRouter, HMRouterMgr, HMParamType, HMPageParam } from "hadss/hmrouter"; import { BaseTitle, RouterConstants } from "commonlib"; import { webview } from kit.ArkWeb; import { PDFView }…

使用 mongosh 设置 MongoDB 账号密码

可以使用 mongosh(MongoDB 6.0+ 的现代Shell)来设置账号密码。mongosh 是官方推荐的新一代MongoDB Shell工具,替代了传统的 mongo 命令。 【本人博文提到的ip均为随机生成的,不是实际的ip,仅供参考,如有雷同,纯属巧合】 使用 mongosh 设置 MongoDB 账号密码 1. 首先连…

HTML+CSS:浮动详解

在HTMLCSS布局中,浮动(float) 是一种经典的布局技术,用于控制元素在页面中的排列方式。它最初设计用于实现文字环绕图片的效果,后来被广泛用于复杂布局,但随着Flexbox和Grid的兴起,其使用场景有…

GPIO初始化及调用

下面把 HAL 库 和 标准外设库(SPL) 初始化 GPIO 点亮/熄灭 LED 的完整步骤、示例代码和常用 API 逐一说清楚。用例默认 PC13 接 LED(蓝板常见;低电平点亮,高电平熄灭——若板子相反,只把写 1/0 对调即可&am…

【GPT入门】第48课 LlamaFacotory 合并原模型与LoRA模型

【GPT入门】第48课 LlamaFacotory 合并原模型与LoRA模型1.合并原模型与LoRA训练的增量模型2. 测试模型1.合并原模型与LoRA训练的增量模型 llamafactory-cli webui 执行合并 合并后模型大小 (base) rootautodl-container-b4b04ea4f2-b5ee47d1:~# du -sh /root/autodl-tmp/mod…

Python爬虫实战:研究tumblr,构建博客平台数据采集分析系统

1. 引言 1.1 研究背景 在信息爆炸的时代,社交媒体平台已成为人们获取信息、表达观点和进行社交互动的主要渠道。这些平台上积累的海量数据包含了用户偏好、社会趋势、文化现象等丰富信息,对学术研究、市场分析、产品开发等领域具有重要价值。 Tumblr 作为一个综合性的轻博客…

集成算法学习总结

一、集成学习基础认知 核心思想:集成学习(ensemble learning)通过构建并结合多个个体学习器来完成学习任务,类似于 “多个专家共同决策”,通常比单个学习器的性能更优。其核心逻辑是利用多个学习器的优势互补&#xff…

线程安全的产生以及解决方案

线程安全原子性(Atomicity)、可见性(Visibility)、有序性(Ordering) 是保证线程安全的三大核心要素 —— 线程安全问题的本质,几乎都是这三个特性中的一个或多个被破坏导致的。操作不会被 “中途…