大语言模型(LLM)之更好的搜索增强生成(RAG)方案——RAG-Fusion,一文讲清!!

大语言模型(LLM)之更好的搜索增强生成(RAG)方案——RAG-Fusion,一文讲清!! 前言检索增强生成RAG的兴起改变了 AI 和搜索领域的范式通过将向量搜索与生成模型的力量融合在一起。然而这项技术并非没有局限性。所谓搜索增强生成首先必须有搜索这一步而搜索这一步有很多难点向量召回准确率的提升很难所以一般会考虑传统的BM25搜索和向量搜索一起进行搜索。但有时候依然效果不好自己想要的没被召回来。这时候我们来借鉴一下传统的搜索技术看看有什么可以进行优化的。在真正的搜索之前其实有 查询词处理与文本理解 这一步其涉及到很多NLP技术比如分词NER同义词词权重意图识别查询词的改写等一系列的NLP任务。这样可以丰富搜索信息让搜索更加准确。我们可不可以借用大模型去优化 查询词处理与文本理解 这一重要步骤呢。接下来笔者介绍的RAG-FUSE 就是利用大模型对query进行改写丰富了搜索信息。所以其实当RAG效果不好时在query预处理上做文章也能收到效果。RAG-Fusion方案RAG-fusion 方案其实简单来说就是使用 LLM 将 用户原始查询 改写成N个不同的查询然后分别进行检索最终汇众多路检索的结果进行重新排列以选择最相关的答案。主要流程如下图所示查询生成/改写使用 LLM 模型对用户的初始查询进行改写生成多个查询。向量搜索对每个生成的查询进行基于向量的搜索形成多路搜索召回。倒数排序融合RRF应用倒数排名融合算法根据文档在多个查询中的相关性重新排列文档。重排: 使用更高精度的排序模型对上一步RRF排序结果进行重排。输出生成然后可以参考重新排列后的TOPK搜索结果生成最终输出。RAG-Fusion倒数排序融合 Reciprocal rank fusion (RRF)RRF一个将各个不同的召回路中序列进行融合排序的方案。混排公式如下RRFD - 文档集R - 文档在某路召回路的排名K - 通常默认设置为 60一言以蔽之就是将文档在每个序列中 排名的倒数是相加 作为最终的排序得分然后倒序排列。这个公式主要是想衡量一个文档是不是在N个序列中都排在前面如果在每一个召回序列中都排在前面在混合过程中也将它排在前面。比如下图是一个搜索query,通过三种不同的召回方式进行了搜索召回1.title的BM25得分2.content的BM25得分3.语义相似性得分这3路召回中每路召回的序列都不一样然后对这3个序列进行混合的案例 其中docment-2在3个序列中分别排在132。综合得分 1/1 1/3 1/2 1.83RAG-Fusion实战这里的代码来自于https://github.com/Raudaschl/rag-fusion整个流程就是查询改写—多路搜索召回内部逻辑没实现—倒数排序融合—结果输出。并没有重排步骤以及基于搜索结果的生成过程。importosimportopenai# 导入 openai 库importrandom# 导入 random 库# 初始化 OpenAI APIopenai.api_keyos.getenv(OPENAI_API_KEY)# 从环境变量中获取 OpenAI API 密钥也可以直接在 main.py 中设置ifopenai.api_keyisNone:# 如果没有找到 OpenAI API 密钥抛出异常raiseException(No OpenAI API key found. Please set it as an environment variable or in main.py)# 定义一个函数使用 OpenAI 的 ChatGPT 模型来生成多个查询defgenerate_queries_chatgpt(original_query):responseopenai.ChatCompletion.create(# 调用 OpenAI 的 ChatCompletion 接口创建一个聊天对话modelgpt-3.5-turbo,# 使用 gpt-3.5-turbo 模型messages[# 设置聊天消息{role:system,content:You are a helpful assistant that generates multiple search queries based on a single input query.},# 系统角色的消息介绍自己的功能{role:user,content:fGenerate multiple search queries related to:{original_query}},# 用户角色的消息输入一个原始查询{role:user,content:OUTPUT (4 queries):}# 用户角色的消息指定输出的查询个数])generated_queriesresponse.choices[0][message][content].strip().split(\\n)# 从响应中获取生成的查询去掉首尾空格按换行符分割returngenerated_queries# 返回生成的查询# 定义一个模拟函数用于模拟向量搜索返回随机的分数defvector_search(query,all_documents):available_docslist(all_documents.keys())# 获取所有文档的键文档名random.shuffle(available_docs)# 随机打乱文档的顺序selected_docsavailable_docs[:random.randint(2,5)]# 随机选择 2 到 5 个文档作为搜索结果scores{doc:round(random.uniform(0.7,0.9),2)fordocinselected_docs}# 为每个文档生成一个 0.7 到 0.9 之间的随机分数保留两位小数return{doc:scorefordoc,scoreinsorted(scores.items(),keylambdax:x[1],reverseTrue)}# 按分数降序排序返回文档和分数的字典# 定义一个函数实现互换排名融合算法defreciprocal_rank_fusion(search_results_dict,k60):fused_scores{}# 创建一个空字典用于存储融合后的分数print(Initial individual search result ranks:)# 打印初始的各个查询的搜索结果排名forquery,doc_scoresinsearch_results_dict.items():# 遍历每个查询和对应的文档分数print(fFor query {query}:{doc_scores})# 打印每个查询和对应的文档分数forquery,doc_scoresinsearch_results_dict.items():# 再次遍历每个查询和对应的文档分数forrank,(doc,score)inenumerate(sorted(doc_scores.items(),keylambdax:x[1],reverseTrue)):# 按分数降序排序遍历每个文档和对应的排名ifdocnotinfused_scores:# 如果文档不在融合分数的字典中fused_scores[doc]0# 初始化文档的融合分数为 0previous_scorefused_scores[doc]# 获取文档的之前的融合分数fused_scores[doc]1/(rankk)# 根据互换排名融合算法更新文档的融合分数print(fUpdating score for{doc}from{previous_score}to{fused_scores[doc]}based on rank{rank}in query {query})# 打印更新文档分数的过程reranked_results{doc:scorefordoc,scoreinsorted(fused_scores.items(),keylambdax:x[1],reverseTrue)}# 按融合分数降序排序返回重新排名的结果print(Final reranked results:,reranked_results)# 打印最终的重新排名的结果returnreranked_results# 返回重新排名的结果# 定义一个模拟函数用于模拟生成输出defgenerate_output(reranked_results,queries):returnfFinal output based on{queries}and reranked documents:{list(reranked_results.keys())}# 返回一个字符串包含生成的查询和重新排名的文档# 预定义的文档集合通常这些文档会来自搜索数据库all_documents{doc1:Climate change and economic impact.,doc2:Public health concerns due to climate change.,doc3:Climate change: A social perspective.,doc4:Technological solutions to climate change.,doc5:Policy changes needed to combat climate change.,doc6:Climate change and its impact on biodiversity.,doc7:Climate change: The science and models.,doc8:Global warming: A subset of climate change.,doc9:How climate change affects daily weather.,doc10:The history of climate change activism.}# 主函数if__name____main__:original_queryimpact of climate change# 设置原始查询为“影响气候变化”generated_queriesgenerate_queries_chatgpt(original_query)# 调用 generate_queries_chatgpt 函数生成多个查询all_results{}# 创建一个空字典用于存储所有查询的搜索结果forqueryingenerated_queries:# 遍历每个生成的查询search_resultsvector_search(query,all_documents)# 调用 vector_search 函数对每个查询进行向量搜索all_results[query]search_results# 将每个查询的搜索结果存入字典reranked_resultsreciprocal_rank_fusion(all_results)# 调用 reciprocal_rank_fusion 函数对所有查询的搜索结果进行互换排名融合final_outputgenerate_output(reranked_results,generated_queries)# 调用 generate_output 函数生成最终的输出print(final_output)# 打印最终的输出结语当然这样利用大模型去进行搜索query改写虽然能够带来更丰富的搜索信息但是性能上会受到损失产品上的设计一定要考虑这一点。最后为什么要学AI大模型当下⼈⼯智能市场迎来了爆发期并逐渐进⼊以⼈⼯通⽤智能AGI为主导的新时代。企业纷纷官宣“ AI ”战略为新兴技术⼈才创造丰富的就业机会⼈才缺⼝将达 400 万DeepSeek问世以来生成式AI和大模型技术爆发式增长让很多岗位重新成了炙手可热的新星岗位薪资远超很多后端岗位在程序员中稳居前列。与此同时AI与各行各业深度融合飞速发展成为炙手可热的新风口企业非常需要了解AI、懂AI、会用AI的员工纷纷开出高薪招聘AI大模型相关岗位。最近很多程序员朋友都已经学习或者准备学习 AI 大模型后台也经常会有小伙伴咨询学习路线和学习资料我特别拜托北京清华大学学士和美国加州理工学院博士学位的鲁为民老师给大家这里给大家准备了一份涵盖了AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频全系列的学习资料这些学习资料不仅深入浅出而且非常实用让大家系统而高效地掌握AI大模型的各个知识点。这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】AI大模型系统学习路线在面对AI大模型开发领域的复杂与深入精准学习显得尤为重要。一份系统的技术路线图不仅能够帮助开发者清晰地了解从入门到精通所需掌握的知识点还能提供一条高效、有序的学习路径。但知道是一回事做又是另一回事初学者最常遇到的问题主要是理论知识缺乏、资源和工具的限制、模型理解和调试的复杂性在这基础上找到高质量的学习资源不浪费时间、不走弯路又是重中之重。AI大模型入门到实战的视频教程项目包看视频学习是一种高效、直观、灵活且富有吸引力的学习方式可以更直观地展示过程能有效提升学习兴趣和理解力是现在获取知识的重要途径光学理论是没用的要学会跟着一起敲要动手实操才能将自己的所学运用到实际当中去这时候可以搞点实战案例来学习。海量AI大模型必读的经典书籍PDF阅读AI大模型经典书籍可以帮助读者提高技术水平开拓视野掌握核心技术提高解决问题的能力同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说阅读经典书籍是非常有必要的。600AI大模型报告实时更新这套包含640份报告的合集涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师还是对AI大模型感兴趣的爱好者这套报告合集都将为您提供宝贵的信息和启示。AI大模型面试真题答案解析我们学习AI大模型必然是想找到高薪的工作下面这些面试题都是总结当前最新、最热、最高频的面试题并且每道题都有详细的答案面试前刷完这套面试题资料小小offer不在话下这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】