提示工程
简介
用例子说明提示工程是什么?
当使用 “The sky is” 作为提示时,模型可能会输出 “blue” 或 “falling”,但如果提示是 “补全英文教材中的句子: The sky is”, 模型更可能输出我们期望的颜色 “blue”。 提示工程就是通过设计和优化这些输入提示来引导模型产生更符合预期的输出。
相关资料
模型设置
各常用模型设置如何影响输出质量?
- Temperature:控制输出的随机性。较低温度(如0.2)会使输出更确定和一致,而诗歌等创意任务可能需要较高温度(如0.8)来增加多样性。
- Top-p:控制输出的多样性。较低的top-p(如0.1)会限制输出在更小的概率分布内,而较高的top-p(如0.9)允许更多可能性。和温度统称为核采样,调节核采样参数时一般二选一。
- Max tokens:限制输出的长度。较短的max tokens(如50)适合简短回答,而较长的(如500)适合详细解释。
- Stop sequences:定义输出的终止条件。可以设置为特定的标点符号或词组,以控制输出的结束位置。
- Frequency penalty:对重复(下个 token 占已响应内容该 token 出现次数的比例)施加惩罚,以减少产生重复内容。
- Presence penalty:对重复的词施加惩罚,重复多次的惩罚权重和重复一次的权重相等,以鼓励模型使用更多新词。
Temperature=0 不保证确定性输出
主流推理框架(如 vLLM、TensorRT-LLM)的 temperature=0 实际映射为一个极小的正数(如 1e-7),采样路径仍受 floating-point 舍入误差和硬件差异影响。更隐蔽的是,
开启 continuous batching 或 prefix caching 时,KV-cache 的内存布局差异会导致 softmax 前的 logits 发生微小漂移,同一请求在不同负载下可能选出不同的 argmax token。
若业务需要严格可复现性(如金融合规对账、测试回归),仅靠 Temperature=0 不够,必须显式设置 random seed 并使用 deterministic sampler, 同时禁用 dynamic batching 和 CUDA graph 的异步调度。
Temperature 与 Top-P 的作用域错位
Temperature 与 Top-P 并非随机性的简单叠加,而是分阶段组合:温度作用于 logits(softmax 前),Top-P 作用于概率分布(softmax 后)1。
文档常见的 Temperature=0, Top-P=0.9 推荐在理论上是矛盾的——温度归零后分布应坍缩为单点,Top-P 的 90% 阈值已无意义。但在浮点实现的缝隙里,这一组合仍可能因数值精度引入微量抖动2。
反过来,高温度把分布压平后,Top-P=0.9 可能一次性放进来几千个候选词,输出质量断崖式下跌。生产环境中「模型突然胡言乱语」的事故,根因往往在此。
生产调参的常见陷阱是:看到输出太随机就同时压低 Temperature 和 Top-P,或看到输出太死板就同时推高两者,却未意识到它们的交互是非线性的。正确的做法是先固定一个参数调另一个,并监控实际保留的候选词数量( effective vocabulary size)而非只看超参数值。
temperature 并非越高越好
Self-Consistency 依赖多次采样的多样性来覆盖不同推理路径,但 temperature 过高会引入与问题无关的噪声,反而降低投票有效性。过高的 temperature 下,模型可能不是因为走了另一条合理解题路径而给出不同答案, 而是单纯生成胡言乱语。这些噪声路径增加了答案分布的离散度,却不贡献有效纠错。不同任务的甜蜜点不同,数学题可能在 0.5–0.7,开放式任务可能略高,但需要通过实验确定,而不是盲目拉到 1.0 以上。
推理模型 temperature 是结构级参数
OpenAI GPT-5.x 等推理模型在 reasoning.effort != "none" 时会直接拒绝 temperature 参数,这不是 bug,而是参数语义的切换。
普通模型里 temperature 控制的是最终输出 token 的采样随机性;但在推理模型里,真正的随机性来自内部 reasoning token 的生成过程,最终答案往往是内部思考收敛后的确定性产物。你能调的不是"让它更发散或更保守",
而是 reasoning.effort 与 max_output_tokens 之间的分配比例——前者决定模型愿意想多久,后者决定总预算天花板,二者共同塑造了输出质量与成本结构。
JSON Mode 仍会输出代码块标记
开启 response_format: { type: "json_object" } 后,模型输出的内容在语法上确实是合法 JSON,但直接丢给 JSON.parse 仍然可能抛异常。L1 层面的现象是:
模型常在 JSON 外套一层 markdown 代码块标记(json ... ),或在 JSON 前后追加解释性文字如"以下是您请求的数据"。L2 层面,这与文档中"保证合法 JSON"的表述形成认知落差——
文档承诺的是模型会生成合法 JSON 对象,而非输出流中只包含 JSON 且不含任何包装字符。很多开发者因为读了文档就省略了清洗步骤,结果生产环境的 parse 失败率并不低。L3 层面的策略是:
任何从模型返回的字符串在 parse 之前都必须经过防御性清洗——先用正则剥离可能的 markdown 标记,再截断尾部非 JSON 内容,最后才执行 parse。不能因为有 JSON Mode 就假设输出可以直接消费。
Schema 约束保的是格式不是语义
Structured Outputs 的核心保证是字段类型与 JSON Schema 声明一致:age 一定是 int、email 一定是 string、is_active 一定是 bool。L1 层面的事实是,
它绝不阻止模型输出 age: 999 或 email: "abc"——类型正确但语义荒谬的幻觉在严格 Schema 下不仅可能发生,反而更难被发现。L2 层面,这与 JSON Schema 的能力边界有关:
type 约束只能验证数据形态,enum、minimum、format 等约束虽然可以收紧,但模型仍可能在合法范围内输出无意义值;更深层的问题是业务层常把"Schema 校验通过"等同于"数据质量合格",从而跳过二次校验。
L3 层面的策略是:Schema 合规只是第一道关卡,类型校验通过后必须追加语义校验层——为数值字段设置合理范围、为字符串字段设置正则或枚举白名单、为关键业务字段设置人工复核阈值。
不能把"100% 符合 Schema"理解为"100% 可用"。
必填字段过多会逼模型编造参数
Function Calling 的 required 数组如果填得太满,当用户 query 信息不足时,模型不会拒绝调用,而是会硬凑参数来满足 Schema。L1 层面的典型表现是:用户只说"查一下订单",
但 product_id 是必填字段,模型可能输出 product_id: "unknown"、随机字符串、甚至从上下文中 hallucinate 一个看似合理的值。L2 层面,这反映了模型训练目标与 Schema 约束之间的张力—
—模型被优化为"满足用户请求"和"满足工具 Schema",当两者冲突时,它倾向于选择"撒谎"来避免调用失败,而不是表达不确定性。L3 层面的工程正确做法是:把不确定的字段设为 optional 并给合理的 default 值,
让模型在信息缺失时有退路;或者设计显式的"未知"枚举值(如 "product_id": "__NOT_PROVIDED__"),让下游逻辑能识别出这是信息不足而非真实数据。
不要让模型在"违反 Schema"和"编造数据"之间被迫选择后者。
提示技巧
常见的提示技巧?
- 零样本提示:在一些常识性任务中,零样本提示的效果可能要比少样本更好,因为少样本非常依赖样本质量和相关性。
- 思维链(CoT):通过引导模型逐步推理,提供中间步骤和思考过程,帮助模型更好地理解任务。比如:“请先思考这个问题的关键点,然后给出答案:如果一个人有5个苹果,他吃掉了2个,还剩多少个苹果?”。
- 自我一致性提示:通过给定多个推理示例,替换 CoT 过程的不确定性。
- 生成知识:通过提供相关背景信息或上下文,帮助模型更好地理解任务。比如:“在讨论气候变化时,请考虑以下因素:温室气体排放、全球变暖、极端天气事件等。”。
- 思维树(ToT):结合 BFS 和 DFS 的思维方式,如:”假设三位不同的专家来回答这个问题。所有专家都写下他们思考这个问题的第一个步骤,然后与大家分享。然后,所有专家都写下他们思考的下一个步骤并分享。以此类推, 直到所有专家写完他们思考的所有步骤。只要大家发现有专家的步骤出错了,就让这位专家离开。”。
显式 CoT 会挤压推理预算
推理模型内部已经有一层隐式 CoT(reasoning tokens)。当你再写"请一步步思考"时,模型可能把一部分本可用于问题求解的 token 预算,挪去给"解释自己正在一步步思考"做表面表演。其机制在于: 上下文窗口和输出 token 预算是有限的,任何无法为内部搜索提供新信息的指令都在占用资源。结果是正确率没提升,latency 和成本却上去了。
OpenAI 官方对 o-series 模型的指导明确表述:这些模型在信任其固有推理能力而非指导推理过程时表现最佳。添加 CoT 指令不会改善内部搜索,反而会在上下文窗口中增加噪音。
见:OpenAI Reasoning Models 文档、Prompting Reasoning Models Differently - Tian Pan
Few-shot 示例对推理模型是负样本
普通模型靠 few-shot 做模仿学习,但推理模型是 RL 自举训练出来的,已经内化了特定的推理路径和风格。外部示例的思考方式如果与它内部的"成功模式"不一致,就会把它从最优搜索路径上拽开。 DeepSeek-R1 和 OpenAI 的官方 benchmark 都倾向于 zero-shot 评测,因为标准 few-shot CoT 演示会持续拉低性能。你的示例在这里不是"参考",而是噪声。
DeepSeek-R1 技术报告显示,该模型通过大规模强化学习训练,其评估基准采用直接推理而不使用演示。工程上应默认对推理模型使用 zero-shot,仅在消融测试证明有效时才添加示例,且需确保示例与期望输出格式精确匹配。
见:DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning、Prompting Reasoning Models Differently - Tian Pan
System Prompt 长度与推理质量非单调
对指令模型来说,更详细的 system prompt 通常是正收益;对推理模型则是 tax。过长的 system prompt 会引入多个竞争目标,让模型把内部搜索的精力花在"满足约束清单"上,而不是探索最优解。同时, system prompt 占用的上下文窗口会挤压 reasoning tokens 的可用空间——OpenAI 官方明确说明 reasoning tokens 同样计入 context window。存在一个隐式的"指令冗余阈值", 一旦越过,复杂任务的推理质量会明显下滑。短、目标导向的 prompt 往往效果更好。
Claude 对 extended thinking 的指导特别指出:详尽的 system prompt 会以降低复杂任务质量的方式约束推理搜索空间,最佳做法是简短、目标聚焦的提示,说明需要什么而非如何获得。
工程上建议将 system prompt 控制在几百词以内,优先保留核心角色设定和关键约束,其他细节通过工具、模板或后续指令承载。若存在目标层级(正确性 > 格式 > 冗长度),应显式声明而非依赖顺序暗示。
见:Building with extended thinking - Claude API Docs、Prompting Reasoning Models Differently - Tian Pan
剪枝阈值存在非线性悬崖效应
ToT 文档推荐的剪枝阈值(如 5)看似温和,但 LLM 对中间步骤的评分往往呈”扎堆分布”——大量候选集中在 4~6 分区间。L1 层面的现象是:阈值从 5 调到 6 时,被剪掉的节点可能不是线性的 20%,而是断崖式的 60%。 L2 层面更隐蔽的是,低分节点的子节点可能反而包含正确路径,因为早期步骤的”错误方向”有时恰好是后期跳脱局部最优的关键。L3 层面的工程正确做法是:剪枝策略必须引入动态阈值或分层评估机制,不能依赖高方差的单一评分做不可逆决策。
Beam Search 以牺牲回溯性换取成本缩减
Beam Search 将 ToT 的推理成本从 100x 压缩到 10x,但 L1 层面的代价是 current_beam 完全丢弃了非 Top-K 的历史路径。L2 层面,ToT 的核心价值本在于”可回溯、可修正”,
而 Beam Search 把它退化成了带宽度限制的深度优先搜索——当问题需要早期试错、后期顿悟时(如数学证明中先假设错误引理再反向修正),Beam Search 会永久剪掉那些初期评分不高但后期爆发的路径。L3 层面的选型原则是:
如果业务场景确实需要回溯能力,Beam Search 不是优化而是功能降级,此时应保留完整树结构或采用可回溯的变体算法。
自评估器对非主流路径有系统性偏见
ToT 代码中的 evaluator(thought) 在工程实践中通常就是调用同一个 LLM 给自己打分。L1 层面的现象是:LLM 倾向于给”看起来合理、表述流畅、符合常见模式”的中间步骤打高分,而对”形式怪异但逻辑正确”
的路径打低分。L2 层面的机制在于,评估器与生成器同构导致认知偏差自我强化——搜索过程不断收敛于保守解,创新性的非标准思路在评分阶段就被系统性压制。L3 层面的缓解策略是:评估器和生成器应当解耦(使用不同模型或不同 prompt),
甚至引入显式的”多样性奖励”来对抗评分趋同性。
- 增强检索(RAG):通过检索相关文档或信息,增强模型的知识基础。比如:“请从以下文档中提取相关信息来回答问题:xxx。”。
- ReACT:使用行动-观察-思考的循环,如:“请按照以下格式解决问题:思考:分析目前情况,进行必要推断。行动:执行一个具体步骤,如推理、查询、计算、判断等。观察:评估行动结果,决定下步策略。反复循环,直到解决问题。”。
- 元提示:专注于任务与问题的结构与句法,而非其中具体内容细节。
Self-Consistency 的系统性偏差陷阱
Self-Consistency 的隐含假设是错误答案随机分散、正确答案能通过多条路径收敛。当模型存在系统性偏差时,这一假设完全失效。模型对某类问题(如特定数学运算符、某年代历史事件) 因训练数据分布偏差或 prompt 中的示例诱导了固定偏差,始终产生同样的错误推理路径,多次采样的结果会高度一致地指向同一个错误答案,多数投票不仅无法纠偏,反而会给错误结果赋予更高的"置信度"。 这与 Self-Consistency 的数学基础——独立同分布误差的统计抵消——直接冲突:系统性偏差是相关误差,不满足大数定律的收敛条件,投票次数再多也无法收敛到正确答案。
在高风险场景下,不能把高一致性分数等同于高可信度。识别此类问题的唯一方式是对一致性结果做分层分析——当多个答案完全一致但用户反馈为错时,应将该 query 标记为"一致性幻觉",触发人工复核而非自动放行。同时, prompt 设计阶段应审查示例是否存在诱导性偏差。
答案归一化是投票前的隐形门槛
Self-Consistency 投票前通常需要增加一层答案归一化,否则语义等价但文本不同的答案会被拆票,一致性信号被稀释。真实场景中,同一张卷子可能同时收到 "5"、"5个"、"每人5个"、"五" 甚至 "five" 这样的答案, 它们在语义上等价,在文本层面却被当成不同选项分别计数。更隐蔽的是,如果几种等价表述恰好落在不同候选答案上,投票结果会直接从"一致"变成"分散"。因此工程上需要在投票前用规则、正则或 embedding 把语义等价答案合并, 否则 Self-Consistency 的收益会被语言表达能力差异吃掉。
早停会系统性高估置信度
Self-Consistency 的早停机制在答案占比达到 threshold 时立即停止,看似节省了 token,但报告的 confidence 经过条件筛选,系统性偏向乐观。只有当某答案已经占到足够高比例时才会触发停止, 因此早停样本的 confidence 被截断在一个乐观区间;而真正摇摆的样本会一路采样到 max_n,其置信度反而更低。这两组 confidence 本质不可比:前者是"条件于已达标"的筛选后结果,后者是"固定采样 n 次后的真实比例"。 若把它们混在一起做下游决策(例如"confidence<0.7 转人工"),会系统性把应该谨慎处理的样本漏过去。
否定性约束会触发"白熊效应"
System Prompt 中大量"不能做 XX"的否定性约束,在 LLM 注意力机制中的处理效果远比表面直觉差。L1 层面,神经语言模型对"不要"的理解天然不稳定——否定不是简单的逻辑取反,而是需要在整个语义空间重新计算概率分布, 这种计算在自回归生成中容易"泄漏"。L2 层面,禁止词反而会提升对应概念在生成过程中的激活强度,形成心理学上的"白熊效应":你告诉模型"不要提竞品价格",模型在相关话题附近反而更容易触发这个禁忌, 因为禁止指令把目标概念推入了模型的"工作记忆"。L3 层面的工程正确做法是将否定性约束转换为肯定性的封闭域定义,把能力边界从"黑名单"切换为"白名单"——用"你只回答以下产品型号"替代"不能回答竞品价格", 用"输出严格遵循 JSON Schema 中声明的字段"替代"不要输出 Schema 以外的字段"。
置信度自评估是虚假安全感
让模型按置信度阈值做路由决策是一种看似聪明实则危险的策略。L1 层面,LLM 的自我置信度报告与真实准确率之间只有弱相关性,模型常在错误答案前礼貌地加上"仅供参考"的免责声明,形成"虚假的谦逊"——它并非真的知道自己在犯错, 而是在训练中学到了在不确定时附加免责措辞的模式。L2 层面更隐蔽的是团队层面的认知陷阱:系统看似具备"自知之明",导致人工审核环节放松警惕,把本该拦截的错误答案放行到用户面前。L3 层面的策略是,真正有效的路由决策应在编排层用独立模块完成— —答案一致性检查、检索相关性打分、或专门的验证模型,替代模型的自我评估作为路由依据。模型的置信度只能作为辅助信号,不能作为决策主干。
Footnotes
- 采样参数的分阶段作用机制,见 Prompt Engineering Guide ↩
- 浮点精度对 softmax 输出的影响,见相关数值分析文献 ↩