懒懒笔记 | 课代表带你梳理【RAG 课程 6&7:评测、召回优化与多路检索】
距 RAG 系列课程上线已两周,不知道大家的进度如何?
前五讲里,志宏老师带我们搞懂了什么是 RAG、如何快速上手 LazyLLM,还示范了项目工程化与自定义 Reader 的实现。然而在学习群里,问题接踵而至:
🙋♂️“召回率太低,想要的内容找不回来...”
🙋♂️“模型经常答非所问,怎么破?”
可见,掌握基础并不等于拥有一套高性能、企业级 RAG 系统。第 6、7 讲 正是为此而来——聚焦效果评测与效果优化。
本贴心小编已为你把干货浓缩成精华
一起来看看
如何评测RAG系统的效果?
Why-为什么做评测?
📌量化→迭代;对齐产品指标
📌系统性多指标分析,助力系统稳步优化
What-评测维度有哪些?
RAG系统主要有检索和生成两大阶段👇
📌检索组件评估(Retrieval)
-
召回率(Recall):检索出的相关文档占所有文档比例,Recall=TP/(TP+FN)
-
上下文相关性(Context Relevance):更细粒度,CR=与查询相关的句子总数/召回文档中的句子总数
📌生成组件评估(Generation)
-
忠诚度(Faithfulness):生成答案是否严格遵循给定上下文(对抗模型幻觉)
-
答案相关性(Answer Relevance):生成答案是否准确响应问题
🚨注意:部分评测方法依赖LLM参与
How-实施步骤
Step1:
构建评测集。
Step2:
用LazyLLM封装的组件,例如LLMContextRecall()、ContextRelevance()、Faithfulness()等。
Step3:
获得评测结果,分析并进行系统迭代。
RAG系统的效果往往取决于四个维度
实践举例
运行代码:
import lazyllm from lazyllm.tools.eval import LLMContextRecall, ContextRelevance data = [{'question': '非洲的猴面包树果实的长度约是多少厘米?', 'answer': '非洲猴面包树的果实长约15至20厘米。', 'context_retrieved': ['非洲猴面包树是一种锦葵科猴面包树属的大型落叶乔木,原产于热带非洲,它的果实长约15至20厘米。', '钙含量比菠菜高50%以上,含较高的抗氧化成分。',], 'context_reference': ['非洲猴面包树是一种锦葵科猴面包树属的大型落叶乔木,原产于热带非洲,它的果实长约15至20厘米。'] }] # 初始化基于LLM的召回率评估器 m_lcr = LLMContextRecall(lazyllm.OnlineChatModule()) res_m_lcr = m_lcr(data) # 初始化上下文相关性评估器 m_cr = ContextRelevance() res_m_cr = m_cr(data) # 0.5 print(f"recall: {res_m_lcr}, context relevance: {res_m_cr}")
运行结果:
测试召回率得分1.0,上下文相关性得分0.5
如何提升RAG系统的召回率?
为什么要提升召回率?
如图,“RAG的效果,重点在R”,准确的知识召回是RAG系统效果的基础。
优化召回有哪些具体策略?
检索前-优化方向:查询重写
📌扩写查询:补充或优化原始查询,使查询更清晰。
-
同义词扩展
-
上下文补充
-
问题模板转换
📌子问题查询:将查询拆解为多个更具体的子问题,通常用于抽象问题。
-
例如原始问题“RAG是什么?”,⼦查询分解: “RAG的定义是什么?”,“RAG的特点是什么?”,“RAG的原理是什么?”等
-
策略会增加系统开销
📌多步骤查询:层层递进的子问题,适用于需要多轮推理或信息串联的场景。
检索时-优化方向:检索优化策略
📌构造节点组(node group)
-
基于分块的策略
🗝️固定大小分块(例如LazyLLM预置的"CoarseChunk", "MediumChunk", "FineChunk"节点组):固定token数量
🗝️递归分块:优先按段落分块,超长则进一步分块,保留语义连贯性
🗝️语义分块:基于语义向量,按照语义单元分割。
🗝️基于文档分块:按照文档自然划分(标题或章节),仅适用于结构化文档。
-
基于语义提取的策略
🗝️关键词节点组
🗝️摘要节点组
🗝️预置QA对节点组:通过构建标准化的问答对,可直接提供完整答案,提升响应效率和体验。
📌使用向量化(Embedding),实现语义相似度检索。
-
原理:使用Embedding模型将用户查询和文档段落转换为高维向量,通过相似度计算(如余弦相似度)筛选距离相近的向量,获取对应文档信息。
-
分类
🗝️稠密向量(Dense Vector):多数元素非零,支持同义词识别和语境理解,但计算开销大,且对文本细节把握弱。
🗝️稀疏向量(Sparse Vector):维度通常等于词表大小,更好保留词级细节。
🗝️相似度计算方法
🗝️内积
🗝️Cosine(向量常用):搭配摘要等概括内容效果更有,即使措辞不同,也能捕捉语义关联性
🗝️BM25(不依赖embedding,直接衡量⽂本匹配程度):更适合原文段落,精准匹配查询当中的关键词
检索后-优化方向:重排序 Reranker
📌原理:先⽤检索器初筛⽂档,再⽤更强模型重排序提升准确率。
📌两阶段检索策略:
-
Retriever负责初筛,从海量文档中筛选候选文档,筛选数量多,速度快,但精度低。
-
Reranker负责对候选文档精排,总体实现“先快后精”,兼顾效率与效果。
整体框架综合优化-优化方向:多路召回策略
📌思路:设置多个检索器在不同粒度进行检索或使用不同的相似度计算方法进行文档召回,对所有检索器召回的文档进行排序得到最终上下文。
📌常用方法:
-
不同粒度的检索器:如原文分块+文档摘要/问答对
-
不同相似度计算方法:如向量+BM25混合检索
实践举例:
📌查询重写:编写对应功能的prompt,使用llm组件接收用户查询,输出重写后的查询。例如子问题查询:
from lazyllm import OnlineChatModule, ChatPrompter, deploy # prompt设计 rewrite_prompt = "你是一个查询重写助手,将用户查询分解为多个角度的具体问题。\ 注意,你不需要对问题进行回答,只需要根据问题的字面意思进行子问题拆分,输出不要超过 3 条.\ 下面是一个简单的例子:\ 输入:RAG是什么?\ 输出:RAG的定义是什么?\ RAG是什么领域内的名词?\ RAG有什么特点?\ \ 用户输入为:" llm = OnlineChatModule() # 调用大模型 query_rewriter = llm.share(ChatPrompter(instruction=rewrite_prompt)) # 通过 llm.share 复用大模型 query = "MIT OpenCourseWare是啥?" queries = query_rewriter(query) # 执行查询重写 queries_list = queries.split('\n') print(f"原查询:{query}\n重写后的查询:{queries_list}")
运行结果:
程序将查询拆分成多个子查询
📌创建节点组:Document中使用create_node_group方法,并将分块策略传入'transform'参数当中。对于语义提取策略,transform可直接使用lazyllm.LLMParser。例如创建摘要节点组:
import lazyllm llm = lazyllm.OnlineChatModule(source="qwen") summary_llm = lazyllm.LLMParser(llm, language="zh", task_type="summary") docs = lazyllm.Document("test_parse") # 初始化文档对象 # 注册摘要节点组 docs.create_node_group(name='summary', transform=summary_llm, trans_node=True, parent='CoarseChunk’)
📌在RAG中使用Embedding和Reranker:
from lazyllm import Document, Retriever, Reranker, OnlineEmbeddingModule # 如果您要使用在线重排模型,请指定相应的 API key。 online_embed = OnlineEmbeddingModule(source='doubao') online_rerank = OnlineEmbeddingModule(source='qwen', type="rerank") docs = Document("/LazyTutorial/test1", embed=online_embed) # 定义检索器 retriever = Retriever(docs, group_name="MediumChunk", similarity="cosine", topk=3) # 定义重排器,指定输出为字符串,并进行串联,未进行串联时输出为字符串列表 reranker = Reranker('ModuleReranker', model=online_rerank, topk=3) query = "证券管理年龄相关的限制?" result1 = retriever(query=query) result2 = reranker(result1, query=query) print("检索器结果:") print("\n\n".join([res.get_content() for res in result1])) print("==="*20) print("重排器结果:") print("\n\n".join([res.get_content() for res in result2]))
运行结果:
📌多路召回,综合优化后的RAG系统:
import lazyllm from lazyllm import bind rewriter_prompt = "你是一个查询重写助手,负责给用户查询进行模板切换。\ 注意,你不需要进行回答,只需要对问题进行重写,使更容易进行检索\ 下面是一个简单的例子:\ 输入:RAG是啥?\ 输出:RAG的定义是什么?" rag_prompt = 'You will play the role of an AI Q&A assistant and complete a dialogue task.'\ ' In this task, you need to provide your answer based on the given context and question.' # 定义嵌入模型和重排序模型 online_embed = lazyllm.OnlineEmbeddingModule(source='doubao') online_rerank = lazyllm.OnlineEmbeddingModule(source='qwen', type="rerank") llm = lazyllm.OnlineChatModule(source='qwen') qa_parser = lazyllm.LLMParser(llm, language="zh", task_type="qa") docs = lazyllm.Document("/LazyTutorial/test1", embed=online_embed) # 创建按行拆分以及QA对节点组 docs.create_node_group(name='block', transform=(lambda d: d.split('\n'))) docs.create_node_group(name='qapair', transform=qa_parser) def retrieve_and_rerank(): with lazyllm.pipeline() as ppl: with lazyllm.parallel().sum as ppl.prl: # 多路召回(不同分块) ppl.prl.retriever1 = lazyllm.Retriever(doc=docs, group_name="CoarseChunk", similarity="cosine", topk=3) ppl.prl.retriever2 = lazyllm.Retriever(doc=docs, group_name="block", similarity="bm25_chinese", topk=3) ppl.reranker = lazyllm.Reranker("ModuleReranker", model=online_rerank, topk=3) | bind(query=ppl.input) return ppl with lazyllm.pipeline() as ppl: ppl.query_rewriter = llm.share(lazyllm.ChatPrompter(instruction=rewriter_prompt)) with lazyllm.parallel().sum as ppl.prl: # 多路召回(分块检索与QA对检索) ppl.prl.retrieve_rerank = retrieve_and_rerank() ppl.prl.qa_retrieve = lazyllm.Retriever(doc=docs, group_name="qapair", similarity="cosine", topk=3) ppl.formatter = ( lambda nodes, query: dict( context_str='\n'.join([node.get_content() for node in nodes]), query=query) ) | bind(query=ppl.input) ppl.llm = llm.share(lazyllm.ChatPrompter(instruction=rag_prompt, extra_keys=['context_str'])) lazyllm.WebModule(ppl, port=23491).start().wait()
运行结果:
今天,我们先用评测指标给RAG系统把脉,再用 召回优化策略对症下药。至此,你已具备打造企业级高性能RAG的部分关键技能啦~
现在就动手实践一番,提升你的RAG系统吧!欢迎各位同学晒结果、提疑惑,一起交流RAG的学习心得~

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
当LLM重构操作系统生态:下一代智能基础设施的技术革命来了!
当 LLM 开始解析 rpm 构建脚本生成兼容性补丁,当 DeepSeek R1模型实时生成内核级运维指令——操作系统开发正经历智能化重构。5月24日,华东师范大学逸夫楼,OSC 源创会将带你探索 LLM 与操作系统的双向赋能机制。 核心亮点 🔥 五大硬核技术议题直击前沿: 1⃣ 《计算机科学之美》作者李昌龙教授揭秘 AI 时代操作系统生态重构 2⃣ FydeOS 创始人唐文松揭秘 FydeOS 与 LLM 协同进化时所做过的尝试 3⃣ 腾讯 OpenCloudOS 团队展示 LLM 赋能操作系统开发的黑科技 4⃣ 阿里云 Mooncake 大模型开源生态体系建设与产业应用实践 5⃣ 百度 飞桨硬件生态负责人深度解读端侧 OS 与 AI 框架融合 💡 技术人必看的创新突破 内核级提示工程如何重写系统调用规则 大模型驱动的智能运维体系实战解析 实时推理加速框架与操作系统的深度集成 KVCache 中心化推理架构技术细节 自研 OS 智能助手实现中文指令秒级响应 🎁 参会即享三重福利: ① 与头部企业技术负责人面对面交流 ② 参与互动抽奖赢取开发者大礼包 ③ 源创会传统披萨美味茶歇...
- 下一篇
SnailJob 1.5.0 发布,分布式任务调度平台
🔥🔥🔥 灵活,可靠和快速的分布式任务重试和分布式任务调度平台 ✅️ 可重放,可管控、为提高分布式业务系统一致性的分布式任务重试平台 ✅️ 支持秒级、可中断、可编排的高性能分布式任务调度平台 项目特性 易用性业务接入成本小。避免依赖研发人员的技术水平,保障稳定性 灵活性能够动态调整配置,启动 / 停止任务,以及终止运行中的任务 操作简单分钟上手,支持 WEB 页面对任务数据 CRUD 操作。 数据大盘实时管控系统任务数据 分布式重试任务支持多样化退避策略、多样化重试类型、流量管控等 分布式调度任务提供丰富的任务触发策略、任务分片、停止恢复、失败重试等 工作流任务编排仿钉钉设计的流程编排引擎,支持复杂的功能编排、失败重试、告警等 任务数据管理可以做到数据不丢失、数据一键回放 容器化部署服务端支持 docker 容器部署 高性能调度平台支持服务端节点动态扩容和缩容 支持多样化的告警方式邮箱、企业微信、钉钉、飞书、自定义告警 支持多种流行数据库mysql、mariadb、sqlserver、oracle、postgres 数据库 开源组件对比 项目 Quartz Elastic-Job ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Mario游戏-低调大师作品
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题