
做AI原生开发绕不开Prompt调优我在实际项目里把Few-shot、CoT、ToT这三个技巧反复用了很多轮踩了不少坑才总结出自己的一套用法。这篇就以一个商品评论结构化抽取的实战为例完整拆解这三种高级Prompt技巧的原理、适用边界和组合姿势适合正在用大模型做应用开发、又对输出稳定性和准确率不满意的朋友。先交代一下背景我接到的任务是从电商评论里抽取商品问题点同时判断用户的退货倾向。一开始我写了个一次性Prompt指令写得明明白白“只输出JSON”结果模型时不时给我来一段废话或者把退货倾向判断得特别武断。后来我把Few-shot、CoT、ToT逐个加上去才把问题彻底治住。这中间的过程比任何教程都更能说明问题。1. 为什么普通Prompt不够用三大技巧的底层逻辑1.1 Few-shot给模型“打样”比“讲道理”更有效Few-shot的核心是在Prompt里放几个输入输出对的示例让模型照着样子干活。最初我理解得很浅以为就是“给个例子让模型模仿”后来才发现它远比模仿更底层。大模型训练时见过海量“前文接下文”的文本你给它的每一段内容都会影响它的输出分布。示例的作用是重塑这个分布你扔进去几个“评论→JSON”的配对模型就会倾向于把当前这条评论也映射成类似结构的JSON。这就是为什么示例比指令更管用——指令是抽象的规则示例是具体的分布锚点。这里有个很容易被忽略的细节示例本身同时承担了两个任务。一是显性的告诉模型“我要什么格式”二是隐性的告诉模型“这个问题该用什么标准判断”。比如你给了两条“用户抱怨电池不耐用→退货倾向高”的示例模型就会把“电池”问题和“退货倾向高”关联起来。所以示例不是随便找几条凑数的示例的质量直接决定了模型行为的天花板。工作里我常用3到5条示例太少覆盖不了边界太多会引入噪声。一个原则是示例之间要有足够的差异尤其要包含“反面情况”。比如你要判断退货倾向不能全是“高”的示例至少要有两条“低”的和一条“中”的。这个细节我后面在坑点里细说。1.2 CoT把“想”的过程写进PromptCoTChain of Thought的思路是不直接让模型给答案而是让模型先把推理步骤写出来再基于推理结果作答。最早看到那种“Lets think step by step”的零样本CoT时我还有点不屑觉得是玄学。真到自己跑实验才发现加上这句话复杂推理任务的准确率就是能涨一大截。为什么有效因为大模型的推理和人类做口算题很像两位数的乘法你直接给答案脑子容易打结但拿张纸列个竖式一步一步来错的概率就低很多。CoT就是那张竖式纸——它把一次高难度的隐形推理拆成几次低难度的显性推理每一步的中间结果都暴露在外面。模型在生成“思考过程”时每一步只需要做很小的决策出错的概率被压低了而且一旦出错你还能从中间步骤里找到问题根源。还有一个附加好处CoT的中间推理给了开发者“审计”的抓手。以前模型直接输出结论你只能瞎猜它为什么这么判断。有了推理链你可以要求它引用原文甚至可以只抽取那些“有证据支撑”的结论。这对于做内容审核、金融风控这类对可解释性有要求的场景价值极大。1.3 ToT从“一条路走到黑”到“多路径搜索”ToTTree of Thoughts比CoT更进一步。CoT是一条推理链走到底错了就错了。ToT则在推理的每一步都生成多个候选分支对每个分支做评估、剪枝、回溯相当于在思维空间里做搜索。需要先说清楚一个容易误导人的点ToT不像CoT那句话一样可以在Prompt里直接触发它本质上是个算法骨架需要你在代码里写循环让模型在某个节点生成多个候选方案→让模型或另一个评估器打分→挑出最靠谱的继续往下走。你可能会在不同分支里来回试直到走到一个可靠的终点。我打个比方。CoT是走迷宫时选了一条路就一路走到黑撞墙了才知道错了。ToT是走到岔路口时先派几个分身各探一段路拿回来对照一下再决定走哪条。代价肯定是多跑很多冤枉路但复杂任务里的最终效果往往更稳。把ToT做进生产环境时我通常用它来跑“高风险决策样本”。普通样本用一次推理就够了越是模棱两可的样本越值得多开几条路径做对比。这跟人做判断的逻辑是一样的小事情直接拍板大事情多找几个人商量。2. 技巧选型什么场景用哪个别一锅端2.1 用错场景反而掉精度刚开始用这些技巧时我的心态是“能加就全加”觉得技巧越多效果越好。实测下来完全是另一回事每个技巧都有它不适合的场景。Few-shot在分类任务里有个隐蔽的坑示例的分布会直接污染输出分布。如果你给了3条退货倾向高的示例、1条退货倾向低的示例模型就会倾向于预测“高”因为训练时见过的条件分布里“高”的概率更大。哪怕真实数据里退货倾向低的评论占多数模型也会被你的示例带偏。这件事我自查了很久才发现排查过程后面单独讲。CoT也有翻车的时候。在简单的事实问答或者模板化抽取任务里让模型先展示推理过程纯属浪费token而且还有副作用模型为了凑一个“看起来合理”的推理链可能会凭空编造中间依据。你让它分析评论里的语气它可能给你编一句评论里根本没出现过的描述然后一本正经地基于它下结论。在需要严格忠实原文的场景里这条尤其危险。ToT的问题在于成本和延迟。每多开一条分支就是多一次完整的大模型调用。线上接口如果平均响应时间要控制在2秒以内ToT的分支一多就直接超时。再加上费用一个分支走到底都费钱更别提多分支并行。所以我的原则是只在离线分析、复杂规划、或者是线上风险样本兜底时用ToT普通请求绝不滥用。2.2 一张表理清选择思路我把三个技巧放在一张表里做过对比也贴在下面供你参考技巧核心思想最适用场景成本特征实现难度Few-shot用示例锚定输出分布输出格式要求严格、分类标准明确只需增加示例token低CoT显性化推理步骤多条件判断、数学推理、逻辑分析推理段token开销低ToT多分支搜索与评估复杂规划、多种方案择优、开放问题多次调用成倍开销高选型的时候我一般按三步走。第一步判断任务是不是“一次推理就能出结果”如果只是格式化抽取直接Few-shot就够如果涉及多因素综合判断那就加CoT。第二步看输出有没有“唯一正确答案”有的话优先保证格式和稳定没有的话可以考虑用ToT生成多条候选再筛选。第三步算算账延迟和费用能不能承受多路调用能承受才上ToT不能就老实点用CoT。这个决策流程看着简单但我实际用下来能省掉80%的盲目尝试。我见过很多人一上来就堆技巧结果Prompt越搞越长效果不升反降。记住一个原则先确认问题本质上需要什么再选择对应的技巧而不是手里有锤子看什么都像钉子。3. 实战改造从普通Prompt到组合技巧完整过程3.1 原始需求与初版Prompt一次惨痛的翻车需求背景很简单我有5000条商品评论需要抽取出“商品问题点”和“退货倾向”两个字段后续要拿去做售后分析。当时偷懒随手写了一个Prompt请分析以下商品评论输出JSON包含字段issue商品问题点、return_intention退货倾向值为高/中/低。 评论{评论内容}还加了一句“只输出JSON不要多余内容”。听起来没问题对吧但实际跑下来5000条里大概有25%的输出是不合格JSON有时候是字段名换成了“问题”、有时候是“退货倾向”写成了“退货意愿”还有时候直接输出一大段分析文字后才附上JSON。更烦的是退货倾向这个判断完全随机同一个问题描述换个说法判断就变了。现在回看问题很清楚指令给的是“规则”但模型需要的是“参考坐标”。规则只能约束方向坐标才能约束落点。我当时最缺的就是Few-shot里那几个“坐标”。3.2 第一步加Few-shot先把格式焊死第一条改造是加示例。我基于评论数据挑了几条典型样本覆盖了“高、中、低”三个退货倾向档位同时特意加入了一条“夸赞很多但也有一个小问题”的边界评论。Prompt变成这样请分析以下商品评论输出JSON包含字段issue商品问题点、return_intention退货倾向值为高/中/低。 示例1 评论用了三天就黑屏申请售后一直没人理再也不买这家了。 输出{issue: 屏幕黑屏、售后响应慢, return_intention: 高} 示例2 评论手机整体还行就是电池掉电快其他没毛病。 输出{issue: 电池续航差, return_intention: 中} 示例3 评论包装很好发货快用了一周没有任何问题挺满意的。 输出{issue: 无, return_intention: 低} 评论{评论内容}加了这三个示例之后格式不合格率从25%降到了3%左右说明示例的“格式锚点”作用立竿见影。但退货倾向的准确性还是不行尤其遇到“既夸又骂”的评论模型经常抓不住重点给个“中”完事但人工看下来这明显是“高”。问题出在模型没有经历推理过程直接跳到了结论。这个阶段给我的教训是Few-shot负责“模型做得像不像”但它不负责“模型想得对不对”。要想判断准确得让模型把“怎么得出结论的”这一步露出来。3.3 第二步加CoT逼着模型按评分卡走第二步改造我在JSON输出之前加了一个“分析过程”字段让模型先给出推理再输出结果。结构大概是这样请分析以下评论推理要求 1. 先列出评论中提到的问题点引用原文关键词 2. 针对每个问题点评估严重程度轻微/中等/严重 3. 如果评论中有明确退货、不再购买、投诉等字眼退货倾向直接判高 4. 最后输出JSON包含字段issue、analysis推理摘要、return_intention。这里的重点是“拆步骤”。我没有笼统地说“请一步步思考”而是给了一个带硬性规则的推理路径。比如“有明确退货字眼就判高”这等于在模型脑子里埋了一个决策节点比让它自由发挥要稳得多。跑完之后退货倾向的准确率明显上来了。拿人工抽样的100条数据做对比判断准确率从65%左右升到了82%左右。最主要的变化是一些“语气强烈但问题不严重”的评论以前会被误判成“高”现在模型会先识别出“没有明确退货意愿”然后给出“中”。CoT也不是没有代价。最直接的感受是token消耗涨了约40%因为每条评论都要先生成一段分析文字。另外有些模型在分析过程里会写出一些评论里根本不存在的内容比如“用户提到客服态度差”但评论原文压根没提客服这是模型依据上下文脑补出来的。后面我在Prompt里加了一句“推理只能基于评论原文内容不得补充评论中未出现的信息”情况才有所改善。3.4 第三步用ToT思路多方案对比避免一锤定音CoT改造完之后整体已经能用了但我发现一个顽固问题遇到模棱两可的评论模型一次推理就敢下结论而且每次结论可能还不一样。比如一条“东西不错但客服敷衍”的评论第一次判“中”第二次判“低”波动很大。这时候我把ToT的思路抽出来但没做完整的树搜索而是用了一个轻量级的变体。核心逻辑是对低置信度样本同时生成多个候选推理结果然后汇总投票。实现起来也不复杂def analyze_with_consistency(comment, client, n3): prompt build_prompt(comment) # 复用带CoT的Prompt results [] for _ in range(n): resp client.chat.completions.create( modelyour-model, messages[{role: user, content: prompt}], temperature0.7, # 温度调高一点让候选之间有差异 ) results.append(parse_json(resp.choices[0].message.content)) # 简单投票取return_intention出现最多的值 intention_votes Counter(r[return_intention] for r in results) final_intention intention_votes.most_common(1)[0][0] final_issue merge_issues([r[issue] for r in results]) return final_issue, final_intention这里我用的是类似Self-Consistency的思路同一个Prompt采样多次结果投票。它和完整ToT的区别在于没有中间步骤的显式分支和评估但已经具备了“多条路径对比”的精髓。我实际只对“置信度边界样本”跑这种多方案投票大概占全部数据的20%其余80%样本走一次推理就够了。整体准确率又被拉高了5个百分点左右而且输出稳定了很多不再忽高忽低。如果你要做完整的ToT那还需要在推理中间步骤上做分支。比如让模型先产出3个“问题点清单”对每个清单打一个合理性分数再挑分数最高的清单接着推理退货倾向。那个工程量更大但应对真正复杂的开放问题时效果会更强。这套组合Prompt的完整模板我保存成了固定格式放进了自己的工程模板库。核心结构是任务描述 评分卡推理规则 Few-shot示例 JSON输出要求外加一个“如果对结果不自信就多路采样”的后处理逻辑。后面所有类似的抽取任务我都直接复用这个模板效果都很稳。4. 落地时最容易踩的坑和排查方法4.1 Few-shot示例被模型“抄答案”这是我最先踩到的一个坑花了很久才发现。现象是某一次跑分类任务所有评论的退货倾向都被判定成了“高”。我以为模型抽风了把温度调低、把指令加重全都没用。后来我把Prompt里示例的排列顺序打乱发现结果跟着变了。才反应过来问题出在示例本身——我放了3条“高”的示例1条“低”的示例模型在进行模式匹配时发现样本里的“高”出现频率最高就倾向于输出“高”它把我给的示例当成了正确答案的分布参考。解决方式有三个我都验证过。一是示例里每个类别的数量尽量均衡二是示例顺序要随机打乱而不是同类排一起三是在示例后面加一句“注意示例仅用于说明格式请根据当前评论内容独立判断”。第三句看着简单但对模型的行为纠偏非常有效原理是明确降低了示例标签对输出分布的影响权重。4.2 CoT推理链被模型“脑补”污染CoT最大的副作用就是中间推理会被脑补内容污染。我做过一次分析任务模型在推理过程中写了一段“用户对配送速度表示强烈不满”但评论原文只有“产品很好”四个字配送什么都没提。模型自己给自己加戏然后基于加戏的内容下了个错误结论。我的排查方法是把推理过程和最终结论分开验证。先看推理中引用的信息是否都能在原文找到对应关键词再对照结论是否与推理逻辑一致。后来我用了一个“可溯源”约束强制模型在推理部分的每个判断后面用括号标记原文关键词。比如“用户提到电池掉电快原文电池一天两充”这是一个特别实用的技巧它把CoT从一个“无法验证的自由发挥”变成了“每个结论都有溯源的推理链”。如果模型还是不老实还有一个更狠但有效的办法不用CoT的“边写边想”改成两阶段Prompt。第一阶段只抽取原文证据不判断第二阶段基于证据做判断。证据和判断彻底分离模型就没什么脑补空间了。4.3 ToT多路验证的成本失控ToT类方案最大的坑是成本失控。我第一次跑全量数据的多路投票时账单直接翻了三倍平均每条的响应时间也到了4秒以上这个方案差点被当场否决。我后来的做法是给多路验证加“准入条件”。先用单次CoT推理跑出一个置信度分数比如“退货倾向为高且证据强度达到0.8以上”就直接出结果。只有分数落在边界区间比如证据强度和结论有冲突、或多条问题互相矛盾的样本才进入多路验证流程。这么一整多路验证只覆盖了总样本的20%成本增量被控制在50%以内而准确率的提升得以保留。再补一句如果用了多个分支做投票记得给中间结果加缓存。同一批评论如果要做回归测试模型输出可以缓存下来不用每次都重新调用省下来的时间和钱都非常可观。4.4 把Prompt当代码一样做版本管理最后分享一个习惯这个习惯帮我在多次改造中没有把效果搞倒退。Prompt不是写一次就完事的它和代码一样会持续演进。我在项目里给每个Prompt都建了版本号用“评论分析Prompt v3.1”这样的命名方式管理。每次修改Prompt我不只凭感觉判断“好不好”而是固定用一组回归测试集来验证。这个测试集是从历史数据里抽出来的100条覆盖各种场景的评论包含边界案例、长评论、乱码评论等。每次改动之后跑一遍回归集对比“格式合格率”“判断准确率”“推理可溯源率”这三个指标。只要是这三个指标没有一项下降改动才算通过。这个习惯的回报非常直接有一次我把CoT的Prompt改得更简洁了肉眼看着效果不错但回归测试一跑发现“格式合格率”掉了一点。我一查原来是简化后的推理步骤少了对原文的引用约束。如果没有回归测试兜底这种细小的质量下滑很容易被忽略等积累多了再排查比当时发现要痛苦得多。回归测试还有一个发明式的用法它会慢慢变成一个“小型的验收文档”。团队协作或者交给别人维护时不用从头读需求跑一遍测试集就知道Prompt现在的行为边界。这比我写十页文档都有用。这个组合技巧改造做完之后我现在接手类似的结构化抽取任务第一反应已经不再是“写个Prompt试试”而是先问自己三个问题这是格式问题还是判断问题判断需不需要可解释这个场景能承受多少次模型调用想清楚这三点再决定上Few-shot、CoT还是ToT。这个过程比套用任何现成模板都可靠你按这个思路去试大概率也能少走我走过的这些弯路。