调提示词这件事,业余做法是”感觉不对就换种说法”,工程做法是把影响输出稳定性的变量一个个固定下来。下面这六个技巧不是什么秘籍,它们的共同点是:减少模型需要猜测的空间。模型猜测越少,输出方差越小。
每个技巧后面都附了可直接复制改造的提示词片段。
一、角色与任务边界:先说清”你是谁、要做什么、不做什么”
模型对开头几句话的权重很高。一个清晰的角色 + 任务声明,能立刻把输出分布收窄到你想要的范围。角色不是为了”演戏”,而是为了激活对应的表达习惯和知识调用模式。
任务边界要有三层:做什么、输入是什么、不要做什么。
你是银行核心系统的资深 SRE。你的任务是根据我提供的告警日志,
输出初步的故障分类和排查步骤。
输入格式:一段原始告警文本,可能包含多条日志。
输出要求:只给出分类和排查步骤,不要给出修复命令。
禁止:
- 不要臆测日志中没有提到的系统状态
- 不要输出免责声明或"建议联系管理员"之类的套话
“禁止”清单单独列出来比混在正文里更有效,模型对显式约束的遵从度明显高于隐含期待。
二、明确输出格式:用结构把自由发挥的空间压掉
自由文本是最不稳定的输出形式。只要下游要解析、入库或展示,就应该把格式要求写死。
结构化文本版:
输出以下三个小节,标题严格使用:
## 分类
## 证据
## 下一步
每个小节不超过 3 句话。证据小节必须引用日志原文中的片段。
JSON 版(对下游解析更友好):
{
"type": "object",
"properties": {
"category": { "type": "string", "enum": ["network", "db", "app", "unknown"] },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
"evidence": { "type": "array", "items": { "type": "string" } }
},
"required": ["category", "confidence", "evidence"]
}
很多接口支持直接传 JSON Schema 约束输出(有些实现里叫结构化输出或 response_format),比在提示词里写”请输出 JSON”可靠得多,因为它在解码层面就限制了语法,不会出现字段名拼错、多了尾巴解释文字这类问题。能用 Schema 约束的场景,就不要靠模型自觉。
三、给示例:few-shot 比描述更省事
有些任务的”正确输出”很难用文字描述清楚,但示例一看就懂。这种场景直接给几个输入输出对(few-shot),比写三段定义有效。
把用户反馈归入以下标签之一:bug、体验、性能、其他。
示例:
输入:登录页转圈十几秒才进得去
输出:性能
输入:点击导出按钮没反应
输出:bug
输入:能不能加个深色模式
输出:体验
输入:你们这个东西真难用
输出:其他
现在处理:
输入:{{用户反馈文本}}
输出:
示例的选取比数量重要:覆盖面比堆数量有用。三个边界清晰的示例,胜过十个同质化的示例。如果任务包含容易混淆的类别,专门给一对”看起来像 A 其实是 B”的示例,效果立竿见影。
四、分步思考:CoT 什么时候值得用
链式思考(Chain-of-Thought,让模型先写出推理步骤再给结论)在多步推理、数学、复杂逻辑题上确实有帮助。但它不是免费的:
- 输出 Token 数显著增加,延迟和成本跟着涨。
- 中间步骤出错时,错误会被放大——模型顺着错误前提一路推到底。
- 有时模型写出的”推理步骤”是事后编的,并不是它真正的计算过程。
实用的判断标准:任务是否需要多步中间状态?
- 需要(多条件筛选、单位换算叠加、代码走查)→ 让它先列步骤,或用”先输出分析,再输出结论”的两段式结构。
- 不需要(分类、抽取、改写、格式转换)→ 直接要结果,别画蛇添足。
折中做法是”隐藏推理、只显结论”:要求模型先在心里过一遍步骤,只输出最终结果。有些接口提供了专门的推理控制参数,可以直接调节推理预算,属于同一类思路。
分析这个问题需要分几步考虑:
1. 识别日志里的时间戳与错误码
2. 对照错误码表确定错误类别
3. 检查是否有多个错误叠加
请按上述步骤分析,最后只输出 JSON 结果,不要输出分析过程。
五、约束与负面清单:把”常见坏输出”提前堵死
模型的输出缺陷往往是可预测的:爱加免责声明、爱开头复述问题、爱结尾升华、爱加”希望这对你有帮助”。这些都可以提前堵:
输出约束:
1. 直接开始回答正文,不要复述问题
2. 不要使用生硬的顺序连接词(比如那套"先这样、再那样、最后收尾"的模板腔)
3. 不要输出任何总结性段落
4. 不确定的地方写"[待确认]",不要猜测
5. 长度控制在 300 字以内
约束写作技巧:可检验、可计数、可判定。”写得专业一点”是不可检验的,”不要使用第一人称”是可检验的。后者才能被稳定执行。
负面清单(禁止事项)和正面清单(必须包含的要素)最好成对出现。只写”不要 X”,模型可能躲到”Y”上,而 Y 也不是你想要的。
六、温度与确定性:先冻结,再放开
这一步和提示词文案无关,但对稳定性的影响比改措辞大得多:
- 生成结构化输出、分类、抽取、代码 →
temperature=0(或该接口的最低值),配合固定格式约束。 - 生成创意文案、头脑风暴、多版本变体 → 适当调高温度,同时接受输出方差。
注意,temperature=0 不代表”完全确定”。很多推理栈在 GPU 上存在非确定性算子,同样的输入在不同时刻可能有细微差异。如果业务要求严格的可复现性(比如回归测试),除了温度,还要记录并固定:模型版本、system prompt 全文、输入的最终拼接结果、接口参数。把”请求指纹”存下来,出了问题能重放。
七、输出校验与重试循环:模型不是终点,是流水线的一环
再好的提示词也会有失败输出。工程上的兜底做法是:把模型输出当作不可信输入,走一遍校验,失败就重试或降级。
for attempt in range(3):
raw = llm.call(prompt, temperature=0)
result = parse_and_validate(raw) # JSON 解析 + Schema 校验 + 业务规则检查
if result.ok:
return result.data
prompt = add_feedback(prompt, result.errors) # 把上次的错误回喂给模型
return fallback_response()
校验分三层:
- 语法层:是不是合法 JSON,字段是否齐全。
- Schema 层:类型、枚举取值、数值范围是否符合约定。
- 业务层:分类结果是否在预定义类别里、引用的日志片段是否真的存在于原文、长度是否超限。
重试时把上次的错误信息带上(”上一次输出的 confidence 是 1.5,超出 0~1 范围,请修正”),修复率比单纯重新生成高。重试次数要有上限,超过就走降级路径(返回默认值、转人工、落日志),别让重试循环变成死循环。
把六个技巧串起来
一套稳定的提示词模板,结构大致长这样:
[角色与边界] → [输入说明] → [示例] → [约束与负面清单] → [输出格式/Schema]
参数层冻结 temperature,外面套一层校验重试。这个组合拳跑起来之后,你会发现需要”调提示词”的次数明显变少——因为剩下的问题大多出在数据和校验层,而不是措辞层。提示词工程的终点,恰恰是不再需要频繁改提示词。
Comments (2)
把抽象概念讲具体了,这点很关键。
这个思路让我重新想了一遍自己的做法。
Please Sign in to join the discussion.