Menu

思维链提示(CoT):让我们一步一步地思考

思维链提示要求模型在给出答案之前,先把推理过程写出来。它对多步骤的数学和逻辑题帮助最大,对那些回答前本来就会先思考的推理模型则作用较小。

下面的每条提示词都可以编辑:改好后,在 ChatGPT、Claude 或其他 AI 应用中打开。

思维链提示要求语言模型在给出最终答案之前,先写出解题的中间步骤。在需要多个步骤的问题上,比如应用题、逻辑谜题和排程,把思考过程写出来往往比直接作答得到更多正确答案,还会留下可以检查的步骤。最简短的版本就是在提示词里加一句话:“让我们一步一步地思考。”

为什么写出步骤有帮助

模型是一个 token 一个 token 地生成回复的,它已经写下的所有内容都会成为下一个 token 的输入。如果提示词要求立即给出答案,模型就必须在页面上还没有任何中间结果时就写出答案。如果它先写下“周一咖啡的销售额是 $168”,这个数字就进入了上下文,下一步就可以在它的基础上推进,而不必把它隐含地记在“脑子里”。

这是直观上的理解。证据来自 2022 年的两篇论文。Wei 等人的《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》表明,写出推理过程的解题示例能提升大模型在算术、常识和符号推理任务上的表现。他们还发现,效果取决于模型规模:较小的模型没有提升,还常常写出流畅却导向错误答案的推理。随后,Kojima 等人的《Large Language Models are Zero-Shot Reasoners》表明,不给任何示例、只加一句“让我们一步一步地思考”,也能大幅提升结果,不过提升幅度通常比不上解题示例。

直接作答与思维链

两个标签页问的是同一个问题。第一个只要金额;第二个要求写出计算过程,并把答案放在固定的最后一行。

一家咖啡馆的咖啡卖 $3.50,松饼卖 $2.25。周一它卖出了 48 杯咖啡和一些松饼,总收入 $213。周二卖出的咖啡比周一少 10 杯,松饼是周一的两倍。周二的收入是多少?只回答金额。
Try it
Example replyReplies vary between models and runs.

$258

直接作答的回复出现了一个典型的疏漏:258是周一的咖啡收入258 是周一的咖啡收入 168 加上周二的松饼收入 $90,它忘了周二的咖啡少卖了 10 杯。一步一步的回复把周二的咖啡杯数单独写成一行,这一步就不可能被悄悄跳过。现在的模型可能直接作答也能算对;问题越长、步骤之间的依赖越多,差距就越大。

写出的步骤还有第二个好处:答案错了的时候,你能看出是哪一步出了问题,并在那里修改提示词或输入。

少样本思维链

Wei 等人最初的方法,是在提示词中放入答案带有推理过程的解题示例,模型就会用同样的方式回答新问题。下面的示例改编自他们论文的第一张图,后面的问题是新的。改一改问题,试试你自己的。

少样本思维链
Fill in
Parts
问:Roger 有 5 个网球。他又买了 2 罐网球,每罐有 3 个。他现在有多少个网球? 答:Roger 一开始有 5 个球。2 罐、每罐 3 个,就是 6 个网球。5 + 6 = 11。答案是 11。
问:一家图书馆的书架上有 120 本书。它借出了 45 本,收回了 18 本,又收到了 30 本捐赠。现在书架上有多少本书? 答:
Try it
Example replyReplies vary between models and runs.

图书馆一开始有 120 本书。借出 45 本后,书架上剩下 75 本。收回 18 本后是 93 本。加上捐赠的 30 本,一共是 123 本。答案是 123。

少样本 CoT 让你能控制推理的形式:写多长、要讲清哪些内容、答案怎么表述。示例里的“答案是 11”是一个固定的结尾,回复也照搬了它。零样本 CoT 写起来更快,但这些选择都交给了模型。关于如何构建示例集,见少样本提示;只用指令的版本,见零样本提示。

把答案单独放在一行

回复里一旦包含推理过程,答案就会夹在某个段落中间,如果需要由程序读取,这就成了问题。要求模型在最后一行用固定的格式给出答案,就像咖啡馆的提示词用“Answer: $X”那样(这个固定标签最好保持原样,因为代码查找的就是它),然后在代码里读取那一行:

import re

matches = re.findall(r"^Answer:\s*(.+)$", reply, re.MULTILINE)
answer = matches[-1] if matches else None

取最后一个匹配很重要,因为在模型自我纠正之前,推理过程本身可能就有一行以“Answer:”开头。如果用户只需要看到答案,可以让模型把推理放在一对标签里,把答案放在另一对标签里,然后只显示后者。需要不止一个字段时,结构化输出介绍了如何要求输出 JSON。

推理模型

现在有些模型生来就会先思考再回答:在可见的回复之前,它们会在内部生成推理过程,这些推理通常被隐藏或只显示摘要。对这类模型,“让我们一步一步地思考”的作用要小得多,因为不管你要不要求,这些步骤都会发生。加上这句话,通常只会让可见的回复变长。

对推理模型依然有帮助的,是推理之外的一切:完整的问题描述、正确答案必须满足的约束,以及最终答案的格式。描述好答案应该是什么样子,而不是规定每一步怎么做;一套固定的步骤可能会让模型偏离它本来能自己找到的更好路线。

什么时候不该用思维链

思维链要消耗 token 和时间,只有当任务包含相互依赖的步骤时才划算。对于查询、翻译、改写或简单分类,它只会让回复变长。模型也可能写出看似合理的推理,却得出错误的答案,所以要单独检查最终结果,而不只是检查推出它的那些步骤。

对于单条推理链可能出错的难题,有两种在它基础上的扩展。自洽性提示会采样多条推理链,取其中多数得出的答案;思维树提示则会先探索并比较几条不完整的推理思路,再选定其中一条。

常见问题

思维链提示是什么?

思维链(CoT)提示要求语言模型在给出最终答案之前,先写出解题的中间步骤。做法有两种:展示带有推理过程的解题示例,或者加上一句“让我们一步一步地思考”这样的指令。在多步骤问题上,这样往往能得到更多正确答案,而且你可以检查每一步。

“让我们一步一步地思考”现在还管用吗?

对标准的聊天模型来说,在需要好几步才能解决的问题上它仍然有帮助,尤其是当提示词本来会催促模型立即作答时。推理模型在回复前会先思考,内部已经在这样做了,所以对它们来说,这句话除了让回复变长以外没什么作用。对这类模型,应该把问题和答案格式说清楚。

思维链什么时候有用,什么时候没用?

它适合需要多个相互依赖步骤的任务:应用题、算术、逻辑谜题、有约束条件的排程,以及推演代码的执行过程。对查询、翻译、改写或简单的分类任务,它帮助不大,只会让回复更长、更慢。

零样本思维链和少样本思维链有什么区别?

少样本 CoT 由 Wei 等人在 2022 年提出,它在提示词中放入带推理过程的解题示例,模型会模仿这种推理风格。零样本 CoT 出自 Kojima 等人 2022 年的论文,不使用示例,只是加上一句“让我们一步一步地思考”之类的指令。零样本写起来更快;少样本则能更好地控制步骤的样子。

模型写出的推理过程,就是它得出答案的真实过程吗?

不一定。这些步骤是模型生成的文本,可能读起来很有道理,最终答案却是错的;也可能某一步有错误,答案却碰巧是对的。把推理过程当作需要检查的内容,而不是证据,并单独核实最终答案。

Coddy 编程语言插图

和 Coddy 一起学编程

开始