十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

020 思维链(Chain-of-Thought)与提示技巧

020 思维链(Chain-of-Thought)与提示技巧 020 思维链Chain-of-Thought与提示技巧那天晚上十一点我盯着屏幕上那只“假装会算数”的模型输出差点把咖啡泼在键盘上。问题是这样的让模型算“一个农场有17只鸡卖了5只又买了3只还剩几只”——它斩钉截铁地回答“15只”。我反复检查了prompt没有任何歧义温度设成了0给的示例也正确。可它就是在简单加减法上翻了车。更气人的是当我随手在prompt里加了一句“请一步一步思考”同一个模型同一个问题它规规矩矩地算出17 - 5 3 15。那一刻我意识到不是模型笨是我没给它“思考的台阶”。这就是思维链Chain-of-Thought以下简称CoT最原始的魔力——不是改变模型的能力而是激活它已有的推理路径。很多人把CoT理解成“让模型多写几步”这没错但太浅了。CoT的本质是给模型一段“内部推理的显式空间”让它在生成最终答案前先把中间状态写到输出里。Transformer在解码时每一步都基于之前的token如果你逼它跳过中间步骤直接给结果它等于在做一个高维空间的跳跃容易掉进概率的陷阱。而有了CoT那些中间步骤变成了“锚点”把推理过程拉回到可预测的轨迹上。这就好比你让一个新人工程师直接写出系统架构他大概率会漏掉边界条件但你让他先把需求点、约束、依赖一条条列出来再画架构错误率会低一个量级。模型也是这样。但CoT不是银弹。我见过太多人写prompt时机械地在结尾加上“Let’s think step by step”然后发现模型开始废话连篇甚至把不该思考的也思考了。比如你问“11等于几”它给你写一篇小作文什么“首先我们定义自然数然后应用皮亚诺公理……”——这已经不是推理是表演推理。所以真正的技巧在于什么时候该用CoT什么时候不该用以及用的时候怎么控制“思考的深度”。先说你不需要CoT的场景。事实性检索、格式转换、简单映射这类任务直接给答案。你让模型“把这段JSON转成XML”它不需要思考它需要查表和规则。你非给它加CoT它可能会“思考”出一些不存在的字段。还有一类是创作类任务写诗、写故事、拟标题CoT反而会破坏灵感的连贯性。你见过哪个诗人先推理“我要表达悲伤所以用雨然后第二句……”吗那是报告不是诗。需要CoT的场景通常是多步推理、数学计算、逻辑判断、代码调试、复杂决策。但这些场景里CoT的写法也有讲究。最简单的用法是零样本CoT就是那句经典的“Let’s think step by step”。它的原理不是“让模型更聪明”而是通过这个指令把模型从“直接生成答案”的默认模式切换到“先生成推理链”的模式。但零样本CoT有个问题它不知道你想要的推理粒度。有些模型会给出过长的推理浪费token有些则一步带过。所以更稳的做法是用少量示例告诉模型“你想要的思考过程长什么样”。这里我给一个我踩过坑的示例。我想让模型做“多个条件约束下的排程”一开始我写了三个示例每个示例的思考过程都很简略比如“先排A再排B考虑冲突”。结果模型学到的思考风格也是简略的遇到新问题就开始漏条件。后来我把示例里的思考过程写得更细明确标出每一步的“当前已知条件”“可选项”“排除原因”模型的表现立刻上了一个台阶。注意不是示例越多越好而是示例的“思维颗粒度”要和你期望的推理深度一致。模型非常擅长模仿你给样例中的“思维形式”你给粗糙的样例它就粗糙地思考你给严谨的样例它就严谨地思考。这其实是一种隐式的控制——比你在prompt里写“请仔细思考”有效得多。还有人喜欢用“自我一致性”来增强CoT就是让模型采样多条推理链然后投票选最终答案。这个技巧在数学推理和常识推理上效果很好尤其在GPT-4级别的大模型上能把准确率再提一档。但代价是成本翻几倍。我一般只在关键路径上用比如处理用户提交的复杂工单分类或者从日志里定位根因。普通问答就别用了响应时间受不了。另一种进阶技巧叫“思维树”就是把CoT从一条链扩展成多分支搜索。但说实话在纯提示工程层面思维树需要你手动设计分支和回溯条件复杂度高而且容易把prompt写成一坨屎。我更推荐把它交给Agent框架去做决策规划而不是在一次性prompt里模拟。作为工程师你要清楚边界提示工程能解决的是“单轮推理深度”问题而“多步探索”应该交给外部循环。代码里写CoT我习惯用注释来控制模型的行为。比如# 这里让模型先列推理步骤再给结论promptf 你有以下配置项 - 数据库连接池上限:{max_conn}- 当前活跃连接:{active_conn}- 每查询需要连接:{conn_per_query}- 新请求到达速率:{req_rate}请判断系统是否需要扩容。先列出你考虑的指标和计算过程最后给出建议。 这个prompt没有写“Let’s think step by step”但通过“先列出……计算过程”把思考路径指定了。效果比那句话更明确因为它还暗示了“最后给建议”让模型知道思考的终点在哪。我曾经把“最后给建议”误写成“然后给建议”模型就多输出了一段“另外我还建议……”的补充内容把格式搞乱了。所以这类指令用“先”和“最后”来框定范围不要用“然后”这种开放式连接词。还有一个容易踩的坑CoT和few-shot混用时的顺序问题。我反复测试过示例的顺序会影响模型对思考模式的关注权重。如果把“标准答案”放在“思考过程”前面模型容易只学答案忽略过程。所以示例里每一步思考过程必须先于最终答案而且最终答案要用统一格式比如“因此答案是”。这样才能让模型把“思考”和“结论”解耦。另外示例中的思考过程不要出现互相矛盾的口径比如一个示例用“第一步”另一个示例用“首先”模型可能会学到“思考过程的开头词不重要”进而降低推理的稳定性。我倾向于所有示例统一用“步骤1/步骤2/步骤3”的编号连标点都保持一致。再说一个容易被忽视的点CoT在中文和英文上的表现差异。我观察下来同样的问题用中文写CoT模型的推理链可能不如英文清晰尤其是在一些逻辑关系复杂的场景。这未必是模型能力问题可能是训练语料中中文的推理链数据比英文少。一个补救办法是在prompt里用中英混合的指令比如“请按以下步骤思考Step by step”有时候能激活更强的推理模式。但不要过度否则显得不伦不类。我之前在一个工业报表生成任务里就把“先汇总各分项数据”写成“Step 1: 汇总各分项数据”结果输出的推理链工整了很多。大家可以在自己的任务上对比试试。CoT还有一个变种叫“少样本思维链”也就是在few-shot里不仅给出输入和输出还给出中间步骤。这本质上是在教模型“在这个任务上思考方式长这样”。但我发现很多人只给一个示例然后期待模型学会所有情况。实际上一个示例只能确定一种推理模式如果任务有多个子类型你需要为每个子类型给一个带思维链的示例。比如分类任务有正常情况、边界情况、异常情况你至少得各给一个。否则模型就会把“一种推理模式”泛化到所有输入上那是灾难。我踩过这个坑让模型区分内存泄漏和CPU飙高我只给了内存泄漏的推理链示例结果CPU飙高也被它按“内存分配失败”去解释了。后来补上CPU的示例它才学会按“先看指标再分特征”的通用逻辑走。更玄的一点是CoT会受prompt里“人格设定”的影响。你给模型设定成“一位严谨的数学教授”它的推理链会更长更规范设定成“一位经验丰富的运维工程师”它的推理链更偏向“先看表象再查根因最后给出应急措施”。这说明CoT不只是机械地展开步骤它还会被角色认知塑造。所以不要小看那句“你是一个……”的system prompt它和CoT是协同作用的。我在做日志分析Agent时把系统提示从“你是一个智能助手”改成“你是一个有十年经验的SRE遇到故障时习惯先确认影响范围再分析日志”然后配合CoT指令根因定位的准确率有了肉眼可见的提升。最后说说我在生产环境中总结出的几条实用经验。第一CoT的输出长度要设限。给max_tokens留出足够余量但不要无限大否则模型可能陷入“思考的深渊”反复咀嚼同一个点。我一般给CoT预留的token是最终答案的35倍。第二用\n分隔步骤不要用. “或”; 。步骤之间用换行模型的解码更稳定而且后续如果要解析推理链换行也是天然的切分点。第三遇到模型推理出现幻觉不要急着换模型或调温度先检查你的示例里有没有给出“错误的中间步骤”。模型会忠实复制你的推理链风格包括错误风格。我曾经在一个prompt里把“用户欠费”写成了中间判断条件结果模型在推理时对所有订单都先检查“是否欠费”把一个简单的年龄筛选任务搞出了完全无关的逻辑。第四对你的CoT做测试时不要只看最终答案要看推理链中的关键中间节点是否和预期一致。如果中间节点错了但答案碰巧对了那这个CoT是不可靠的需要调整。写到这里我想起那个深夜的调试。那时我只知道加一句“请一步一步思考”就能救场后来才明白那句话只是推开了一扇门——门后是推理粒度、示例设计、步骤格式、人格协同、输出控制这一整个工具箱。当你能根据任务类型自由地塑造模型的思考路径时提示工程才算真正入了门。CoT不是咒语它是你与模型之间一套心照不宣的“草稿纸协议”。你会写草稿吗不是把数字乱涂而是把关键的中间结论一行行列出来让错误无处藏身。给模型一张清晰的草稿纸它就能给你可靠的答案。这张纸怎么画比画什么更重要。
返回列表