编译 | 11 个优化 AI 智能体的提示词技巧

B站影视 日本电影 2025-06-21 16:47 1

摘要:提示词工程已成为现代软件开发中回报率最高的技能之一。你提供给 AI 智能体的提示词决定了它如何规划、如何使用工具,以及它将构建还是破坏你的工作流。微小的改动——一行额外的上下文、一个明确的约束、一条重排的指令——往往能在准确性和可靠性上带来巨大的提升。本文浓缩

引言

提示词工程已成为现代软件开发中回报率最高的技能之一。你提供给 AI 智能体的提示词决定了它如何规划、如何使用工具,以及它将构建还是破坏你的工作流。微小的改动——一行额外的上下文、一个明确的约束、一条重排的指令——往往能在准确性和可靠性上带来巨大的提升。本文浓缩了我们在 Augment Code 用于构建自主 AI 智能体的实战策略,使其表现得像纪律严明的团队成员,而非产生幻觉、凭感觉编程的工具。

文中的示例侧重于编程 AI 智能体,但这些技术具有普适性。

什么是提示词工程?

一个 AI 智能体的 提示词 (prompt) 包含所有提供给模型的输入内容。这包括多种组成部分:

系统提示词 (System prompt) 工具定义 (Tool definitions) 工具输出 (Tool outputs) 用户指令 (User instructions) 模型在前几轮对话中自身的输出

提示词工程 (Prompt engineering) 是通过提供更好的提示词来提升模型在特定任务上表现的艺术。提示词的所有部分都可能通过提示词工程得到改进。例如:

系统提示词可以包含通用指令,以引导模型采用不同的响应风格或自主性水平。 工具定义可以向模型解释在何种情况下应该或不应该使用某个工具。 工具输出可以告知模型错误情况。 用户指令可以在展示给模型前被重写 (即提示词增强)。 之前的模型输出可以被压缩或截断以节省 Token,这样更长的对话历史就能放入上下文窗口中。如何截断对质量至关重要。 如何理解模型

模型是 (人工) 智能的。给模型编写提示词更像是与人交谈,而非对计算机进行编程。模型完全基于提示词中的内容来构建其世界观。这个世界观越完整、越一致,模型的结果就越好。

模型向我们呈现的是一个自然语言界面,这与人们使用的编程语言是分开的。将大语言模型 (LLM) 界面视为一个独立但真实的抽象层是很有用的。这个界面可以用来呈现正常路径下的结果,也可以用来提醒错误、通知变更等——总的来说,就是用来与模型沟通。

示例:

如果模型错误地调用了一个工具,不要在你的 AI 智能体代码中抛出异常。相反,应返回一个工具结果,解释错误原因: Tool was called without required parameter xyz (工具调用时缺少必要参数 xyz)。模型将会恢复并重试。 如何评估提示词

除非目标是让模型执行一项非常具体的任务,否则通常很难自动评估提示词。尝试设计各种场景来测试提示词,并寻找可能因提示词变更而导致性能衰退的例子。关于这些评估原则在实践中的具体示例,请参阅这些相同的提示词工程技术如何推动 Augment Code 在 SWE-bench 上取得了开源模型第一的成绩

提示词工程技巧

遵循这些技巧,你就能解锁 AGI。

优先关注于上下文

提示词工程中最重要的因素是为模型提供 尽可能最佳的上下文 :即用户提供的信息 (相对于我们提供的提示词文本)。这是模型执行其任务所使用的主要信号。

当前的模型擅长在长提示词中找到相关的有用上下文片段,所以当有疑问时,如果增加信息能提高上下文中包含有用相关信息的机会,那就倾向于提供更多信息。

关于一个提示词,首先应该问的问题是——它是否包含了所有相关信息,以及包含的可能性有多大?回答这个问题通常并非易事。

示例:

在为模型提供长命令输出而进行截断时,截断方法至关重要。通常,截断长文本涉及截去后缀。然而,对于命令输出,有用的信息更可能出现在前缀和后缀,而非中间部分。例如,程序崩溃的堆栈跟踪信息通常出现在后缀。因此,为了最大化模型获取最相关上下文的可能性,截断命令输出的中间部分比截断后缀更好。

通过解释模型所处的环境,并提供可能有助于其良好表现的细节,来帮助模型进入正确的状态。例如,如果你希望模型扮演一名软件开发人员,就在系统提示词中告诉它。向它解释它能访问哪些资源,以及应该如何使用它们。

例如,在 Augment AI 智能体开发的早期,系统提示词中加入了以下内容,就极大地提升了其性能:

你是一个 AI 助手,可以访问开发者的代码库。你可以使用提供的工具来读取和写入代码库。

在提示词各组件间保持一致

确保提示词的所有组件 (系统提示词、工具定义等) 以及底层的工具定义都是一致的。

示例: 系统提示词包含这样一行: The current directory is $CWD (当前目录是 $CWD) execute_command 工具允许 AI 智能体执行 shell 命令,它包含一个可选的 cwd 参数。一致性意味着这个参数的默认值应该是 $CWD 。这可以在工具定义中指定。如果没有指定,模型很可能会假定是这种情况。 read_file 工具接受一个要读取文件的路径参数。如果提供的是相对路径,它应该被解析为相对于 $CWD 。 注意:避免让模型感到意外。 模型很容易被混淆。如果模型很可能期望从一次工具调用中得到某个特定结果,请确保要么提供该结果,要么在工具结果中解释偏差。例如,如果工具定义承诺返回特定长度的输出,要么返回该长度的输出,要么在回答前加上类似 Output of length N was requested, but returning output of length K instead because ... (请求了长度为 N 的输出,但返回长度为 K 的输出,因为...) 的声明。

示例:

如果提示词包在会话期间可能改变的状态 (例如当前时间),不要将它们包含在系统提示词或工具定义中。 相反应在下一条用户消息中告知模型这一变化。这能保持提示词的内部一致性:模型可以看到每一轮对话时的状态是什么。

考虑用户的视角,并尝试使模型与该视角对齐。

示例:当用户在 IDE 中工作时,可以向模型呈现一个详细的 IDE 状态视图,重点关注用户最可能关心或在其指令中提及的元素。

可能有助于对齐模型的示例:

用户的当前时间和时区 用户的当前位置 用户的活动历史

包含 IDE 状态的基础系统提示词示例:

用户在一个 IDE 中工作。当前的 IDE 状态:文件 foo.py 处于打开状态。IDE 的类型是 VSCode。

描述 IDE 状态的更详细的系统提示词示例:

The user works in an IDE. The current IDE state:The IDE is of type VSCode.The currently open file is foo.py.Lines 134 through 179 are visible on the screen.Here is the currently visible text, with the cursor location denoted by:```python134 def bar:135 print("hello")...179 # TODO implement this```There is no selected text.There are 14 open tabs. Here they are from most recently to last recently visited:foo.pybar.py ...xyz.py

注意: 这并不是说其中一个提示词必然比另一个更好。详细提示词的潜在缺点是,模型可能会开始过度关注 IDE 状态,而这并不总是用户意图的最佳信号。

力求详尽

详尽的提示词对模型有益。不要担心提示词的长度。当前的上下文长度很长,并且会持续增加:你不可能通过写更长的提示词来耗尽提示词的预算。

一个成功且详细的提示词示例,用于教模型如何使用版本控制工具 Graphite:

## Using Graphite for version controlWe use Graphite for version control on top of git. Graphite helps manage git branches and PRs.Graphite maintains stacks of PRs: changes to a PR automatically cause rebases on higher PRs in the stack,saving a lot of manual effort. Each section below describes how to perform a common version control workflows using Graphite and GitHub.If the user asks you to perform such a workflow, follow these guidelines.### What NOT to doDo not use `git commit`, `git pull`, or `git push`. These commands are all replaced by Graphite commands that start with `gt`, as described below.### Creating a PR (and branch)In order to create a PR, do the following:- Use `git status` to see which files were changed, and which files are new- Use `git add` to stage the relevant files- Use `gt create USERNAME-BRANCHNAME -m PRDESCRIPTION` to create the branch, where: `USERNAME` can be obtained, see instructions elsewhere `BRANCHNAME` is a good name for the branch you come up with `PRDESCRIPTION` is a good description for the PR you come up with- This may fail because of pre-commit issues. Sometimes pre-commit fixes the issues itself. Check `git status` to see if any files were modified. If so, `git add` them. If not, fix the issues yourself and `git add` them. Then repeat the `gt create` command to try creating the PR again.- Run `gt submit` to create the PR on GitHub (if you're only creating the branch, skip this step).- If `gh` is available, use it to set a PR description.Note: Do not forget to add files before running `gt create`, or you will get stuck!### Updating a PRIn order to update a PR, do the following.- Use `git status` to see which files were changed, and which files are new- Use `git add` to stage the relevant files- Use `gt modify` to commit the changes (no need to supply a message)- This may fail because of pre-commit issues. Sometimes pre-commit fixes the issues itself. Check `git status` to see if any files were modified. If so, `git add` them. If not, fix the issues yourself and `git add` them. Then repeat the `gt create` command to try creating the PR again.- Use `gt submit` to push the changes- If you also need to update the PR description, use `gh` (if it's not installed, tell the user but don't insist on updating the PR description)### Pulling changes from mainIn order to synchronize your local repository with main, do the following.- Use `git status` to make sure the working directory is clean- Use `gt sync` to pull changes and rebase- Follow the instructions. If there are conflicts, ask the user if they want to resolve them. If so, follow the instructions shown by `gt sync`.### Other Graphite commandsTo find other commands, run `gt --help`.

避免对特定示例过拟合

模型是强大的模式匹配者,会抓住提示词中的细节。提供具体的操作示例可能是一把双刃剑:这是引导模型走向正确方向的简单方法,但也存在模型对这些示例过拟合而在其他方面表现退化的风险。请务必进行实验,并包含可能暴露过拟合问题的示例。

相比之下,告诉模型 不 该做什么通常是安全的 (尽管不总是有效)。

考虑工具调用的局限性

工具调用在几个方面受到限制:

如果模型在类似的工具上训练过,或者指令和工具之间的联系很明确,模型通常会选择正确的工具。在许多情况下,即使有最好的提示词,它们也可能无法选择正确的工具。 如果面对多个功能相似的工具,不应期望模型在任何给定情况下都能选择正确的工具。例如,当面对一个简单和一个复杂但能完成相似任务的工具时,Claude 通常会选择简单的那个。 模型经常会以不正确的方式调用工具,违反了工具定义中的契约:参数类型可能错误,参数范围可能错误,必需的参数可能缺失等。最好是验证输入,并在失败时返回一个解释错误的工具输出。模型通常会从中恢复。

示例:

给模型一个可以编辑文件某个区域的 edit_file 工具。 给模型一个 clipboard 工具,模型可以用它来剪切、复制和粘贴大量代码。告诉模型在移动大量代码时使用此工具。 指示模型「将 Foo 类从 foo.py 移动到 bar.py」。Sonnet 3.5 通常会选择使用 edit_file 。

威胁和唤起同理心有时会有用

告诉模型诸如「正确执行此操作,否则你将面临财务破产」之类的话,有时确实有助于提高性能。友好地请求模型或对它「吼叫」式命令则很没什么帮助。

注意提示词缓存

只要有可能,构建提示词时应使其能在会话期间被追加内容,以避免提示词缓存失效。

示例:

如果提示词包含在会话期间可能改变的状态 (例如当前时间),不要将它们包含在系统提示词或工具定义中,因为一旦它们改变,大部分提示词缓存将失效。

相反,应在下一条用户消息中告知模型这一变化。

模型更关注提示词开头或特别是结尾的信息

模型对指令的关注程度似乎是:用户消息 → 输入的开头 → 中间的某个位置。如果某件事很重要,可以考虑将其添加到用户消息中。(这是一个当前的快照,随着模型训练的演进,这种优先级很可能会改变。)

警惕提示词工程的平台期

通过直接的提示词工程所能达到的效果是有限的。当提示词工程进入收益递减的阶段时,就需要引入其他技术了。

结论

掌握提示词工程,技巧在其次,更重要的是严谨的沟通:给予 AI 智能体完整、一致的上下文;像对待不被信任的同事一样验证其行为;并通过经验进行迭代。当你像对待代码库一样——进行版本控制、审查和测试——来处理提示词时,你将解锁能够扩大你的影响力,而非增加你麻烦的 AI 智能体。

来源:东窗史谈一点号

相关推荐