Prompt Engineering 提示词工程详解

提示词工程详解

提示词工程 不是给模型念咒,也不是把一句话写得更客气。它真正解决的问题是:怎么把人的模糊意图,翻译成模型能稳定理解、稳定执行、稳定校验的任务说明。

如果说 LLM 是一个能力很强但容易“顺着话跑”的协作者,那么 Prompt 就是你给它的任务单。任务单写得含糊,结果就靠运气;任务单写得清楚,模型才有机会稳定地做对。

本文脉络:

  • 一、提示词工程到底是什么
  • 二、为什么同一个模型,换个提示词差别很大
  • 三、一个好 Prompt 的 7 个零件
  • 四、角色设定:不是扮演,而是限定视角
  • 五、上下文管理:给足信息,但别把噪声全塞进去
  • 六、输出约束:让结果可读、可用、可解析
  • 七、Few-shot:用示例告诉模型“照这个风格来”
  • 八、思考过程与分步任务:让复杂问题可控
  • 九、面向 Agent 的 Prompt:还要考虑工具和状态
  • 十、提示词评估与迭代
  • 十一、常见问题

一、提示词工程到底是什么

很多人第一次接触提示词工程,会把它理解成“怎么把一句话写得更厉害”。比如:

帮我写一篇文章。

改成:

你是一名资深技术作家,请用专业、深入、通俗易懂的方式,帮我写一篇高质量文章。

这当然比第一句好一点,但还远远谈不上工程。

真正的提示词工程关心的是这几个问题:

问题 例子
目标是否清楚 到底要写文章、改代码、总结会议,还是生成 JSON?
上下文是否够用 读者是谁、业务背景是什么、输入数据在哪里?
边界是否明确 哪些内容不能编、哪些假设要说明、哪些操作不能做?
输出是否可用 要 Markdown、表格、SQL、代码,还是结构化 JSON?
质量能否评估 怎样算回答好?怎样算失败?

所以我更愿意这样定义:

提示词工程,是围绕 LLM 输入输出建立的一套任务表达、上下文组织、约束设计和结果评估方法。

它的目标不是“骗模型变聪明”,而是减少歧义,降低随机性,让模型更容易按你的真实意图工作

二、为什么同一个模型,换个提示词差别很大

LLM 不是传统函数。传统函数的输入很明确,sum(1, 2) 只能返回 3。但自然语言输入有大量隐含信息。

你说:

帮我优化这段代码。

模型需要猜很多事:

  • 优化性能,还是优化可读性?
  • 可以改接口吗?
  • 要不要保持兼容?
  • 代码运行环境是什么?
  • 需要解释修改原因吗?
  • 输出完整文件,还是只输出 patch?

你没说,模型就会猜。它猜得对,你觉得它聪明;猜错了,你觉得它不靠谱。

提示词工程的第一原则就是:不要让模型猜关键条件

当然,也不是所有条件都要写满。简单任务可以简单写,复杂任务才需要完整结构。比如“把这句话翻译成英文”不需要 20 行 Prompt;但“帮我生成一份用于生产环境的数据迁移方案”,最好把约束、风险、回滚、验收标准都写清楚。

三、一个好 Prompt 的 7 个零件

一个可复用的 Prompt,通常由 7 个零件组成。

一个可复用 Prompt 的 7 个零件

零件 作用 示例
角色 限定回答视角和专业标准 你是一名后端架构师
目标 说明最终要交付什么 设计一个订单查询接口的限流方案
上下文 提供背景、资料、业务限制 QPS 峰值 2 万,Redis 可用,接口读多写少
输入 待处理的数据、文本、代码 下面是当前接口代码
约束 明确不能做什么、必须注意什么 不允许引入新中间件,不改数据库表
输出格式 让结果可读、可解析、可执行 按“方案 / 风险 / 代码”三部分输出
验收标准 定义怎样算合格 必须覆盖超时、降级和监控指标

把它们合起来,一个工程化 Prompt 可以长这样:

你是一名资深后端架构师。

目标:
为订单查询接口设计一套限流与降级方案。

上下文:
- 当前峰值 QPS 约 20000
- Redis 集群可用
- 接口读多写少,允许部分非核心字段降级
- 不能新增 Kafka、MQ 等新中间件

输入:
下面是当前接口的调用链路和关键代码:
{code_or_context}

约束:
- 不修改数据库表结构
- 不影响核心订单状态字段返回
- 必须说明失败场景和回滚方式

输出格式:
1. 推荐方案
2. 关键流程
3. 伪代码
4. 风险与监控指标

验收标准:
- 能解释为什么选择该方案
- 覆盖限流、降级、超时、监控
- 给出可落地的参数建议

你不一定每次都要写成这个模板。但只要任务开始变复杂,就应该检查:我是不是漏了目标、上下文、约束或验收标准?

四、角色设定:不是扮演,而是限定视角

“你是一名资深专家”是最常见的 Prompt 句式,也是最容易被滥用的一句。

角色设定不是为了让模型进入某种神秘状态,而是为了告诉模型:用什么标准判断答案好坏

比如同样是“解释 RAG”,不同角色会给出不同答案:

角色 回答重点
面向初学者的技术作者 少术语、多类比、先讲直觉
后端架构师 系统组件、延迟、缓存、稳定性
算法工程师 Embedding、召回、重排、评估指标
产品经理 用户场景、成本、体验、边界

所以,角色要具体到任务,不要只写“专家”。

更好的写法:

你是一名有生产系统经验的 AI Agent 工程师。
请从工程落地角度解释这个方案,重点关注稳定性、可观测性、失败恢复和成本。

不太好的写法:

你是世界顶级 AI 专家,请给出最专业、最全面、最高质量的回答。

后者听起来很强,但信息量很低。模型仍然不知道你要它按什么标准取舍。

五、上下文管理:给足信息,但别把噪声全塞进去

提示词不是越长越好。长 Prompt 最大的问题不是浪费 token,而是噪声会稀释重点

上下文管理要回答三个问题:

问题 判断方式
该给什么 和当前任务直接相关的信息
不该给什么 历史包袱、无关讨论、重复材料
怎么给 摘要、结构化条目、原文片段、引用来源

比如你让模型排查线上问题,直接丢 5000 行日志通常效果很差。更好的做法是先整理:

背景:
- 服务:order-query
- 现象:18:20 后 P99 从 180ms 升到 2.4s
- 影响:订单详情页加载变慢,无大面积 5xx

关键日志片段:
{error_logs}

已排除:
- 数据库连接池未打满
- Redis 命中率无明显下降

请帮我分析最可能的 3 个原因,并说明下一步验证方法。

这比“帮我看看这堆日志有什么问题”可靠得多。

上下文管理还有一个很重要的技巧:把事实和要求分开

事实是模型不能随便改的,比如“数据库不能改表”。要求是你希望它完成的动作,比如“给出迁移方案”。两者混在一起,模型更容易漏条件。

六、输出约束:让结果可读、可用、可解析

很多 Prompt 失败,不是模型不会答,而是答出来没法用。

比如你想把用户反馈分类,模型输出一段散文:

这些反馈大多和性能有关,也有一些涉及价格和客服体验……

人能读,但程序不好处理。更好的方式是直接要求结构化输出:

请把下面的用户反馈分类,输出 JSON 数组。

字段:
- id:反馈编号
- category:只能是 performance / price / support / bug / other
- sentiment:positive / neutral / negative
- reason:一句话说明分类原因

要求:
- 不要输出 JSON 以外的解释
- 如果无法判断,category 填 other

输出格式不是装饰,它决定下游能不能接。

常见输出约束有几类:

约束类型 适用场景 示例
Markdown 结构 文档、文章、方案 使用二级标题,最后给总结表
表格 对比、清单、评估 输出“问题 / 原因 / 解决方案”三列
JSON 程序解析、自动化流转 只输出合法 JSON,不要额外说明
SQL / 代码 开发任务 给完整代码,并说明关键改动
字数限制 摘要、标题、卡片文案 控制在 120 字以内

这里有个经验:越要自动化,输出格式越要严格;越是启发式讨论,格式可以越松。

七、Few-shot:用示例告诉模型“照这个风格来”

Few-shot 指的是在 Prompt 里放几个输入输出示例,让模型模仿模式。

它适合处理这类问题:

  • 分类口径容易误解
  • 输出风格很具体
  • 业务术语有内部含义
  • 你很难用规则把要求完全说清楚

例如你要把客服工单分类:

请把工单分到以下类别:
- payment:支付、退款、账单
- delivery:物流、配送、签收
- account:登录、注册、账号安全
- other:其他

示例:
输入:我已经付款了,但订单还显示待支付
输出:payment

输入:快递显示签收了,但我没收到
输出:delivery

现在分类:
输入:{ticket}
输出:

Few-shot 的重点不是堆很多例子,而是放容易混淆的边界例子

比如“退款失败”显然属于 payment,不需要太多示例;但“优惠券不能用”到底属于 payment、promotion 还是 other,就需要示例统一口径。

八、思考过程与分步任务:让复杂问题可控

复杂任务不要一口吞。

比如:

帮我设计一个 AI 客服系统。

这句话太大了。模型可能直接给你一篇看起来完整但细节虚的方案。

更好的方式是拆成阶段:

请分三步完成:

第一步:先列出系统边界和核心需求,不要设计架构。
第二步:基于需求给出模块划分和数据流。
第三步:指出最容易出问题的 5 个环节,并给出工程对策。

每一步都要等前一步结论成立后再展开。

分步不是为了让回答显得更长,而是为了降低任务复杂度。尤其在架构设计、代码迁移、问题排查、长文写作里,分步能明显减少跑偏。

不过这里也要注意:不要要求模型输出冗长的隐藏推理过程。对实际使用来说,更有价值的是让模型输出关键依据、检查项和结论

可以这样写:

请给出结论,并列出支持结论的关键依据。
不要展开无关推理,只保留可验证的判断。

九、面向 Agent 的 Prompt:还要考虑工具和状态

普通聊天 Prompt 只需要考虑“模型怎么回答”。但 Agent 的 Prompt 还要考虑“模型怎么行动”。

Agent 可能会调用工具、读取文件、修改代码、访问网页、执行命令。这时 Prompt 需要补充三类约束:

约束 说明 示例
工具边界 什么能做,什么不能做 修改前先读文件,不要改无关模块
状态管理 如何记录当前进展 每完成一步更新计划
风险控制 哪些动作需要确认 删除数据、提交代码、推送远程前先确认

比如一个代码 Agent 的任务 Prompt 可以这样写:

目标:
修复订单查询接口在 Redis 超时时没有降级的问题。

工作方式:
- 先阅读相关代码和测试,不要直接修改
- 只改订单查询链路相关文件
- 新增或更新测试覆盖 Redis timeout 场景
- 修改后运行对应测试
- 不要自动提交代码,先汇总改动

验收标准:
- Redis timeout 时接口仍返回核心订单字段
- 日志包含 timeout 原因
- 测试能稳定复现并通过

这已经不是一句“帮我修 bug”了,而是一份可执行的工作协议。

如果你读过本博客的「AI Agent 系统架构:Planner、Executor、Memory、Tools 如何协作」,会发现 Prompt 在 Agent 里常常是 Planner、Executor 和 Tools 之间的胶水。它不仅描述任务,还描述任务如何被拆解、如何调用工具、如何避免危险动作。

十、提示词评估与迭代

提示词工程最容易被忽略的一点是评估。

很多人写 Prompt 的方式是:改一句,试一次,感觉不错,就收工。问题是,大模型输出有随机性,一次好不代表稳定好。

更工程化的方式是准备一组测试样例:

样例类型 作用
正常样例 验证主路径能跑通
边界样例 验证容易混淆的情况
反例样例 验证模型不会乱答
长输入样例 验证上下文管理
格式样例 验证输出是否可解析

迭代流程大概是这样:

提示词工程迭代流程

每次修改 Prompt,最好记录三件事:

记录项 例子
改了什么 增加“不要输出 JSON 以外内容”
为什么改 之前模型会在 JSON 前加解释
效果如何 20 个样例中格式错误从 5 个降到 0 个

这听起来有点麻烦,但它是“提示词工程”和“聊天试手气”的分界线。

如果某个 Prompt 要进生产系统,至少应该有一组固定评估集。哪怕只有 20 条,也比完全凭感觉强。

十一、常见问题

问题 回答要点
提示词工程是不是玄学? 不是。它有试错成分,但核心是任务表达、上下文管理、输出约束和评估迭代。能被复用、测试、对比,就不是玄学。
Prompt 越长越好吗? 不一定。长 Prompt 可以减少歧义,也可能引入噪声。关键是相关信息要足,重复和无关信息要少。
角色设定有用吗? 有用,但不要只写“你是专家”。角色要具体到判断标准,比如“从后端稳定性角度评审”。
Few-shot 示例越多越好吗? 不一定。优先放边界样例和容易混淆的样例,而不是堆一堆简单例子。
为什么模型还是会不按格式输出? 可能是格式约束不够明确、任务太复杂、示例冲突,或模型本身结构化输出能力有限。生产场景要配合解析校验和重试。
Prompt 能解决幻觉吗? 只能降低,不能根除。需要让模型基于来源回答、要求说明不确定性,并配合 RAG、工具调用、引用校验等机制。
什么时候该把 Prompt 做成模板? 当同类任务会重复出现,并且你已经知道输入、输出、约束和验收标准时,就该模板化。

最后给一个我自己的判断:提示词工程不是 AI 时代的“话术技巧”,而是人与模型协作时的接口设计。

接口设计得好,调用方少猜,被调用方少跑偏;接口设计得差,再强的模型也会在含糊需求里来回打转。