你有没有做过这样一件事——请客吃饭。客人说要来,你心想:“今晚得张罗一桌菜。”如果真把“做一桌菜”当成一个动作冲进厨房,大概率会手足无措地站在灶台前发呆:菜呢?肉呢?锅呢?火呢?真正会做饭的人会怎么做?先定菜单,再拆任务:凉菜一道、热菜两道、汤一锅、甜品一份。每一项再往下拆——买菜、洗菜、切菜、炒菜、摆盘。每一小步清清楚楚,各自执行,最后端菜上桌,一桌席面就齐了。 AI处理复杂问题也是同一个道理。当用户抛来一句“帮我比较三家云厂商在东南亚的计费规则,并推荐一家适合中小团队的主机方案”时,如果让AI直接拿这句话去检索文档库,往往会“站在灶台前发呆”——一次检索既覆盖不了所有厂商,又照顾不到“东南亚”“计费”“中小团队”等不同维度,最终答非所问。查询分解(Query Decomposition) 的思路就是:先把大问题像设计菜单一样拆成若干子问题,分别检索、分别回答,最后把子答案合并成一份完整的最终回答。这正是本文要讲的“子问题RAG”(Sub-Question RAG)策略。
对AI从业者来说,掌握查询分解等于掌握了复杂问答场景的“后厨管理术”——不必换更贵的模型,就能成倍提升RAG系统在对比、多条件、多属性类问题上的回答质量。
可视化演示
演示LR分析器对输入id+id*id的移进-归约解析过程:通过栈操作展示shift和reduce动作,最终接受输入并完成语法分析。
本节配有交互动效(进入视口后自动加载,约 3KB)。
LR分析器 Shift: 将输入符号移入栈 Reduce: 栈顶符号归约为非终结符 Accept: 输入完全匹配文法
问题分解策略
请客吃饭的第一步永远不是冲进厨房,而是坐下来写菜单。主人家会先想清楚客人的口味:有没有人忌辣?有没有小孩?荤素怎么搭配?然后才落笔把“一桌菜”拆成凉菜、热菜、汤、甜品。查询分解(Query Decomposition) 的第一节,做的就是这件事——拿到用户的大问题后,先不急着检索,而是先“写菜单”:拆成哪几个子问题。
从比喻落到技术上,这一步的输入是主查询(Main Query),输出是一组子查询(Sub-Query) 的列表。这组子查询必须满足两个关键性质:覆盖性(Coverage) 和独立性(Independence)。覆盖性指所有子问题合起来,必须完整覆盖主问题的全部信息需求,不能漏掉任何关键维度;独立性指子问题之间尽可能互不重叠,避免重复检索同一段知识。回到菜单的比喻:覆盖性保证“每道菜都有着落”,独立性保证“两道菜不会都跑去抢同一块五花肉”。
用集合语言可以精确描述这两个性质。设主问题为 $\text{Main}$,拆出的 $n$ 个子问题为 $\text{Sub}_1, \text{Sub}_2, \ldots, \text{Sub}_n$:
写菜单时有条经验:好菜单的每道菜都边界清晰、互不抢料。子问题拆分也是如此。拆得好,后续每一步都会顺畅;拆得烂,检索再快也弥补不了结构上的漏洞。
- 主问题集合$\text{Main}$ 表示用户原始查询包含的全部信息需求,可以想象成一个“信息篮子”,里面装着所有要找到的答案碎片。
- 子问题并集$\displaystyle\bigcup_{i=1}^{n}\text{Sub}_i$ 把 $n$ 个子问题各自的信息需求全部合并到一个大篮子里,检查这个大篮子是否完全装下了 $\text{Main}$ 里的每一片碎片。
- 覆盖关系$\subseteq$ 表示“被包含于”,即主问题篮子里的东西,子问题合并篮子里全都有,一个都不能少。
- 互不相交$\text{Sub}_i \cap \text{Sub}_j = \varnothing$ 表示任意两个子问题的信息需求没有交集,就像菜单上“凉拌黄瓜”和“拍黄瓜”不能同时出现一样,避免重复劳动。
提示词设计
家宴主人决定了菜单后,不会自己闷头干,而是把任务分给帮厨。但真正会做事的主人,一定会写“任务卡”:菜名、要点、时限、交付物。含糊一句“你去弄一下”的结果往往是帮厨端出一盘完全跑偏的菜。提示词(Prompt)就是给大模型的任务卡。
在设计查询分解提示词时,有几样“任务卡必填项”。第一,角色与任务设定(Role Setting):明确告诉模型“你是一个问题拆解助手,负责将复杂问题拆成可独立检索的原子子问题”。第二,输出格式(Output Format):要求模型输出结构化的JSON列表,例如 {"sub_questions": ["子问题1", "子问题2"]},方便下游程序直接解析调度。第三,示例引导(Few-shot):给一两个“问题→拆解结果”的样例,模型会模仿样例的拆分粒度。第四,边界约束(Constraints):提醒模型“不得改变原问题语义”“按原子粒度拆分”“拆分数量3-5个为宜”。
拆解质量不是拍脑袋,可以量化打分量化为三个维度——覆盖度、独立度、可检索度。令覆盖度指标为 $\alpha$ 权重、独立度为 $\beta$ 权重、可检索度为 $\gamma$ 权重,那么一次拆分的整体质量分数可以写成:
任务卡写得越好,帮厨越不容易跑偏。提示词里把角色、格式、示例、边界四件事写清楚,模型的拆分质量就会像拿着任务卡做菜的帮厨一样稳定可靠。
- 覆盖度分量$C(\text{sub})$ 表示子问题对主问题信息需求的覆盖比例,满分1意味着每个需求都有对应子问题;如果漏了一个维度,这个值就小于1。
- 独立度分量$I(\text{sub})$ 衡量子问题两两之间的重叠程度,重叠越多分值越低,理想状态接近1。
- 可检索度分量$R(\text{sub})$ 衡量每个子问题是否足够具体、能直接命中检索库,太抽象的问题这项得分会很低。
- 加权求和$\alpha \cdot C + \beta \cdot I + \gamma \cdot R$ 把三个维度乘上各自权重再相加,得到一个综合评分;$\alpha+\beta+\gamma=1$ 保证评分结果落在0到1之间,便于横向比较。
并行检索调度
菜单定好、任务卡发出去,真正高效的后厨是什么样的?绝对不会是每个帮厨都排队等同一口锅。有经验的厨房一定是:凉菜师傅在自己案板上切,蒸锅师傅守着灶,炒锅师傅在另一边颠勺——多线并行,互不阻塞。子问题RAG的检索阶段,正是借鉴了这样的“后厨流水线”。
调度机制分三步:批量分发(Dispatch)、并发执行(Execute)、结果收集(Collect)。先把所有子问题打包成一批任务,同时发给多个检索执行单元(可以理解为多个“检索器”或“工人”),每个工人独立完成自己的检索任务后,把结果统一交回调度中心。因为子问题之间具有独立性,所以它们的检索过程互不依赖,天然适合并行。
并行带来的时间收益非常直观。假如串行执行,总耗时是每个子问题检索耗时的累加;并行执行时,总耗时约等于最慢的那个子问题耗时,加上最后的聚合开销。设 $n$ 个子问题的检索耗时分别为 $T_1, T_2, \ldots, T_n$:
后厨的高效来自并行,RAG的高效同样来自并行。拆出的子问题越多,并行检索的省时效果越显著,但也要注意一次拆得太多会引入调度和聚合的额外开销——这正是第五节“递归与终止”要讲的度。
- 单子问题耗时$T_i$ 表示第 $i$ 个子问题从发起到检索完成所花的时间,每个子问题耗时可能不同。
- 并行总耗时$\max(T_1, T_2, \ldots, T_n)$ 取所有子问题耗时中的最大值,因为并行是同时跑的,总时长由最慢的那个决定。
- 聚合开销$T_{\text{agg}}$ 表示把各个子答案收集起来、合并处理的固定耗时,它和子问题个数无关,但必然存在。
- 节省时间$\Delta T = \sum_{i=1}^{n}T_i - \max(T_i)$ 用串行总耗时减去并行耗时(忽略聚合项),差值就是并行带来的收益——子问题越多,差值越大。
答案聚合与冲突消解
没有哪家家宴是菜炒好直接往桌上一扔就开吃的。主人会先尝一遍:凉菜咸了要调,热菜重复了要撤掉一道,口味相冲的菜调整上菜顺序。答案聚合(Answer Aggregation) 做的就是“尝菜调整”这一步:把各条子问题的检索答案收集起来,去重、消解、校验,最后端出一桌协调的席面。
聚合面对的首要问题是冗余。三个子问题可能都检索到同一篇文档的同一段话,直接拼接会让最终答案里出现三遍重复内容,所以第一步是去重。第二步是冲突消解(Conflict Resolution)。子问题A回答“这家云厂商东南亚节点延迟低”,子问题B回答“这家云厂商东南亚没有可用区”——两个答案矛盾时,需要一套仲裁机制。常用的方法包括多数投票(Majority Voting) 和置信度加权(Confidence Weighting),即看多个子答案中哪个答案的证据更充分、被更多子检索支持,就采信哪个。
设某个候选最终答案 $F$,$n$ 个子答案中有 $k$ 个支持 $F$,可以用投票分数来衡量这个候选答案的可信度:
上菜前的“尝菜”环节决定了这桌饭能不能拿得出手。答案聚合后的最终回答,也要经过去重、仲裁、校验这三道把关,才能交给用户。
- 指示函数$\mathbb{1}[\text{Ans}_i = F]$ 是一个“投票开关”——当第 $i$ 个子答案与候选答案 $F$ 完全一致时取1,否则取0。
- 逐项投票$\displaystyle\sum_{i=1}^{n}\mathbb{1}[\text{Ans}_i = F]$ 把所有子答案的投票相加,得到总支持票数,最高就是 $n$ 票(全员支持)。
- 归一化$\frac{1}{n}$ 把总票数除以子答案个数,把分数压到0到1区间,使不同问题之间可以比较。
- 最高分胜出遍历所有候选答案,取 $\text{Confidence}(F)$ 最大的那个作为最终答案,等于说“得票最多的答案胜出”。
递归与终止
家宴菜单不是一成不变的。如果客人是广东人,主人想做一道“佛跳墙”当硬菜——这道菜里又有鲍鱼、又有花胶、又有鸽子蛋,每个食材的处理方式不同,于是任务卡上又拆出三张小任务卡。这就是递归分解(Recursive Decomposition):子问题如果仍然太复杂,可以继续往下拆,形成一棵“问题树”。
但递归不能无限进行下去。厨房里时间有限、灶台有限,过了火候菜反而做砸了。所以必须有终止条件(Termination Condition) 和深度上限(Depth Limit)。两个常用判据:一是看子问题的粒度是否已足够“原子化”——如果子问题已经具体到可以直接检索命中,就停止拆分;二是看拆分的深度是否超过预设上限——比如规定最多拆3层,更深就不再递归。此外,如果拆到最底层仍然无法检索到有效答案,还需要一个兜底策略(Fallback):直接返回现有检索结果或提示用户收窄问题。
把递归的收益和成本放在一起看,可以得到终止的量化依据。设分解深度为 $d$,每多拆一层的平均精度收益为 $\Delta A(d)$,而每层的代价为 $c$(时间与计算开销),最优深度出现在边际收益等于边际成本处:
好厨师懂得“见好就收”。递归分解同样讲究“恰到好处”——既要拆到子问题足够清晰可检索,又不能在收益递减后继续浪费算力。
- 边际精度收益$\Delta A(d)$ 表示从第 $d$ 层往下再拆一层,最终答案质量能提升多少——拆到后面,每层提升越来越小。
- 边际代价$c$ 表示每多拆一层带来的固定开销,包括额外的提示词调用、额外的检索请求和延迟。
- 净收益$G(d) = \Delta A(d) - c$ 等于边际收益减去边际成本,就是“值不值得再拆一层”的判断值。
- 停止条件$G(d+1) \leq G(d)$ 表示再拆一层的净收益已经开始下滑,此时就是最佳停止点。
适用场景
不是每次吃饭都得摆一桌家宴。平时一个人在家,下碗面条5分钟搞定就好;只有客人来访、值得庆贺的日子才值得大动干戈准备一桌。查询分解也是如此:先评估收益,再决定要不要拆。 不是所有问题都值得分解,拆得好是效率倍增器,拆得不好是画蛇添足。
最适合查询分解的是三类场景。第一,多条件约束查询(Multi-constraint Query):例如“找出上海静安区、月租3000以内、允许养猫的一室户”,每个条件是一个独立的检索维度,合在一起检索容易顾此失彼。第二,对比类问题(Comparative Question):例如“A云和B云谁的按量计费更便宜”——需要分别检索两家厂商的计费规则再对比,天然适合拆成两个子问题。第三,多属性检索(Multi-attribute Retrieval):例如“找一款屏幕好、续航长、价格低于5000的笔记本”,三个属性各自检索再聚合,比一次性检索更精准。
什么时候拆、什么时候不拆,可以量化成收益评估模型。设 $V$ 为答案的价值(比如用户决策的重要性),$P(\text{miss})$ 为一次直接检索失败的先验概率(问题越复杂这个概率越高),$C_{\text{decomp}}$ 为分解成本,$C_{\text{latency}}$ 为额外延迟成本:
一句话:“值得请客才开家宴,问题够复杂才拆解。”掌握这个判断标准,查询分解就不是一把无脑挥舞的锤子,而是一把只在合适时机出鞘的手术刀。
- 失败概率$P(\text{miss})$ 是直接检索答非所问的概率——问题越复杂多条件,这个值越高。
- 预期损失$P(\text{miss}) \times V$ 用失败概率乘以答案价值,得到“不拆解可能付出的期望损失”。
- 分解成本$C_{\text{decomp}}$ 是让大模型做拆解提示词调用的开销,以及拆出来的子问题数量带来的检索费用。
- 延迟成本$C_{\text{latency}}$ 是并行检索后额外等待的时间成本——虽然并行省了时间,但拆解本身仍会引入延迟。
- 净收益判断$\text{Gain}$ 为正则值得拆,为负则不如直接检索。
AI 应用场景
场景一:电商平台的多条件商品对比搜索
阶段:查询分解 → 并行检索 → 答案聚合
解决的问题:用户在电商平台搜索“适合户外露营的轻薄本,重量1.3kg以内,续航10小时以上,价格7000以内”,传统搜索引擎按关键词匹配时,很难让同一篇商品详情同时满足四个条件,往往返回一堆顾此失彼的结果。AI把问题拆成“轻于1.3kg的轻薄本”“续航超10小时的笔记本”“7000元以内的便携本”三个子问题分别检索,再聚合出同时满足三个条件的机型。
具体案例:某电商导购助手接入了查询分解RAG后,用户输入上述多约束查询时,系统先拆出三个子问题并行检索规格库与评测库,聚合时用投票机制筛掉只满足部分条件的机型,最终给出一个对比表格,直接标注每款机型的命中维度。
场景二:企业知识库的对比分析答疑
阶段:子问题拆分 → 分库检索 → 冲突消解
解决的问题:企业内部员工问“今年Q3和去年Q3各产品线的营收变化如何”,直接检索会得到一堆混合历史年份的报表片段。AI把问题拆成“去年Q3各产品线营收”“今年Q3各产品线营收”“两期数据对比分析”三个子问题,分别从财务知识库检索,最后聚合成一张对比分析结论。
具体案例:某SaaS公司为其销售团队部署了知识库问答助手,销售在准备客户方案时询问“对比我们标准版和Pro版的计费差异”,助手自动拆成两个子问题分别检索定价文档,再聚合出差异对照表,销售直接复制进方案书。
场景三:多文档研究报告辅助撰写
阶段:递归分解 → 并行检索 → 证据综合
解决的问题:分析师需要回答“东南亚各国近三年的云计算政策有什么共同趋势”,这个问题的复杂度值得递归分解:先按国家拆成“新加坡”“印尼”“越南”三个子问题,每个子问题又按时间轴拆成“2021年政策”“2022年政策”“2023年政策”再检索。AI层叠聚合后给出跨国家、跨年份的趋势综述,并附上每一条结论对应的文档引用。
具体案例:某咨询公司的研究助手接入了递归查询分解,分析师输入一个泛主题后,系统自动展开成“国家×年份”的检索网格并行抓取,最终生成的综述引用了40多篇政策文档,与传统手工检索相比效率提升了5倍以上。
Python 演示
# -*- coding: utf-8 -*-"""query_decomposition_demo.py一个极简的查询分解RAG演示:1. 用规则把大问题拆成子问题2. 每个子问题独立检索模拟文档库3. 聚合子答案并去重输出""" import reimport timefrom concurrent.futures import ThreadPoolExecutor DOC_STORE = { "aws": "AWS在东南亚有新加坡和雅加达两个region,按量计费每小时0.10美元起。", "azure": "Azure东南亚region在新加坡,月度订阅套餐更优惠,需预付1年合约。", "gcp": "GCP在东南亚有新加坡和雅加达region,网络流量费较低。", "price": "按量计费适合短期弹性负载,长期稳定业务建议包年包月。", "latency": "新加坡region对东南亚用户延迟最低,雅加达region覆盖印尼本地更优。", "team": "中小团队通常选择包年包月以控制成本,起步配置约每月50美元。",} class QueryDecomposer: def __init__(self): self.max_depth = 2 self.gc_count = 0 def decompose(self, question): """按关键词规则将问题拆成子问题列表""" sub_list = [] if "云厂商" in question and "东南亚" in question: for vendor in ["AWS", "Azure", "GCP"]: sub_list.append(f"{vendor}在东南亚的计费规则是什么") sub_list.append(f"{vendor}在东南亚的region分布在哪里") if "适合" in question and "团队" in question: sub_list.append("中小团队应该选择按量计费还是包年包月") if not sub_list: sub_list = [question] return sub_list[:6] class SimpleRetriever: def __init__(self): self.doc_list = list(DOC_STORE.keys()) self.free_lists = {} def search(self, sub_query): """按关键词命中文档,模拟检索""" self.free_lists["hit"] = [] for key, text in DOC_STORE.items(): for kw in sub_query.split("的"): kw = kw.strip() if kw and kw in text: self.free_lists["hit"].append(text) break time.sleep(0.2) return list(set(self.free_lists["hit"])) class AnswerAggregator: def __init__(self): self.gc_count = 0 def aggregate(self, sub_answers): """合并多个子答案,去重后拼接""" seen_set = set() merged = [] for ans in sub_answers: for piece in ans: if piece not in seen_set: seen_set.add(piece) merged.append(piece) return " ".join(merged) def main(): question = "对比AWS、Azure、GCP在东南亚的云服务,推荐一个适合中小团队的方案" print("原始问题:", question) decomposer = QueryDecomposer() sub_questions = decomposer.decompose(question) print("拆解出的子问题:") for i, sq in enumerate(sub_questions, 1): print(f" {i}. {sq}") retriever = SimpleRetriever() start = time.time() with ThreadPoolExecutor(max_workers=4) as pool: results = list(pool.map(retriever.search, sub_questions)) print(f"并行检索完成,耗时 {time.time() - start:.2f} 秒") aggregator = AnswerAggregator() final_answer = aggregator.aggregate(results) print("聚合后的最终回答:") print(" ", final_answer) if __name__ == "__main__": main()
sub_list.append(f"{vendor}在东南亚的计费规则是什么")按供应商维度生成独立子问题,保证覆盖性与独立性if not sub_list: sub_list = [question]兜底策略:如果拆不出子问题,就直接用原问题检索,不强行拆分ThreadPoolExecutor(max_workers=4)创建4个并行线程执行检索调度,对应正文的并行检索阶段pool.map(retriever.search, sub_questions)批量分发所有子问题,并发执行,自动收集结果for kw in sub_query.split("的")用简单关键词匹配模拟向量检索,教学演示用,生产环境替换为真实检索if piece not in seen_set答案聚合时按片段内容去重,避免多个子问题命中同一段文档被重复拼接aggregator.aggregate(results)统一收集所有子答案并合并为最终回答,对应答案聚合与冲突消解阶段
常见误区
误区是不是只要用了查询分解,效果一定比直接检索好?那我干脆把所有用户问题都先拆一遍再检索,反正拆总比不拆强。
正解拆解本身有成本。每次调用大模型做分解要花时间和token,拆出来的子问题逐个检索要增加检索次数和延迟。如果问的是“今天天气怎么样”这类简单问题,拆解带来的收益约等于零,反而白白增加了两三倍的延迟。就像一个人吃饭也要摆八道菜,菜做不完也吃不完,纯属浪费。
为何常见:因为看到案例里查询分解在复杂问题上效果显著,容易产生“技巧万能”的错觉,忽略了收益评估——判断标准是公式 $\text{Gain} = P(\text{miss}) \times V - C_{\text{decomp}} - C_{\text{latency}}$ 是否为正。
误区拆完问题、检索完每个子问题,把各段答案按顺序拼在一起不就是最终回答了吗?反正信息都有了,还要多做一步处理干嘛?
正解直接拼接会带来两个问题:一是多个子问题可能命中同一段文档,最终回答里同一句话出现两遍;二是子答案之间可能互相矛盾,直接拼接等于把矛盾原样交给用户。正确答案聚合需要经过冗余去重、冲突消解、一致性校验三步。就像把每道菜直接往桌上扔,盘子叠盘子、菜汁混菜汁,客人根本没法下筷。
为何常见:初学者最容易低估“聚合”这一步的技术含量,以为检索完就万事大吉,忽略了从“信息”到“答案”还需要一道处理工序。
误区既然拆得细能检索得更精准,那我尽量多拆——一个复杂问题拆成二十个子问题,覆盖得全面,答案一定更好。
正解子问题数量存在最优区间,并不是越多越好。拆得太多,每个子问题的检索收益递减,调度和聚合的开销却线性增长,并行检索时间反而可能超过串行——因为调度器本身要处理的任务排队也在耗时。正规做法是观察收益拐点,当边际收益小于边际成本时停止。后厨请二十个厨师炒一道菜,光协调指挥就比做菜还累。
为何常见:把这个策略和“检索粒度越细越准”混淆了,粒度的精细化有一个前提——每个检索操作本身有固定开销,数量膨胀会压垮收益。
误区拆分时就当每个子问题孤立处理,反正公式写了“独立性保证”,检索时互不干扰就行,不用考虑子问题之间的关联。
正解真实场景中,很多问题拆出来的子问题存在隐含依赖。比如“对比AWS和Azure的计费”,两个子问题各自检索价格,但“哪家更适合”这个结论依赖两边的价格对比,而不是各自孤立的价格信息。忽略依赖关系会导致聚合阶段出现逻辑矛盾。把“独立性”理解为“检索动作互相独立”,而不是“信息内容毫无关联”,才是正确的视角——就像夫妻俩分别买菜,买完还要商量这顿饭怎么做。
为何常见:公式里的 $\text{Sub}_i \cap \text{Sub}_j = \varnothing$ 容易让人误解为“信息完全不相关”,实际含义是“检索任务不重复”,而不是“答案内容不关联”。
误区子问题还复杂就继续拆,拆到不能再拆为止——层数深一点没事,拆到底总能把最原子的答案找出来。
正解递归必须设深度上限和终止条件。每拆一层都在增加延迟和成本,而且拆到第4层、第5层时,问题已经过于碎片化,检索回来的片段脱离上下文,反而拼不回完整的答案。终止条件应该是“子问题已可直接检索命中”或“达到预设深度”的或逻辑。佛跳墙里的鲍鱼要提前三天发泡,但不会有人把发泡后的鲍鱼再切成分子料理——过了头就失去了食材本味。
为何常见:看到“递归”两个字就联想到“深入到底”,忽略了工程实践里“深度换精度”的边际递减规律。
面试题
Q1. 查询分解的核心思想是什么?
- A.用更复杂的模型重新生成答案
- B.将大问题拆为多个子问题分别检索← 正确答案
- C.一次性检索全部知识库文档
- D.把答案拼接后直接返回用户
答案:B。查询分解的核心是把复杂大问题拆成多个可独立检索的子问题,再聚合子答案。选项B准确描述了这一定义;A是换模型思路;C是暴力检索;D忽略了聚合处理工序,直接拼接不是完整思想。
Q2. 子问题的“独立性”指什么?
- A.子问题答案互相矛盾
- B.子问题之间检索任务互不重复← 正确答案
- C.子问题数量必须相等
- D.子问题不能用中文表达
答案:B。独立性指子问题的信息需求互不重叠,检索任务不重复,对应公式 $\text{Sub}_i \cap \text{Sub}_j = \varnothing$。B正确;A是冲突不是独立;C数量无要求;D语言无关。
Q3. 以下哪个不是提示词设计中的关键要素?
- A.角色与任务设定
- B.规定JSON输出格式
- C.给一两个拆解示例
- D.指定检索时使用的向量维度← 正确答案
答案:D。提示词设计四要素是角色设定、输出格式、示例引导、边界约束。检索向量维度是检索器内部参数,与提示词无关,D不属于提示词设计范畴。
Q4. 适合使用查询分解的典型场景有哪些?
- A.多条件约束查询← 正确答案
- B.对比类分析问题← 正确答案
- C.简单事实性问题
- D.多属性联合检索← 正确答案
答案:ABD。查询分解适合多条件、对比类、多属性联合检索等复杂查询。C“简单事实性问题”直接用单次检索即可,分解反而浪费成本,不符合收益评估原则。
Q5. 答案聚合阶段的主要挑战是什么?
- A.检索速度不够快
- B.子答案冗余与冲突消解← 正确答案
- C.提示词写得太短
- D.文档库容量不足
答案:B。聚合阶段面对两个核心挑战——子答案冗余去重和冲突消解,对应正文的Confidence公式。A是检索阶段问题;C是分解阶段问题;D是数据层问题,均不属于聚合挑战。
Q6. 关于并行检索调度,以下说法正确的有?
- A.并行总耗时等于所有子任务耗时之和
- B.并行总耗时约等于最慢子任务的耗时← 正确答案
- C.子问题拆得越多并行收益一定越高
- D.调度与聚合会引入额外开销← 正确答案
答案:BD。并行耗时约等于$\max(T_i)$加聚合开销,B正确;A描述的是串行耗时;C错误,子问题过多时调度与聚合开销增长会抵消收益;D正确,调度器处理和聚合步骤都是固定额外成本。
Q7. 递归分解中“停止条件”的作用是什么?
- A.让子问题永远拆下去
- B.当子问题可检索命中时停止← 正确答案
- C.强制所有问题只拆一层
- D.跳过聚合步骤直接返回
答案:B。终止条件是在子问题已经足够原子、可直接检索命中时停止递归,或达到深度上限时停止。A是反面;C不灵活;D跳过聚合是错误的。
Q8. 查询分解中“覆盖率”的含义是?
- A.检索文档占知识库的比例
- B.子问题覆盖主问题全部需求← 正确答案
- C.答案占最终输出的比例
- D.提示词覆盖字符比例
答案:B。覆盖率指所有子问题合起来完整覆盖主问题的全部信息需求,对应公式 $\text{Main} \subseteq \bigcup \text{Sub}_i$。A是文档覆盖率概念;CD与查询分解的覆盖率无关。
Q9. 关于冲突消解的投票机制,正确的理解有?
- A.每个子答案对候选答案投一票← 正确答案
- B.得票率最高的候选答案胜出← 正确答案
- C.所有冲突都必须投票解决
- D.投票分数可用归一化公式计算← 正确答案
答案:ABD。公式 $\text{Confidence}(F) = \frac{1}{n}\sum \mathbb{1}[\text{Ans}_i=F]$ 表明每个子答案投一票、归一化后比较支持率,A、B、D正确。C太绝对,实际中证据权重充分时可直接采信,不必所有冲突都投票。
Q10. 判断“是否值得拆分”的核心标准是什么?
- A.问题字数是否超过20字
- B.拆解收益大于分解与延迟成本← 正确答案
- C.用户是否要求详细回答
- D.模型参数量是否足够大
答案:B。收益评估公式 $\text{Gain} = P(\text{miss}) \times V - C_{\text{decomp}} - C_{\text{latency}}$ 表明,只有当失败预期损失大于分解与延迟成本时才值得拆。A、C、D都不是判断依据,B符合收益评估的核心标准。