RAG实战4-RAG过程中发生了什么?

2024-06-12 11:04
文章标签 实战 过程 发生 rag

本文主要是介绍RAG实战4-RAG过程中发生了什么?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

RAG实战4-RAG过程中发生了什么?

在RAG实战3中我们介绍了如何追踪哪些文档片段被用于检索增强生成,但我们仍不知道RAG过程中到底发生了什么,为什么大模型能够根据检索出的文档片段进行回复?本文将用一个简单的例子来解释前面的问题。

在阅读本文之前,请先阅读RAG实战3。

回答:为什么大模型能够根据检索出的文档片段进行回复?

先执行以下代码:

import logging
import sys
import torch
from llama_index.core import PromptTemplate, Settings, StorageContext, load_index_from_storage
from llama_index.core.callbacks import LlamaDebugHandler, CallbackManager
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLM# 定义日志
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))# 定义system prompt
SYSTEM_PROMPT = """You are a helpful AI assistant."""
query_wrapper_prompt = PromptTemplate("[INST]<<SYS>>\n" + SYSTEM_PROMPT + "<</SYS>>\n\n{query_str}[/INST] "
)# 使用llama-index创建本地大模型
llm = HuggingFaceLLM(context_window=4096,max_new_tokens=2048,generate_kwargs={"temperature": 0.0, "do_sample": False},query_wrapper_prompt=query_wrapper_prompt,tokenizer_name='/yldm0226/models/Qwen1.5-14B-Chat',model_name='/yldm0226/models/Qwen1.5-14B-Chat',device_map="auto",model_kwargs={"torch_dtype": torch.float16},
)
Settings.llm = llm# 使用LlamaDebugHandler构建事件回溯器,以追踪LlamaIndex执行过程中发生的事件
llama_debug = LlamaDebugHandler(print_trace_on_end=True)
callback_manager = CallbackManager([llama_debug])
Settings.callback_manager = callback_manager# 使用llama-index-embeddings-huggingface构建本地embedding模型
Settings.embed_model = HuggingFaceEmbedding(model_name="/yldm0226/RAG/BAAI/bge-base-zh-v1.5"
)# 从存储文件中读取embedding向量和向量索引
storage_context = StorageContext.from_defaults(persist_dir="doc_emb")
index = load_index_from_storage(storage_context)
# 构建查询引擎
query_engine = index.as_query_engine(similarity_top_k=5)# 查询获得答案
response = query_engine.query("不耐疲劳,口燥、咽干可能是哪些证候?")
print(response)# get_llm_inputs_outputs返回每个LLM调用的开始/结束事件
event_pairs = llama_debug.get_llm_inputs_outputs()
# print(event_pairs[0][1].payload.keys())
print(event_pairs[0][1].payload["formatted_prompt"])

输出很长,我们一部分一部分来看。

首先找到类似下面的输出:

**********
Trace: query|_query ->  14.458354 seconds|_retrieve ->  0.845918 seconds|_embedding ->  0.71383 seconds|_synthesize ->  13.612246 seconds|_templating ->  2e-05 seconds|_llm ->  13.60905 seconds
**********

以上的输出记录了我们的query在程序过程中经历的阶段和所用的时间。整个过程分为两个阶段:抽取(retrieve)和合成(synthesize)。

合成阶段的templating步骤会将我们的query和抽取出来的文档片段组合成模板,构成新的query,然后调用LLM,得到最终的response。

所以,我们只要找到templating所构建的新query,就可以知道为什么大模型能够根据我们检索出来的文档进行回复了。

在输出中找到response下面的部分:

[INST]<<SYS>>
You are a helpful AI assistant.<</SYS>>Context information is below.
---------------------
file_path: document/中医临床诊疗术语证候.txt4.6.1.1津液不足证  syndrome/pattern of fluid and humor insufficiency津亏证因津液生成不足,或嗜食辛辣,蕴热化燥,邪热灼损津液所致。临床以口眼喉鼻及皮肤等干燥,大便干结,小便短少,舌质偏红而干,脉细数等为特征的证候。4.6.1.file_path: document/中医临床诊疗术语证候.txt临床以口干、舌燥,频饮而不解其渴,食多、善饥,夜尿频多,逐渐消瘦,舌质红,舌苔薄黄或少,脉弦细或滑数,伴见皮肤干燥,四肢乏力,大便干结等为特征的证候。4.6.3.2津亏热结证  syndrome/pattern of fluid depletion and heat binding液干热结证因津液亏虚,热邪内结所致。file_path: document/中医临床诊疗术语证候.txt临床以口眼喉鼻及皮肤等干燥,大便干结,小便短少,舌质偏红而干,脉细数等为特征的证候。4.6.1.2津液亏涸证  syndrome/pattern of fluid and humor scantiness津液亏耗证津液干枯证因津液亏损,形体官窍失养所致。临床以口干、唇裂,鼻燥无涕,皮肤干瘪,目陷、螺瘪,甚则肌肤甲错,舌质红而少津,舌中裂,脉细或数,可伴见口渴、欲饮,干咳,目涩,大便干,小便少等为特征的证候。file_path: document/中医临床诊疗术语证候.txt临床以鼻咽干涩或痛,口唇燥干,舌质红,舌苔白或燥,脉浮或微数,伴见发热、无汗,头痛或肢节酸痛等为特征的证候。3.6.3.2燥干清窍证  syndrome/pattern of dryness harassing the upper orifices因气候或环境干燥,津液耗损,清窍失濡所致。临床以口鼻、咽喉干燥,两眼干涩,少泪、少涕、少津、甚则衄血,舌质瘦小、舌苔干而少津,脉细等为特征的证候。file_path: document/中医临床诊疗术语证候.txt6.3.1津伤化燥证  syndrome/pattern of fluid damage transforming into dryness津伤燥热证因燥热内蕴,或内热化燥,伤津耗液所致。临床以口干、舌燥,频饮而不解其渴,食多、善饥,夜尿频多,逐渐消瘦,舌质红,舌苔薄黄或少,脉弦细或滑数,伴见皮肤干燥,四肢乏力,大便干结等为特征的证候。4.6.3.
---------------------
Given the context information and not prior knowledge, answer the query.
Query: 不耐疲劳,口燥、咽干可能是哪些证候?
Answer: [/INST] 

上面这段很长的文本是由print(event_pairs[0][1].payload["formatted_prompt"])语句输出的,这段文本就是templating后的新query。

现在,我们就能回答为什么大模型能够根据检索出的文档片段进行回复这个问题了:我们的原始query由"不耐疲劳,口燥、咽干可能是哪些证候?"变成了上面这段很长的新query,由于我们给大模型提供了一些文档片段知识,并且要求大模型根据提供的先验知识回答我们的原始query,因此大模型能够根据检索出的文档片段进行回复。(这其实也就是RAG技术的本质了)

可以发现一个问题,新query中既有中文,也有英文,这是因为LlamaIndex是外国人做的,他们构建的模板都是英文的。LlamaIndex允许自定义查询流程,构建自己的中文模板,这里中英文混合也解决了我们的问题,因此不再赘述。

此外,event_pairs中其实还有很多对我们有用的信息,你可以通过输出或DEBUG的方式来寻找能够解决你自己问题的信息。比如,我注释掉的#print(event_pairs[0][1].payload.keys())就可以输出事件结束时所有相关的属性。

下面是模型的回复:

从提供的中医临床证候信息来看,口燥、咽干的症状可能与以下证候相关:1. 津液不足证:由于津液生成不足或者体内燥热导致,表现为口眼喉鼻干燥,咽干是其中的一个症状。2. 津亏热结证:津液亏虚加上热邪内结,也可能出现口燥和咽干。3. 津液亏涸证:严重的津液亏损可能导致口唇干燥、咽部干燥,伴随其他严重脱水症状。4. 燥干清窍证:气候干燥或体质原因引起的津液缺乏,口鼻咽喉干燥也是其特征。5. 津伤化燥证:燥热内蕴或内热化燥损伤津液,也会出现口燥、频饮但不解渴的现象。因此,这些证候都有可能与不耐疲劳和口燥、咽干的症状相符合,需要结合其他临床表现来确定具体的证候类型。建议在中医诊断中由专业医生根据全人情况判断。

进阶尝试

接下来,我们尝试跟踪一下更复杂的RAG过程。

前面我们提到了抽取(retrieve)和合成(synthesize)两个阶段。

抽取(retrieve)阶段的retrievers模块规定了针对查询从知识库获取相关上下文的技术。我们之前使用的都是默认的方法,其实LlamaIndex官方为我们提供了一些其他常用的方法:

  • SimilarityPostprocessor: 使用similarity_cutoff设置阈值。移除低于某个相似度分数的节点。
  • KeywordNodePostprocessor: 使用required_keywords和exclude_keywords。根据关键字包含或排除过滤节点。
  • MetadataReplacementPostProcessor: 用其元数据中的数据替换节点内容。
  • LongContextReorder: 重新排序节点,这有利于需要大量顶级结果的情况,可以解决模型在扩展上下文中的困难。
  • SentenceEmbeddingOptimizer: 选择percentile_cutoff或threshold_cutoff作为相关性。基于嵌入删除不相关的句子。
  • CohereRerank: 使用coherence ReRank对节点重新排序,返回前N个结果。
  • SentenceTransformerRerank: 使用SentenceTransformer交叉编码器对节点重新排序,产生前N个节点。
  • LLMRerank: 使用LLM对节点重新排序,为每个节点提供相关性评分。
  • FixedRecencyPostprocessor: 返回按日期排序的节点。
  • EmbeddingRecencyPostprocessor: 按日期对节点进行排序,但也会根据嵌入相似度删除较旧的相似节点。
  • TimeWeightedPostprocessor: 对节点重新排序,偏向于最近未返回的信息。
  • PIINodePostprocessor(β): 可以利用本地LLM或NER模型删除个人身份信息。
  • PrevNextNodePostprocessor(β): 根据节点关系,按顺序检索在节点之前、之后或两者同时出现的节点。

合成(synthesize)阶段的响应合成器(response synthesizer)会引导LLM生成响应,将用户查询与检索到的文本块混合在一起。

假设有一堆文档。现在,你问了一个问题,并希望根据这些文档得到答案。响应合成器就像人一样,浏览文档,找到相关信息,并生成回复。

retrievers负责提取出相关的文本片段,我们已经讨论过了。而响应合成器负责将这些片段收集起来,并给出一个精心设计的答案。

LlamaIndex官方为我们提供了多种响应合成器:

  • Refine: 这种方法遍历每一段文本,一点一点地精炼答案。
  • Compact: 是Refine的精简版。它将文本集中在一起,因此需要处理的步骤更少。
  • Tree Summarize: 想象一下,把许多小的答案结合起来,再总结,直到你得到一个主要的答案。
  • Simple Summarize: 只是把文本片段剪短,然后给出一个快速的总结。
  • No Text: 这个问题不会给你答案,但会告诉你它会使用哪些文本。
  • Accumulate: 为每一篇文章找一堆小答案,然后把它们粘在一起。
  • Compact Accumulate: 是“Compact”和“Accumulate”的合成词。

此外,retriever和response synthesizer都支持自定义,在此不作讨论。

现在,让我们选择一种retriever和一种response synthesizer。retriever选择SimilarityPostprocessor,response synthesizer选择Refine

代码如下所示:

import logging
import sys
import torch
from llama_index.core import PromptTemplate, Settings, SimpleDirectoryReader, \VectorStoreIndex, get_response_synthesizer
from llama_index.core.callbacks import LlamaDebugHandler, CallbackManager
from llama_index.core.indices.vector_store import VectorIndexRetriever
from llama_index.core.postprocessor import SimilarityPostprocessor
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.response_synthesizers import ResponseMode
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLM# 定义日志
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))# 定义system prompt
SYSTEM_PROMPT = """You are a helpful AI assistant."""
query_wrapper_prompt = PromptTemplate("[INST]<<SYS>>\n" + SYSTEM_PROMPT + "<</SYS>>\n\n{query_str}[/INST] "
)# 使用llama-index创建本地大模型
llm = HuggingFaceLLM(context_window=4096,max_new_tokens=2048,generate_kwargs={"temperature": 0.0, "do_sample": False},query_wrapper_prompt=query_wrapper_prompt,tokenizer_name='/yldm0226/models/Qwen1.5-14B-Chat',model_name='/yldm0226/models/Qwen1.5-14B-Chat',device_map="auto",model_kwargs={"torch_dtype": torch.float16},
)
Settings.llm = llm# 使用LlamaDebugHandler构建事件回溯器,以追踪LlamaIndex执行过程中发生的事件
llama_debug = LlamaDebugHandler(print_trace_on_end=True)
callback_manager = CallbackManager([llama_debug])
Settings.callback_manager = callback_manager# 使用llama-index-embeddings-huggingface构建本地embedding模型
Settings.embed_model = HuggingFaceEmbedding(model_name="/yldm0226/RAG/BAAI/bge-base-zh-v1.5"
)# 读取文档并构建索引
documents = SimpleDirectoryReader("document").load_data()
index = VectorStoreIndex.from_documents(documents)# 构建retriever
retriever = VectorIndexRetriever(index=index,similarity_top_k=5,
)# 构建response synthesizer
response_synthesizer = get_response_synthesizer(response_mode=ResponseMode.REFINE
)# 构建查询引擎
query_engine = RetrieverQueryEngine(retriever=retriever,response_synthesizer=response_synthesizer,node_postprocessors=[SimilarityPostprocessor(similarity_cutoff=0.6)],
)# 查询获得答案
response = query_engine.query("不耐疲劳,口燥、咽干可能是哪些证候?")
print(response)# get_llm_inputs_outputs返回每个LLM调用的开始/结束事件
event_pairs = llama_debug.get_llm_inputs_outputs()
print(event_pairs[0][1].payload["formatted_prompt"])

运行代码后,在输出中可以找到类似下面的内容:

**********
Trace: query|_query ->  33.425664 seconds|_synthesize ->  33.403238 seconds|_templating ->  2e-05 seconds|_llm ->  7.425154 seconds|_templating ->  2.5e-05 seconds|_llm ->  4.763223 seconds|_templating ->  2.4e-05 seconds|_llm ->  6.601226 seconds|_templating ->  2.2e-05 seconds|_llm ->  6.878335 seconds|_templating ->  2.2e-05 seconds|_llm ->  7.726241 seconds
**********

可以看出,我们将response synthesizer由默认的Compact替换为Refine之后,query在程序过程中经历的阶段发生了变化,REFINE模式会进行更多次的templating和LLM调用。

构建的新Query如下所示,这与之前是一样的:

[INST]<<SYS>>
You are a helpful AI assistant.<</SYS>>Context information is below.
---------------------
file_path: document/中医临床诊疗术语证候.txt临床以干咳、痰少,或痰中带血,口渴,鼻咽燥痛,声音嘶哑,肌肤枯燥,舌质红而干,舌苔少,脉虚数,伴见低热,神疲、乏力,语声低微,盗汗,大便干结等为特征的证候。5.4.1.5.1.1肺燥津伤证  syndrome/pattern of lung dryness with fluid damage肺燥津亏证因燥邪袭肺,津液亏虚,肺燥失润所致。临床以干咳、少痰,咽干,口燥,鼻燥,喉痒,舌质红,舌苔少津,脉浮细数等为特征的证候。5.4.1.5.1.2肺燥伤阴证  syndrome/pattern of lung dryness damaging yin因肺热化燥,伤及阴津所致。临床以咳嗽,痰少或无,痰黄而黏,口干、咽燥,烦渴、多饮,小便短少,舌质红,舌苔焦黄,脉弦数,可伴见潮热、颧红等为特征的证候。5.4.1.5.1.3肺燥阴虚证  syndrome/pattern of lung dryness with yin deficiency阴虚肺燥证因阴液亏虚,肺燥失润所致。临床以午后潮热,干咳、痰少,喉痒、鼻燥、少涕,咽干、烦渴,消瘦,舌质红,舌苔少,脉细数,伴见盗汗浸衣,心烦、失眠等为特征的证候。5.4.1.5.2肺燥郁热证  syndrome/pattern of lung dryness with stagnated heat肺燥化热证因忧劳伤肺,郁热化燥,伤及肺津所致。临床以发热、烦渴,咳嗽、痰少而黏,胸胁灼痛,大便干结,小便短少,舌质红而干,舌苔薄黄,脉弦数等为特征的证候。5.4.1.6肺经证  syndrome/pattern of lung meridian (vessel)泛指因各种原因致使肺经循行部位异常所引起的一类证候。5.4.1.6.1肺经风热证  syndrome/pattern of wind and heat in the lung meridian因风热邪客肺经,或风热郁滞肤腠,外发于头面所致。
---------------------
Given the context information and not prior knowledge, answer the query.
Query: 不耐疲劳,口燥、咽干可能是哪些证候?
Answer: [/INST] 

另外,由于我们使用了SimilarityPostprocessor的retriever,并将相似度阈值设置为0.6,因此检索出的相似度小于0.6的文档片段会被摘除。

最后,我们看一下模型的回复:

从中医角度看,不耐疲劳、口燥、咽干的症状可能涉及多个证候,如燥邪犯肺证(4.6.3.3),由于燥气耗伤肺津;津亏热结证(4.6.3.2)或津枯肠结证(4.6.3.3),表现为体内津液亏损且伴有热象,导致口干、便秘等;肺胃阴虚证(5.6.4.4.2.2)和心肾阴虚(5.1.1.1.1),特别是心肾不交时,也会出现类似症状。此外,心系证中的心寒证(5.1.1.1)如心中寒证也可能表现出口干咽燥。具体诊断需根据临床表现、体质和相关检查结果来确定。

从上面的案例可以看出,我们可以自由组合不同的retriever和response synthesizer,以完成我们的需求。当LlamaIndex提供的

retriever和response synthesizer不能满足我们的需求的时候,我们还可以自定义retriever和response synthesizer,有兴趣的读者可以自行探索。

最后的最后

感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你。

因为这个行业不同于其他行业,知识体系实在是过于庞大,知识更新也非常快。作为一个普通人,无法全部学完,所以我们在提升技术的时候,首先需要明确一个目标,然后制定好完整的计划,同时找到好的学习方法,这样才能更快的提升自己。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

五、面试资料

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下。
在这里插入图片描述

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

这篇关于RAG实战4-RAG过程中发生了什么?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1054030

相关文章

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

oracle 11g导入\导出(expdp impdp)之导入过程

《oracle11g导入导出(expdpimpdp)之导入过程》导出需使用SEC.DMP格式,无分号;建立expdir目录(E:/exp)并确保存在;导入在cmd下执行,需sys用户权限;若需修... 目录准备文件导入(impdp)1、建立directory2、导入语句 3、更改密码总结上一个环节,我们讲了

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Java Kafka消费者实现过程

《JavaKafka消费者实现过程》Kafka消费者通过KafkaConsumer类实现,核心机制包括偏移量管理、消费者组协调、批量拉取消息及多线程处理,手动提交offset确保数据可靠性,自动提交... 目录基础KafkaConsumer类分析关键代码与核心算法2.1 订阅与分区分配2.2 拉取消息2.3

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶