news 2026/5/5 22:43:06

RAG检索优化秘籍:问题分解实现多步推理,复杂查询轻松应对!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RAG检索优化秘籍:问题分解实现多步推理,复杂查询轻松应对!

二、问题分解

2.1 简介

问题分解 (Query Decomposition)是指将一个内容较为复杂或结构多层的提问(即主任务),拆分为若干个相对简单、易于处理的子问题(即子任务)。这一思路与人类处理复杂问题时的惯用方式类似:先分步解决各个小环节,再整合得出最终结论。

在 RAG 应用中,该方法能够有效规避因问题过于宽泛和笼统而导致的检索偏差,从而提升对复杂查询的整体应答质量。

2.2 核心思想

其核心理念可概括为“分步拆解”与“层层递进”:

  • 化繁为简:复杂的提问通常对应知识库中多个分散的信息点。通过将问题拆解,使每一次检索的目标更加清晰具体。
  • 逻辑窜联:部分提问需要先了解前提问题(A),才能回答后续问题(B)。分解有助于理清这种先后依赖关系。
  • 整合输出:将多个局部信息汇总融合,最终形成一个完整且具有深度的综合性答案。

2.3 实现原理

A. 串行执行 (Sequential/Chain of Thought)

该模式下,各子任务之间存在

逻辑先后关系:

  1. 分解阶段:大语言模型将原始问题拆分为若干个存在依赖关系的子问题(如:子问题1、子问题2……子问题N)。
  2. **逐步执行:**先处理“子问题1”,获得对应的答案内容“答案1”。
  3. **信息传递:**将“答案1”作为提示词(Prompt),并与“子问题2”一起输入模型。
  4. **递进处理:**模型在回答后续子问题时,能够借助之前已获取的信息进行推理。
  • 适用场景:适用于需要多步推理的任务。例如提问“梁文锋创立的公司现在市值多少?”——需先确定该公司为宇树科技,再进一步查询其市值。

B. 并行执行 (Parallel/Multi-Query)

该模式下,各子任务之间

相对独立,无先后依赖:

  1. 分解阶段:大语言模型将原始问题拆分为多维度的多个彼此不干扰的子问题。
  2. **并发处理:**将所有子问题同时提交给检索系统,并为每个子问题分别获取对应的“局部结果”。
  3. **结果整合 (Aggregation):**最后再由大语言模型将所有局部结果汇总,生成最终的综合性回答。
  • **适用场景:**适用于对比分析或综合类问题。例如提问“对比 苹果手机 和 华为手机的优缺点”——可拆分为“苹果手机的优缺点”和“华为手机的优缺点”两个独立子任务并行处理。

2.4 优势

问题分解 (Decomposition)使得 RAG 从原本简单的“提问—回答”模式,升级为具备“任务处理”能力的系统。它借助大语言模型的规划机制,将一个难以直接跨越的复杂问题,拆解为多个易于执行的小步骤,从而逐步完成整体解答。

三、问题分解实现方式

3.1 数据准备

此处,选用番茄炒蛋的制作教程数据作为示例,将数据切分成如下三块:

from langchain_core.documents import Documentfrom langchain_chroma import Chroma# 假设切分过的数据documents = [ Document(page_content="番茄炒蛋的食材:\n\n- 新鲜鸡蛋:3-4个(根据人数调整)\n- 番茄:2-3个中等大小\n- 盐:适量\n- 白糖:一小勺(可选,用于提鲜)\n- 食用油:适量\n- 葱花:少许(可选,用于增香)\n\n这些是最基本的材料,当然也可以根据个人口味添加其他调料或配料。"), Document(page_content="番茄炒蛋的步骤:鸡蛋打入碗中,加入少许盐,用筷子或打蛋器充分搅拌均匀;\n - 番茄洗净后切成小块备用。\n\n3. **炒鸡蛋**:锅内倒入适量食用油加热至温热状态,然后将搅拌好的鸡蛋液缓缓倒入锅中。待鸡蛋凝固时轻轻翻动几下,让其受热均匀直至完全熟透,随后盛出备用。\n\n4. **炒番茄**:在同一锅里留下的底油中放入切好的番茄块,中小火慢慢翻炒至出汁,可根据个人口味加一点点白糖提鲜。\n\n5. **合炒**:当番茄炒至软烂并开始释放大量汤汁时,再把之前炒好的鸡蛋倒回锅里,快速与番茄混合均匀,同时加入适量的盐调味。如果喜欢的话还可以撒上一些葱花增加香气。\n\n6. **完成**:最后检查一下味道是否合适,确认无误后即可关火装盘享用美味的番茄炒蛋啦!"), Document(page_content="技巧与注意事项:1. **选材**:选择新鲜的鸡蛋和成熟的番茄。新鲜的食材是做好这道菜的基础。\n2. **打蛋液**:将鸡蛋打入碗中后加入少许盐(根据个人口味调整),然后充分搅拌均匀。这样做可以让蛋更加松软且味道更佳。\n3. **处理番茄**:番茄最好先用开水稍微焯一下皮,然后去皮切块。这样可以去除表皮的硬质部分,让番茄更容易入味,并且口感更好。\n4. **热锅冷油**:先用中小火把锅烧热,再倒入适量食用油,待油温五成热时下蛋液。这样的做法可以使蛋快速凝固形成漂亮的形状而不易粘锅。\n5. **分步烹饪**:通常建议先炒鸡蛋至半熟状态取出备用;接着利用剩下的底油继续翻炒番茄至出汁,最后再将之前炒好的鸡蛋倒回锅里与番茄混合均匀加热即可。\n6. **调味品**:除了基本的盐之外,还可以根据喜好添加少量糖来提鲜或者一点酱油增色添香。注意调味料不宜过多以免掩盖了食材本身的味道。\n7. **出锅前加葱花**:如果喜欢的话,在即将完成时撒上一些葱花不仅能增加菜品色泽还能增添香气。") ] # 初始化向量库vectorstore = Chroma.from_documents(documents=documents, embedding=embeddings_model, collection_name="decomposition")# 初始化检索器retriever = vectorstore.as_retriever(search_kwargs={"k": 1})

先采用基础的 RAG 检索方式进行效果验证:

pretty_print_docs(retriever.invoke("番茄炒蛋怎么制作?"))

运行结果显示如下:

运行结果显示,从向量库中只检索出了制作材料,制作步骤并未被检索出来。将这样不完整的数据交给 LLM 进行整合,无法给出正确答案,因此需要采用特定的优化方案。

3.2 问题分解

首先将用户提问的原始问题拆解为若干个子问题,随后再分别到向量库中进行检索:

from langchain.retrievers.multi_query import LineListOutputParser# 设置问题拆分模版QUERY_PROMPT = PromptTemplate( input_variables=["question"], template="""你是一名AI语言模型助理。你的任务是将输入问题分解成3个子问题, 通过一个个解决这些子问题从而解决完整的问题。子问题需要在矢量数据库中检索相关文档。 通过分解用户问题生成子问题,你的目标是帮助用户克服基于距离的相似性搜索的一些局限性。 请提供这些用换行符分隔的子问题本身,不需要额外内容。原始问题: {question}""",)chain = QUERY_PROMPT | llm | LineListOutputParser()chain.invoke({"question":"番茄炒蛋怎么制作?"})

运行结果如下,成功的把用户的一个问题拆分成了三个问题:

3.3 拆分问题检索

分别对拆分的问题进行检索,代码如下:

from langchain_core.retrievers import BaseRetrieverfrom langchain_core.language_models import BaseLanguageModelfrom langchain_core.prompts import PromptTemplate,BasePromptTemplatefrom langchain.retrievers.multi_query import LineListOutputParserfrom langchain_core.callbacks import CallbackManagerForRetrieverRunfrom typing import Listfrom langchain_core.documents import Documentfrom langchain_core.runnables import Runnable,RunnableLambdaDEFAULT_QUERY_PROMPT = PromptTemplate( input_variables=["question"], template="""你是一名AI语言模型助理。你的任务是将输入问题分解成3个子问题, 通过一个个解决这些子问题从而解决完整的问题。子问题需要在矢量数据库中检索相关文档。 通过分解用户问题生成子问题,你的目标是帮助用户克服基于距离的相似性搜索的一些局限性。 请提供这些用换行符分隔的子问题本身,不需要额外内容。原始问题: {question}""", )DEFAULT_SUB_QUESTION_PROMPT = PromptTemplate( input_variables=["question", "sub_question", "documents"], template="""要解决主要问题{question},需要先解决子问题{sub_question}。以下是 为支持您的推理而提供的参考文档:{documents}。请直接给出当前子问题的答案。""",)class DecompositionQueryRetriever(BaseRetriever): # 向量数据库检索器 retriever: BaseRetriever # 生成子问题链 llm_chain: Runnable # 解决子问题链 sub_llm_chain: Runnable @classmethod def from_llm( cls, retriever: BaseRetriever, llm: BaseLanguageModel, prompt: BasePromptTemplate = DEFAULT_QUERY_PROMPT, sub_prompt:BasePromptTemplate = DEFAULT_SUB_QUESTION_PROMPT ) -> "DecompositionQueryRetriever": output_parser = LineListOutputParser() llm_chain = prompt | llm | output_parser sub_llm_chain = sub_prompt | llm return cls( retriever=retriever, llm_chain=llm_chain, sub_llm_chain=sub_llm_chain ) def _get_relevant_documents( self, query: str, *, run_manager: CallbackManagerForRetrieverRun, ) -> List[Document]: # 生成子问题 sub_queries = self.generate_queries(query) # 解决子问题 documents = self.retrieve_documents(query,sub_queries) return documents def generate_queries(self, question: str) -> List[str]: response = self.llm_chain.invoke({"question": question}) lines = response print(f"Generated queries: {lines}") return lines def retrieve_documents(self,query:str, sub_queries: List[str]) -> List[Document]: sub_llm_chain = RunnableLambda( # 传入子问题,检索文档并回答 lambda sub_query: self.sub_llm_chain.invoke( { "question": query, "sub_question": sub_query, "documents": [doc.page_content for doc in self.retriever.invoke(sub_query)] } ) ) # 批量执行所有的子问题 responses = sub_llm_chain.batch(sub_queries) # 将子问题和答案合并作为解决主问题的文档 documents = [ Document(page_content=sub_query + "\n" + response.content) for sub_query, response in zip(sub_queries, responses) ] return documents # 开始检索decompositionQueryRetriever = DecompositionQueryRetriever.from_llm( llm=llm, retriever=retriever)decomposition_docs = decompositionQueryRetriever.invoke("番茄炒蛋怎么制作?")pretty_print_docs(decomposition_docs)

运行结果如下:

3.4 答案生成

将子问题检索出的结果,连同原始问题一起交给 LLM,生成最终答案:

#创建prompt模板template = """请根据以下文档回答问题:### 文档:{context}### 问题:{question}""" #由模板生成promptprompt = ChatPromptTemplate.from_template(template)chain = prompt | llm response = chain.invoke({"context":[doc.page_content for doc in decomposition_docs],"question": "番茄炒蛋怎么制作?"})print(response.content)

生成结果如下,能够准确地回答用户提出的问题:

四、总结

问题分解的核心是将复杂问题拆解为多个简单子问题分别检索,再汇总答案,使RAG具备多步推理能力。实现方式分为两种:串行执行适用于子问题存在依赖关系的场景(如“先查A再查B”),需逐步推理;并行执行适用于子问题相互独立的场景(如对比分析),可同时检索提升效率。该方法的优势在于能够应对复合查询、避免检索遗漏、提升答案完整性;但也会增加LLM调用次数,带来额外的延迟与成本开销。实践建议:对于多跳推理或综合类问题,优先采用问题分解;对于单点事实查询,直接使用基础RAG即可。

2026年AI行业最大的机会,毫无疑问就在应用层

字节跳动已有7个团队全速布局Agent

大模型岗位暴增69%,年薪破百万!

腾讯、京东、百度开放招聘技术岗,80%与AI相关……

如今,超过60%的企业都在推进AI产品落地,而真正能交付项目的大模型应用开发工程师**,**却极度稀缺!

落地AI应用绝对不是写几个prompt,调几个API就能搞定的,企业真正需要的,是能搞定这三项核心能力的人:

✅RAG:融入外部信息,修正模型输出,给模型装靠谱大脑

✅Agent智能体:让AI自主干活,通过工具调用(Tools)环境交互,多步推理完成复杂任务。比如做智能客服等等……

✅微调:针对特定任务优化,让模型适配业务

目前,脉脉上有超过1000家企业发布大模型相关岗位,人工智能岗平均月薪7.8w!实习生日薪高达4000!远超其他行业收入水平!

技术的稀缺性,才是你「值钱」的关键!

具备AI能力的程序员,比传统开发高出不止一截!有的人早就转行AI方向,拿到百万年薪!👇🏻👇🏻

AI浪潮,正在重构程序员的核心竞争力!现在入场,仍是最佳时机!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

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

⭐️从大模型微调到AI Agent智能体搭建

剖析AI技术的应用场景,用实战经验落地AI技术。从GPT到最火的开源模型,让你从容面对AI技术革新!

大模型微调

  • 掌握主流大模型(如DeepSeek、Qwen等)的微调技术,针对特定场景优化模型性能。

  • 学习如何利用领域数据(如制造、医药、金融等)进行模型定制,提升任务准确性和效率。

RAG应用开发

  • 深入理解检索增强生成(Retrieval-Augmented Generation, RAG)技术,构建高效的知识检索与生成系统。
  • 应用于垂类场景(如法律文档分析、医疗诊断辅助、金融报告生成等),实现精准信息提取与内容生成。

AI Agent智能体搭建

  • 学习如何设计和开发AI Agent,实现多任务协同、自主决策和复杂问题解决。
  • 构建垂类场景下的智能助手(如制造业中的设备故障诊断Agent、金融领域的投资分析Agent等)。

如果你也有以下诉求:

快速链接产品/业务团队,参与前沿项目

构建技术壁垒,从竞争者中脱颖而出

避开35岁裁员危险期,顺利拿下高薪岗

迭代技术水平,延长未来20年的新职业发展!

……

那这节课你一定要来听!

因为,留给普通程序员的时间真的不多了!

立即扫码,即可免费预约

「AI技术原理 + 实战应用 + 职业发展

「大模型应用开发实战公开课」

👇👇

👍🏻还有靠谱的内推机会+直聘权益!!

完课后赠送:大模型应用案例集、AI商业落地白皮书

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 22:42:49

2026程序员财富自由指南:6条AI独立开发实战路径,月入3万不是梦!

文章探讨了在AI浪潮下,程序员如何转型成为AI独立开发者,分享了6条真实可行的转型路径,包括AI工具开发、开源项目变现、AI外包接单、内容创作、AI Agent产品开发以及AI垂直行业解决方案。每条路径都提供了核心逻辑、案例参考、工具推荐、收入预…

作者头像 李华
网站建设 2026/5/5 22:42:40

我的树莓派AI助手搭建记:从下载GGML模型到配置ChatGLM聊天界面

我的树莓派AI助手搭建记:从下载GGML模型到配置ChatGLM聊天界面 去年冬天的一个深夜,我盯着书架上积灰的树莓派4B,突然萌生一个疯狂的想法——能不能让这个巴掌大的小电脑跑起来一个能聊天的AI?当时ChatGPT正火,但每次…

作者头像 李华
网站建设 2026/5/5 22:39:29

告别重复造轮子:用快马一键生成高可靠dht11驱动模块提升开发效率

在物联网开发中,温湿度传感器DHT11的使用频率非常高,但每次新项目都要从头编写驱动代码确实让人头疼。最近我在一个智能家居项目中就遇到了这个问题,好在发现了InsCode(快马)平台,它帮我快速生成了一个高可靠性的DHT11驱动模块&am…

作者头像 李华
网站建设 2026/5/5 22:37:27

通过curl命令排查taotokenapi接口调用的常见问题

通过curl命令排查Taotoken API接口调用的常见问题 1. 准备工作与环境检查 在开始排查问题前,确保已准备好以下信息:有效的Taotoken API密钥、正确的Base URL以及目标模型ID。这些信息可以在Taotoken控制台的"API密钥管理"和"模型广场&q…

作者头像 李华
网站建设 2026/5/5 22:34:32

SIMART:基于MLLM的3D模型自动关节绑定技术解析

1. 项目背景与核心价值在数字内容创作领域,将静态3D模型转化为可动关节资产一直是个耗时的手工流程。传统方法需要美术师手动拆分模型、定义关节层级、设置物理属性,整个过程可能需要数小时甚至数天。SIMART的出现彻底改变了这个工作流——它利用多模态大…

作者头像 李华