提示词这东西,乍一看谁都会写,但真正让大模型稳定输出、不跑偏,比想象中难得多。我身边很多朋友开始学 AI Agent,第一课往往是“怎么调 API”,第二课就卡在提示词上:同样一个需求,有人写出来模型规规矩矩执行,有人写得模型东拉西扯。差别就在提示词。
我自己的学习路线里,提示词工程被放在 AI Agent 之前,是有原因的。Agent 本质上是一系列“提示词 + 工具调用 + 记忆管理”的组合,如果你连跟大模型对话都说不清楚需求,后面写出来的 Agent 大概率是个“人工智障”。这篇笔记不是系统理论课,而是把我从第一行提示词开始踩过的坑、总结出的套路,完整地捋一遍。看完之后你至少能写出“能稳定干活”的提示词,而不是碰运气式地让模型自由发挥。
1. 为什么提示词会成为AI Agent学习的第二课
1.1 从“能对话”到“能干活”的鸿沟
很多人第一次接触大模型,都会惊叹于它的自然对话能力。但真到了实际项目,你会发现光会聊天远远不够。比如你想让模型扮演一个客服,对客户提问进行分类、提取关键词、打标签,再决定要不要转人工。如果直接说“你是客服,帮我处理消息”,模型大概率会给你一段含糊其辞的“话术”,而不是一个结构化的 JSON 结果。
这就是“能对话”和“能干活”之间的鸿沟。对话是开放式的,模型可以自由发挥;干活是封闭式的,你需要它按照约定好的格式、逻辑、边界去执行。提示词工程本质上就是跨越这道鸿沟的桥。它把人的意图翻译成模型能理解的任务定义,再把模型的输出翻译回人能直接使用的结构化数据。
我写过太多“看着很合理但根本不能落地”的提示词。比如让模型“总结这封邮件”,它给你写一段散文;让模型“抽取发布日期”,它给你写一段解释。后来我意识到,问题不在模型,而在于我给的约束不够。模型天然倾向于生成“看起来自然”的内容,而不是“正好符合需求”的内容。你要用明确的指令、格式、示例把它摁住。
1.2 提示词工程到底是什么?它与Agent是什么关系
提示词工程(Prompt Engineering)并不是什么玄学,简单说就是“设计输入给大模型的文本,以稳定获得期望输出”的一整套方法。它包含的内容很杂:角色设定、任务分解、上下文组织、输出格式约束、示例构造、错误边界说明,甚至还包括如何管理对话历史、如何在多轮交互中控制 token 消耗。
在 AI Agent 的语境里,提示词的地位又被放大了。Agent 往往需要在大模型的决策下调用工具、读取记忆、规划步骤,这些行为全部依赖系统提示词(System Prompt)来定义。你可以把 Agent 看成“包了一层提示词和执行逻辑的外壳”,外壳里的大模型仍然是个文本生成器,提示词就是它的操作手册。
所以我一直建议初学者不要直接扑向 LangChain 之类的框架,先把提示词功底打扎实。框架只是帮你拼装,但真正决定 Agent 行为上限的,是那几段提示词写得够不够准。后面的学习里你会发现,所谓 Agent 跑得稳不稳,有时候真的就是提示词里多一句话少一句话的事。
1.3 为什么说提示词是一项“投资回报率”最高的技能
我见过有人花大量时间研究微调模型,却很少花时间琢磨提示词。不是说微调不好,而是从投入产出比看,提示词工程是更划算的选择。微调需要数据、算力、测试周期,而提示词只需要你调整文本,几分钟就能看到效果。对大多数业务场景,一套设计良好的提示词,能把模型能力使用到 90 分,已经非常够用了。
更何况,提示词的设计能力是可以迁移的。你会写一个 Agent 的系统提示词,换一个模型、换一个框架,很多套路依然适用;但微调过的模型,换一个底座就要重新来。我个人经验是:先穷尽提示词的优化空间,再谈微调。这可能是 AI 应用开发里性价比最高的一条路径。
2. 先理解大模型的“听话”机制
2.1 Token、概率与指令遵循
想写好提示词,至少要对大模型的“思考方式”有个基础认知。模型读入文本时,会先切成 token,也就是一些词块或字符组合。比如中文里“提示词”可能被切成好几个 token。模型要做的事,是根据已有的 token 序列,去预测下一个 token 的概率分布。
这意味着,模型并不是真的“理解”你的话,它是在做一种高维度的模式匹配。它能“听懂”,是因为训练数据里见过太多类似模式:当你给出“请用 JSON 输出”,它大概率会遵从,因为互联网文本里有大量这种对应关系。如果你用模糊、口语化、歧义多的说法,它就更容易走偏。
理解这一点之后,你写提示词的态度就会变。你不是在跟一个“聪明的同事”聊天,而是在给一台“概率机器”设定一个高概率命中的路径。所有提示词技巧,本质上都是在提高“期望输出”的概率权重。这也是为什么很多提示词模板里会写上“不要解释,直接输出”“只输出 JSON,不要其他内容”——因为这样就把模型的生成空间压缩了。
2.2 上下文窗口是有限的舞台
大模型每一次生成,能参考的文本总量是有限的,这个限制叫“上下文窗口”。有的模型是 8K token,有的是 32K、128K,甚至更大。听起来很大,但实际用起来很容易塞满。尤其是 Agent,每一轮对话、每一条工具返回结果、每段历史记录,都会占用上下文。
上下文窗口就是舞台,模型只能看到舞台上摆着的东西。舞台之外的一切,它都看不见。很多 Agent 应用莫名其妙“失忆”,往往不是模型出了问题,而是历史记录被截断了,或者把不重要的信息填了进来。提示词工程里非常重要的一件事,就是学会“布置舞台”:什么信息一定放在前面,什么信息可以压缩,什么信息可以干脆丢掉。
这里有一个容易被忽略的细节:模型对不同位置的关注度不一样。通常开头和结尾的内容,模型注意得更多,中间部分容易被“注意力稀释”。所以,如果有一条最关键的要求,建议放在系统提示词的最开头和最结尾各强调一遍。你可以说这是“提示词的黄金首尾”,我用这个技巧避免了无数次格式不稳定的问题。
2.3 让模型听懂的三层信息:意图、约束与环境
一个合格的提示词,应该包含至少三层信息。
第一层是“意图”,也就是你到底要模型做什么。是总结、抽取、改写、分类,还是生成内容?这一层必须动词明确,比如“请从以下内容中提取所有价格信息”,而不是“帮我看看这段文字里的价格”。
第二层是“约束”,包括输出格式、长度、语气、不能做什么。比如“用中文回答,字数控制在100字以内,不要提及具体人名”。约束写得越明确,模型越老实。但要注意,约束不要一次性堆太多,模型也有“指令过载”的时候。实验下来,一页以内、要点不超过 5-8 条比较保险。
第三层是“环境”,也就是模型作答需要的背景材料。比如用户的输入、数据库查询结果、已经执行过的工具返回等。环境信息要整理好再塞给模型,而不是把原始数据一股脑丢进去。你会发现,原始数据里大量无用字段会严重干扰模型的理解,先做一步提炼,效果会好得多。
3. 提示词工程的实操框架:一份能直接套用的模板
3.1 角色设定:给模型一个身份和立场
角色设定是提示词里最简单也最有效的一招。给模型一个明确的身份,相当于告诉它“你现在站在什么角度、用什么口吻、按什么标准来输出”。比如“你是资深 Python 工程师”和“你是初学编程的助手”,得到的回答风格完全不同。
角色设定最好和任务强相关。如果任务是审查代码,那“资深架构师”比“AI 助手”更合适;如果任务是写产品文案,那“资深市场策划”比“万能助手”更有用。因为模型会从训练数据里检索与该角色相关的写作模式、专业词汇和判断标准,输出质量差别是肉眼可见的。
但角色设定不是万能的。如果任务本身信息不足,角色设定就成了空中楼阁。我在使用中把角色设定当作“语气和立场调节器”,而不是任务描述本身。核心任务该写多清楚还是写多清楚,角色只是替模型找到一个合适的“高频输出分布”。
3.2 任务描述:把目标拆到模型听得懂的动作
很多提示词写得差,主要是因为任务描述太笼统。“帮我写一下本周的工作周报”这种提示词,模型只能靠猜。更好的方式是给足背景:“我是产品经理,本周完成了以下三件事……请帮我按工作内容、成果、问题、下周计划四段来写周报,语气偏向简洁干练。”
我把这叫作“5W1H 提示法”:Who(角色)、What(任务)、Why(背景)、When(时间范围)、Where(场景限制)、How(输出形式)。不需要每次都写满,但至少要把“What、How、Why”说清楚。尤其是 Why,很多人会忽略。当模型知道这份周报是给老板还是给团队看的,它选择的措辞是完全不同的。
任务描述还要避免“复合指令”。比如“帮我翻译并润色下面的文字,还要解释重点单词”是一口气让模型干三件事。除非你明确告诉它分步做,否则很容易顾此失彼。稳妥的做法是拆成多轮,或者让模型按步骤输出。
3.3 输出格式:让结果可解析、可复现
对于 Agent 开发来说,输出格式可能是提示词里最不能含糊的部分。你需要模型输出 JSON、Markdown、表格,或者特定的字段结构,就必须把这个格式写进提示词,并且伴随示例。只写“用 JSON 输出”是不够的,模型仍有可能在 JSON 里加注释、换行不对、或者输出多余文字。
我常用的格式模板大概是:“请以 JSON 对象返回,结构如下:{“category”: “分类结果”, “reason”: “理由”, “confidence”: 0-1之间的浮点数}。不要输出其他内容,不要使用 Markdown 代码块。”加上示例会更稳,比如“例如输入……返回……”。多给两个正反例,模型基本就能守住边界。
格式要求有一个长期被低估的价值:可复现性。当你的提示词能稳定产出标准格式,你才能把 Agent 的输出接入下游逻辑。否则你还得自己写正则、写清洗脚本,相当于把模型的“不听话”转嫁给自己。从第一天起,我要求自己每个项目的提示词都必须产出“程序可直接读取”的结构,省掉了大量麻烦。
3.4 示例与思维链:少样本提示和CoT在Agent里的应用
少样本提示(Few-shot Prompting)就是给模型看几个例子,让它模仿你的做法。这比光讲规则有用得多,尤其是那些“说不清但一看例子就懂”的场景。比如想定义一套情绪标签体系,与其用三百字解释“什么是中性情绪”,不如给出三个典型句子和对应标签,模型一下就学会了。
思维链(Chain-of-Thought)则是让模型在输出最终答案之前,先展示一步步的推理过程。这对数学题、逻辑判断、复杂推理类任务非常有效。但在 Agent 场景里要注意,思维链有时候会让模型“话多”。我一般会在提示词里限制“写出简要步骤,不超过三行”,或者干脆只保留思维链,不输出具体解释。
一个通用技巧是“先推理后输出”。比如让模型先列出考虑的因素,再给出分类结果。这听上去像是多此一举,但实测下来,推理过程确实会显著提高准确率。而且当模型错误时,这条推理过程就是你排查问题的第一手线索。
4. 从提示词到Agent:系统提示词的进阶设计
4.1 Agent提示词与普通对话提示词的区别
普通对话提示词,目标是输出一段自然回复;Agent 的系统提示词,目标是“在一个循环里做出合理的决策”。这个区别特别重要。Agent 里的大模型往往不是直接输出最终答案,而是输出“下一步动作”:要不要调用工具?调用哪个工具?入参是什么?如果结果不对,下一步怎么调整?所以提示词的结构和语气,都要围绕“决策”来设计。
我见过很多人把普通对话提示词直接搬进 Agent 里,结果模型总是“好心”地把所有事都分析一遍,就是不输出工具调用。原因很简单:它的模型行为偏向聊天,而不是行动。你需要用系统提示词明确地告诉它:“你是一个能调用工具的智能体,你的任务是根据对话内容判断是否需要工具调用,需要时请严格按工具定义格式输出。”
Agent 提示词还需要考虑“失败模式”。大模型在做决策时,偶尔会凭空想象出一个不存在的工具名,或者编造一个工具返回值。防范方法是在系统提示词里加一条:“只能使用给定的工具,不要自行捏造工具名称。如果工具调用失败,如实说明失败原因。”我加了这个以后,Agent 的幻觉率明显下降。
4.2 工具描述与函数调用的提示设计
如果你使用函数调用(Function Calling)机制,工具描述本身就是提示词的一部分。每个工具都需要一个清晰的名字、说明和参数定义。工具说明要写“这个工具做什么、什么时候用、什么时候不要用”,很多 Agent 乱调用工具,往往不是因为模型笨,而是因为工具描述太简短了。
举个例子,你有一个“查询天气”的工具,如果描述只写“查询天气”,模型可能在任何需要温度、湿度、风力的问题下都调用它。但如果描述写成“查询指定城市当前的天气状况,包括温度、湿度、风力。仅当用户明确询问天气信息时调用”,模型的选择就会准很多。
还有一个细节:工具返回值也要“归置好再给模型”。如果工具返回了很长的 JSON,Agent 的处理能力会下降。我一般在工具内部先做裁剪、格式化,让返回给模型的信息保持精简。这比让模型去一个长 JSON 里找字段要可靠得多。
4.3 上下文工程:Agent如何把记忆组织成提示词
上下文工程这个词,这两年越来越被提起。它关注的是“该往提示词里放什么、按什么顺序放、什么时候丢掉什么”。Agent 的记忆无外乎三类:短期对话历史、长期事实记忆、以及刚执行完的工具结果。这三类信息如果一股脑全塞进上下文,不仅浪费 token,还会严重干扰模型。
我的经验是:对话历史保留最近 3-5 轮就够,更早的内容如果重要,就提炼成摘要再放进提示词。事实记忆(比如用户偏好)可以单独放在系统提示词里,并且定期更新。工具结果要在本次决策时立即注入,用完之后如果暂时用不到,下一轮就可以移除。
这是一项“慢功夫”,也是 Agent 里最容易被忽略的性能瓶颈。你可能会发现,Agent 第一轮表现很好,到第 5 轮就开始答非所问。这时候不是模型坏了,而是上下文里塞了太多杂物。你可以打印一下发给模型的最终提示词,往往一眼就能看出问题。
4.4 一个最小可运行的Prompt示例(附代码调用)
空谈太多不如动手做一个。下面是一个最小 Agent 雏形的系统提示词,以及一段调用大模型接口的 Python 代码。假设我们做一个“查天气 + 报菜名”的助手,模型需要决定是否调用工具。
import requests import json system_prompt = """ 你是一个智能助手,你可以调用工具来回答用户问题。 可用工具: 1. get_weather(city: str): 查询指定城市当前天气,仅当用户询问天气、温度、下雨等情况时调用。 2. recommend_dish(taste: str): 根据口味推荐一道家常菜,仅在用户要求推荐菜谱时调用。 规则: - 当你决定调用工具时,请严格输出一个 JSON 对象,不要加任何解释,格式如下: {"tool": "工具名", "args": {"参数名": "参数值"}} - 当你不需要调用工具时,请直接用自然语言回答用户。 - 禁止编造工具名或参数。 """ user_input = "北京现在冷吗?需不需要穿羽绒服?" # 用任意 OpenAI 兼容 API 调用,endpoint 和 key 按实际情况替换 response = requests.post( "https://your-api.example.com/v1/chat/completions", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "model": "your-model", "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_input} ], "temperature": 0, } ) print(response.json()["choices"][0]["message"]["content"]) # 期望输出:{"tool": "get_weather", "args": {"city": "北京"}}你看到这个例子的重点了吗?系统提示词把“什么时候调用工具”和“输出格式”都规定死了。temperature 也设成了 0,让模型尽量少自由发挥。如果你把 system_prompt 换成一句“帮我处理用户的请求”,结果大概率会是一段散文,而不是结构化工具调用。
这个示例虽小,但它已经包含了 Agent 提示词的核心三件事:角色职责、工具定义、决策规则。后面你要加记忆、加多步规划,都是在这个基础上扩展。
5. 常见问题与避坑经验
5.1 模型不听话?先检查这四处
遇到模型输出不符合预期,先别急着换模型、加规则,按下面的顺序检查提示词。
第一,任务是不是太模糊。把“分析这段内容”改成“提取三个关键观点,并说明理由”,模型立刻会收敛。第二,输出格式有没有被“夹在”其他信息中间。如果重要的格式要求被埋在一大段背景信息里,模型很容易忽略。我习惯把格式要求单独成段,放在用户输入的上一行。
第三,是不是给了模型太多“自由发挥空间”。如果提示词里没有“不要解释”“不要输出多余内容”的字样,模型总会话痨式输出。第四,历史对话里有没有“带偏”的信息。比如上一轮模型刚跑题了,这一轮它大概率延续跑题。这时候,把系统提示词里的相关约束再强调一遍,比继续对话更有效。
5.2 常见问题速查表
我把日常开发里最常遇到的几个问题做成了表格,方便你遇到类似情况时快速对照。
| 问题现象 | 可能原因 | 调整思路 |
|---|---|---|
| 输出格式不稳定,偶尔多出解释文字 | 格式约束写在了中间,或者没有给示例 | 把格式要求放到提示词首尾,并给正反例 |
| 模型不按角色说话 | 角色设定只出现在对话消息里,系统层面没设置 | 把角色写进系统提示词第一句,并在任务中强化 |
| Agent 频繁调用无关工具 | 工具描述太简短,缺少“何时不用”说明 | 扩充每个工具的描述,写清适用条件 |
| 多轮交互后记忆力明显变差 | 上下文窗口被历史信息占满 | 只保留最近几轮,把长期信息做成摘要 |
| 模型回答过于空泛 | 任务描述缺少具体产出形式 | 明确输出格式、字数、结构、语气 |
| 逻辑类任务总做错 | 直接让模型输出最终答案 | 要求模型先输出推理步骤,再给结论 |
这张表是我自己整理出来的“排查顺序表”,几乎能覆盖 80% 的提示词问题。真正复杂的问题通常是最开始设计提示词时埋下的,到后面再补规则很难救回来。所以我的习惯是:一个新任务,第一版提示词一定会包含角色、任务、格式、边界这四件套,宁可写得多一点,也不给模糊空间。
5.3 我踩过的几个坑
第一个坑是“一次性堆太多约束”。我早期写提示词喜欢把能想到的要求全写进去,结果模型经常顾此失彼,格式对了但内容质量下降。后来我控制在“每段提示词不超过一个核心目标,其他都是补充说明”,效果反而更好。核心目标放最前面,剩下的约束都算作边界条件。
第二个坑是“太依赖模型自觉”。比如提示词写了“请仔细核对数据”,模型就会“自信地”编造数据。正确的做法是让模型引用信息来源,比如“从用户提供的资料里提取,资料中没有的信息要标注‘未找到’”。这样至少能把幻觉范围控制住。
第三个坑是“忘了解释提示词给队友听”。做 Agent 项目往往需要多人协作,如果提示词写得只有自己能看懂,后面维护成本极高。我现在给每个 Agent 的系统提示词都写“设计缘由”注释,把每条规则的目的写清楚。这不仅方便队友,也方便我一个月后回来看懂自己当时在想什么。
第四个坑和 token 有关。我一开始觉得上下文窗口很大,就随意塞资料,结果钱花了不少,效果反而不行。后来养成了“进提示词之前先裁一遍”的习惯,就像做菜之前先切菜,把原始数据里的杂质去掉,模型才能吃得干净。
6. 一点个人经验总结
提示词工程学到现在,我最深的感受是:它不是一个一次性学会的技术,而是一种反复打磨的思维方式。你每用一次模型,都会发现新的“不听话”方式,而这些基本都是提示词的漏洞。
我现在写提示词的流程很固定:先写一个“足够糙但能用”的版本,跑一次看结果;然后根据失败点,补一条约束或换一种措辞;连续跑五六次测试用例,确认稳定之后才交给 Agent 使用。这个过程有点像调乐器,不是调一次就准,而是靠耳朵一遍一遍辨音。
如果你也想把提示词工程练起来,我建议从今天就开始做一件事:把你平时经常发给模型的提示词,全部升级成“角色 + 任务 + 格式 + 示例”的完整结构。哪怕一开始显得啰嗦,跑出来的效果一定会让你觉得值得。等你习惯了这种写法,再回头看原来那些“一句话提示词”,会觉得很不可思议。