Least-to-Most提示法并不是要推翻思维链,而是把思维链中一次完成的推理过程拆成独立的子任务,按照由易到难的顺序逐步推进。它的关键假设是:模型在简单子问题上表现更稳定,而通过逐步引入前面已经求得的中间结果,可以显著降低长链条推理中的错误累积。本文会从该方法与标准思维链的差异、两阶段实现流程、具体示例以及调优边界几个角度展开。

Least-to-Most为什么能缓解复杂推理中的错误累积
标准思维链让模型在生成最终答案之前,先输出一串推理步骤。对于三五步以内的任务,这种做法通常效果不错。但当推理步骤达到七八步甚至更多时,模型容易在中间某一步产生幻觉、跳步或者忽略关键条件,而后续步骤又会基于这个错误继续推导。由于整个推理链在一个回答中完成,错误很容易沿着不断增长的文本序列向后传播,最终导致答案偏离正确路径。
Least-to-Most把任务从单一提示分解为多个提示。第一阶段先让模型把原始问题拆成一组子问题列表;第二阶段按照从易到难的顺序逐个求解这些子问题。因为模型每次只需要处理一个小范围的子任务,输入中的已知信息更加明确,输出长度也更短,所以中间答案的可靠性更容易控制。如果某个子问题解错了,还可以单独重新生成该子问题的答案,而不必像标准思维链那样重新生成整条推理链。
这种做法的另一个优势在于上下文组织更清晰。标准思维链的中间结果夹在同一个回答里,模型在生成后续步骤时需要自己从前面文本中提取相关信息。Least-to-Most则把每个已经解决的子问题和对应答案作为结构化上下文附加到新提示中,相当于明确告诉模型哪些信息已经确认,从而减少重复推理或漏用条件的概率。对于需要严格遵循先后顺序的任务,这种显式上下文传递比依赖模型自我回溯更可靠。
两阶段实现流程与关键提示词设计
分解阶段需要模型输出真正可执行的子任务,而不是简单重述原问题。提示词中应当明确要求:将复杂问题分解为多个子问题,按从易到难的顺序排列,并且每个子问题都必须是原问题求解路径上的必要步骤。为了帮助模型理解拆分粒度,可以补充一到两个few-shot示例,展示什么样的子任务粒度足够小、顺序合理。例如,不要把“计算最终结果”当成一个子问题,而要把它拆成先求已知量、再组合条件、最后计算总和这样的步骤。
逐级求解阶段需要把前面所有子问题及其答案一起放进当前提示中。格式可以设计成“已知信息”“当前子问题”“求解要求”三个部分。这样模型不会把当前子问题当成孤立问题来处理。下面是一个基于Python伪代码的实现框架,llm可以替换为任意大模型调用函数。
def least_to_most_solve(problem):
decomposition_prompt = (
"请把下面的复杂问题分解为多个子问题,"
"按从易到难的顺序排列,每个子问题都更接近最终答案:\n"
f"问题:{problem}"
)
sub_problems = llm(decomposition_prompt, max_tokens=500).split("\n")
context = []
for sub in sub_problems:
solve_prompt = (
"已知前面的推理结果:\n"
f"{context}\n\n"
f"请解决子问题:{sub}"
)
answer = llm(solve_prompt, max_tokens=300)
context.append(f"子问题:{sub}\n答案:{answer}")
final_prompt = (
"根据以下子问题的答案,给出原始问题的最终答案:\n"
f"{context}\n\n"
f"原始问题:{problem}"
)
return llm(final_prompt, max_tokens=500)
在实际系统中,分解阶段和求解阶段可以使用不同的提示模板。分解阶段建议把温度设置得低一些,例如0.2,重点保证子任务列表结构稳定;求解阶段可以保持较低温度,也可以根据子问题难度动态调整。每个子问题的答案最好再做一次简单校验,比如要求模型在输出答案前先复述该子问题用到的条件。这样可以提前发现明显遗漏,避免错误答案进入后续上下文。
从具体算术题看Least-to-Most如何展开
假设原问题是:某商店第一天卖出12件商品,第二天卖出数量是第一天的两倍少3件,第三天卖出数量比前两天总和多5件,问三天总共卖了多少件。标准思维链可能一次性写到第三天时忘记加上前两天的总和,或者在理解“两倍少3件”时出错。Least-to-Most会先让模型给出分解结果,类似下面这样。
子问题1:第一天卖出多少件? 子问题2:根据第一天数量,第二天卖出多少件? 子问题3:根据前两天总和,第三天卖出多少件? 子问题4:三天总共卖出多少件?
求解阶段先处理子问题1,答案是12件。然后把“子问题1:第一天卖出多少件?答案:12件”放入上下文,再求解子问题2,得到第二天为12乘以2再减3等于21件。类似地,子问题3得到12加21再加5等于38件,子问题4得到12加21加38等于71件。每一步的输入都包含明确的前序结果,模型不需要在长文本中回溯查找,也不容易混淆第二天和第三天的计算条件。
这种拆分方式在处理多条件应用题、符号运算和代码生成时尤其有效。以代码生成任务为例,如果让模型一次性生成一个包含解析配置、连接数据库、处理异常和输出报表的程序,它很可能只覆盖前两个部分,或者把异常处理放在错误的位置。若先让模型列出实现步骤,再依次生成每个步骤对应的代码,并对每段代码做单独检查,最终拼接出的代码质量通常更高。需要注意的是,拆得太碎也会增加调用成本,通常按照“一个子问题对应一个明确可验证结果”的粒度比较合适。
| 维度 | 标准思维链 | Least-to-Most |
|---|---|---|
| 推理过程 | 单次输出一整条推理链 | 多次输出,逐个求解子问题 |
| 中间结果利用 | 依赖模型在长文本中自行回看 | 显式作为上下文传入后续提示 |
| 错误定位 | 较难定位中间步骤 | 可以单独重试某个子问题 |
| 调用成本 | 较低 | 较高,Token消耗更大 |
| 适用规模 | 短链条任务 | 长链条、多条件复杂任务 |
适用边界、常见误区和调优建议
Least-to-Most并非所有任务都适用。对于一些简单的常识问答或一步到位的事实查询,拆解反而会增加延迟和Token消耗。它的价值主要体现在几类场景中:需要连续多步推理的数学题、需要先分析实体关系再回答的问题、需要生成多文件代码或多步骤操作脚本的任务,以及需要严格遵循先后顺序的业务流程。如果任务本身只有一两个推理步骤,直接使用标准思维链或甚至直接回答会更划算。
常见误区是把分解阶段当成最终答案的生成。如果模型在第一阶段输出的子问题本身就有语义偏差,后续求解会沿着错误路径前进。因此,在重要业务中应当对子问题列表做规则校验或人工确认。另一个误区是上下文无限堆积。子问题较多时,早期中间结果可能被模型忽略,可以只保留与当前子问题最相关的几个前置结果,或者定期对中间结果做摘要,避免上下文越长反而越容易丢失关键信息。
调优时可以从三个角度入手。一是降低分解提示的温度,保证子问题列表结构稳定;二是在每个求解提示中使用固定格式,例如“已知信息”“当前任务”“输出要求”,减少格式漂移;三是为分解阶段提供2到3个标注好的few-shot示例,帮助模型理解拆分粒度。经过这些调整,Least-to-Most通常能比标准思维链在复杂推理任务上表现出更低的错误率,代价是交互次数和Token消耗会有所增加。
Least-to-Most提示法思维链提示工程修改时间:2026-09-20 01:30:29