RAG的流程

宏观上看RAG的过程分为以下6个部分:

上传、分块、向量化、索引、检索、生成
他们又分为两个阶段。

一、准备阶段(离线做一次)

上传

这一步需要把各种格式的文档(txt、docx、pdf)解析成干净的纯文本

分块

根据文档不同的类型选择不同的分块策略把长文档切成小块。

因为:

  1. 大模型上下文窗口有限
  2. 一次检索只需要文档中的一部分,塞入大量无关文本反而影响模型生成内容的质量
向量化

调用embedding模型把chunk文本向量化。

通过向量去匹配语义,语义越相近的两段文本在向量空间中距离越近。

索引

把向量存储到向量数据库中并建立索引,供后续检索使用。

二、运行阶段(每次都执行)

检索

把用户提的问题向量化后去数据库匹配相似的n条chunk

(检索阶段还有很多细节,后文继续讨论)

生成

把检索到的文本和systempormpt、用户问题拼接起来一并发送给LLM生成回答。

检索在后端经过的几个阶段

深入项目后,检索阶段内部也分为几个阶段:

1. 加载对话历史

如果系统需要支持多轮对话,就需要引入对话历史,否则 LLM 无法获得之前对话中的上下文信息。关键是上下文窗口是有限的,不能把所有历史都无脑塞进去,常见的策略有:

  1. 滑动窗口

    只保留最近的n轮对话,缺点:可能在开局给LLM交代了一些重要内容,经过n轮的对话后它丢失了最开始的重要信息

  2. 滑动窗口 + 摘要压缩

    这是对方案1的优化,同样保留最近的n轮对话,并且对于滑出窗口的对话进行压缩,保留核心的内容

    缺点:调用LLM压缩产生额外的成本,且增加接口响应时间

2. 问题重写和拆分

问题重写主要是去掉问题中的代词,例如:

​ 第一轮,用户:iphone15的保修策略是什么?

​ 第一轮,LLM:xxxxxxxxxx

​ 第二轮,用户:那它的退货政策是什么?

问题就出在这个“它”上,大模型可以理解语义,对照上下文知道这里的它指的是iphone15。

但如果直接用“它”去检索,可能检索到的是“macbook的退货政策”。

再来看问题拆分:

​ 用户:airport的退货流程和保修策略什么?

退货流程和保修策略在不同位置,不同chunk,一起检索的话会导致得分不高,可能影响检索效果。

对于包含多个独立意图的问题,将问题拆分后分别检索,通常可以提高召回结果与各个子问题的相关性,且意图识别需要对每个子问题分析

3. 意图识别

用户的问题不一定都是需要到知识库检索的,假如随手问个hi,直接让LLM回答就好了,检索反而多此一举;

再比如问“我的年假还有几天?”,系统内部的数据需要调用工具(或MCP)获取数据,到知识库检索反而导致内容错误。

意图的识别也是通过LLM打分来做的。

4. 歧义引导【短路点】

用户问的问题可能太模糊了,有歧义,与其随便检索一个相关性不高的答案,不如引导用户来澄清,在下一次对话中通过问题重写得到精确的问题。

​ 用户:保修政策是什么?

​ 系统引导:您说的是iphone的还是airport或是其他?

5. 系统直答【短路点】

当意图识别到为系统直达后就不需要走后续的流程了,提前结束,直接让LLM回答。

6. 多通道检索

根据意图分别到知识库检索和mcp工具调用(并行),最终将结果合并到一起。

7. 空结果处理

如果没有检索到结果,不要让LLM随意发挥,直接告诉用户“未检索到与问题相关的内容”,不然大模型基于自己训练的数据回答和实际的情况大相径庭,对用户来说完全是误导,不可接受。

8. 拼接prompt流式生成

可能根据不同场景调整参数,例如kb检索时需要稳定,可以把temperature调成0严格按照检索到的上下文回答,调用工具时允许一定程度的发挥temperature=0.3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值