Dify 高级实验(05):多步推理——如何把复杂问题拆解成子问题逐个击破
发布时间:2026/8/15 12:15:15 作者:尧图编辑部 阅读量:1,286
:多步推理——如何把复杂问题拆解成子问题逐个击破)
Dify 高级实验05多步推理——如何把复杂问题拆解成子问题逐个击破Dify 实验系列 · 高级 05/10 | 实验编号DIFY-103-05基于 Dify 1.16.1 实测2026-081. 业务场景先讲一个我们实际遇到的场景。一位用户在产品社区里问「我该买 iPhone 还是华为」这个看似简单的问题直接问 LLM 往往得到一段含糊其辞的「各有优劣看你的需求」——因为「买哪个」背后其实是一串子问题价格差多少性能谁强续航谁久生态谁全最后还要结合用户自己的偏好做判断。一步回答模型要么信息不全要么夹带私货用户看完还是不知道买哪个。我们第一次遇到这类问题时第一反应也是「让模型多思考一会儿不就行了」。后来才发现——问题不在思考时长而在上下文模型在同一个上下文里既要回忆事实、又要对比、还要下判断互相干扰一步回答天生不可靠。把问题拆开、逐个击破、最后综合才是人类分析问题的方式也是 LLM 该有的方式。这不是个例。任何「一步答不准」的问题都是这个模式产品对比A 和 B 选哪个、行业分析新能源车会不会取代燃油车、研究型问答这个技术方案值不值得采用——问题越复杂一步到位的回答越不可靠因为模型在同一个上下文里既要回忆事实、又要对比、还要下判断互相干扰。2. 场景痛点这个流程的痛点在问问题的人身上体现得最直接一步回答信息不全模型一次回答只能覆盖部分维度——对比手机只聊了价格没聊续航用户拿到的结论是残缺的决策依据不足。不可解释模型直接给结论「推荐华为」但没说清楚基于哪些维度、每个维度怎么比较的——用户无法判断这个推荐是否适合自己也不敢信。复杂问题答不准事实、对比、判断混在一个回答里模型容易顾此失彼——说了价格忘了性能说了优点不提缺点回答质量随问题复杂度直线下降。无法定位错误回答错了用户不知道错在哪一步——是事实记错了还是对比维度漏了还是判断逻辑有问题完全无法追溯。本质上一步回答的瓶颈不是模型不够聪明而是「把复杂问题当简单问题处理」——复杂问题需要先拆解、再逐个击破、最后综合这是人类分析问题的方式也是 LLM 该有的方式。3. 方案为什么是这套多步推理范式Dify 工作流里的「拆解 → 迭代推理 → 综合」链路把「一步回答」变成「先拆后答」正好复刻人类分析问题的过程。选它的理由我们实际对比过拆解让每个子问题都可独立求解LLM 把复杂问题拆成 3-5 个可独立检索或推理的子问题每个子问题单独回答——单点准确率远高于一次答全迭代节点逐个击破Dify 原生迭代节点对每个子问题单独跑一轮 LLM子问题之间不互相污染答案可逐条核对综合阶段显式标注缺口子回答出现「不确定」时汇总代码检测出来最终答案显式标注信息缺口——不掩盖不确定性用户知道哪些结论可靠、哪些要核实。这篇文章我们就用它搭一个「多步推理问答助手」复杂问题先拆成子问题逐个推理再综合成结构化回答。4. 整体架构开始user_query / query_subjectLLM 问题拆解输出子问题 JSONCode 准备迭代解析 JSON → items 数组迭代「逐子问题分析」itstart0 → LLM 子问题回答Code 汇总子回答拼接 检测「不确定」缺口LLM 综合回答引用分步结果标注缺口结束链路很清晰入口收复杂问题 → 拆解成子问题 → 逐个子问题推理 → 汇总检测缺口 → 综合回答。拆解和迭代是这个架构的核心——拆得好每个子问题都能独立求解迭代让子问题逐个处理互不干扰。5. 模块设计5.1 拆解 LLMlm_decompose系统提示词限定输出纯 JSON并要求 3-5 个子问题、先事实后判断你是一个问题拆解专家。将用户的问题拆解成 3-5 个独立的子问题。 用户问题{{#start.user_query#}} 拆解规则 1. 每个子问题必须是可独立检索或推理的 2. 子问题之间不要重叠 3. 按逻辑顺序排列先事实后判断 输出格式纯 JSON不要 Markdown {sub_questions: [{id: 1, question: xxx, type: fact/compare/judge}], reasoning_path: 从基本信息到综合判断的逻辑链描述}5.2 准备迭代代码cd_prepare解析拆解结果并兜底think剥离 →json.loads→ 失败则按行正则提取子问题最后items[:5]截断防迭代 30 元素上限defmain(sub_questions_json,query_subject):importjson,re textsub_questions_jsonifisinstance(sub_questions_json,str)elsestr(sub_questions_json)textre.sub(rthink.*?/think,,text,flagsre.DOTALL).strip()mre.search(r\{[^}],text)ifm:texttext[m.start():]try:questionsjson.loads(text)itemsquestions.get(sub_questions,[])ifisinstance(items,list)andlen(items)0:return{items:items,total:len(items),reasoning_path:questions.get(reasoning_path,)}except:passlinestext.split(\n)items[]forlninlines:m2re.match(r^\d[\.\、\,]\s*(.)$,ln.strip())ifm2andlen(m2.group(1).strip())5:items.append({id:len(items)1,question:m2.group(1).strip(),type:fact})return{items:items[:5],total:min(len(items),5),reasoning_path:}5.3 迭代节点it三件套缺一不可iterator_selector指向 items 数组、output_selector只选可见类型string、start_node_id与迭代起始标记 id 一致-data:desc:iterator_selector:[cd_prepare,items]output_selector:[lm_sub,text]start_node_id:itstart0title:逐子问题分析type:iteration5.4 子问题 LLMlm_sub迭代内部 LLM 引用{{#it.index#}}序号与{{#it.item.子字段#}}这是迭代标准机制必须配reasoning_format: separated你是一个专题分析师。请回答以下子问题。 主题{{#start.query_subject#}} 子问题第{{#it.index#}}个{{#it.item.question#}} 问题类型{{#it.item.type#}} 回答要求 1. fact 类型基于知识回答compare 列出对比维度judge 给出判断理由 2. 控制在 100 字以内 3. 如不确定明确说不确定 4. 直接给出回答不要重复问题5.5 汇总代码cd_summary逐条拼接 Q/A并检测信息缺口——has_information_gaps展平为字符串boolean 在变量选择器不可见defmain(sub_results,original_query,reasoning_path):lines[]has_gapsFalseforitemin(sub_resultsifisinstance(sub_results,list)else[]):qitem.get(question,?)ifisinstance(item,dict)else?aitem.get(answer,item.get(text,未回答))ifisinstance(item,dict)elsestr(item)lines.append(fQ:{q}\nA:{a}\n)if不确定ina:has_gapsTruereturn{intermediate_results:\n.join(lines),has_information_gaps:trueifhas_gapselsefalse,gap_note:部分信息未确认建议核实ifhas_gapselse信息完整}5.6 综合 LLMlm_final引用{{#cd_summary.intermediate_results#}}与{{#cd_prepare.reasoning_path#}}要求先给直接答案、再引关键论据、最后按缺口标注。6. 运行验证输入期望行为实测user_query我该买 iPhone 还是华为query_subject手机对比拆解出 5 个子问题价格/性能/续航/生态/推荐逐个回答后给出综合对比与推荐与预期一致回答结构化、含缺口标注逻辑user_queryAI 会不会取代程序员query_subject职业分析拆解出「AI 能力现状/程序员工作内容/替代分析/趋势」等子问题输出行业分析与预期一致构造一个让子回答出现「不确定」的输入gap_note 部分信息未确认建议核实最终回答末尾标注与预期一致信息缺口检测生效7. 实战坑坑现象修复迭代内部 LLM 缺reasoning_format: separated思考过程混入text污染整个迭代输出数组cd_summary里不确定 in a把思考中的「不确定」误判为信息缺口迭代内 LLM 显式加reasoning_format: separateddify103_05 实测迭代五件套缺失或yaml.dump()重写内部节点 UI 叠在一起 /iteration_id、parentId、isInIteration、sourcePosition、targetPosition被静默销毁校验报错内部节点补全五件套修改用patch精确定位不用 yaml round-tripprompt 变量用{{变量名}}双花括号1.16 不替换双花括号字面传给模型回答「参考资料为空」LLM prompt 一律{{#节点id.字段#}}三花括号dify102_12 实测拆解出过多子问题迭代运行报then length of var item must be less than 30 elements拆解 prompt 限 3-5 个 cd_prepare里items[:5]截断留余量dify103_09 实测8. 实验文档及源码获取实验文档完整操作步骤DIFY-103-05多步推理工作流.md源码可直接导入dify103_05_多步推理工作流.yml文章聚焦核心配置与采坑点实验的完整分步操作节点搭建/参数表/调试指引见实验文档原文。下一篇Dify 高级实验06自动化报告——如何让系统定时自动生成周报 你在这个实验的场景里踩过什么坑欢迎评论区分享你的实战经验。