Anthropic员工分享提示工程最佳实践

2025年1月15日

本文来自Anthropic员工对外分享的提示词入门。

核心要点如下:

简单的提问(Prompt)往往效果不佳。要想让 AI(以 Claude 为例)准确、可靠地完成复杂任务,必须精心设计和构建提示(Prompt Engineering)。

一个优秀的提示应该像一份清晰的说明书,通常包含以下部分: 1、任务背景与角色设定:明确告诉 AI 它的身份和目标。 2、上下文与背景数据:提供所有必要的信息、文档或图片。 3、详细的任务指令与规则:给出分步指令,设定行为边界。 4、提供示例(Few-shot Learning):展示一两个理想的输入输出范例,让 AI 模仿。 5、定义输出格式:要求 AI 以特定格式(如 JSON、XML)输出,方便后续处理。

实用技巧

使用分隔符:像 XML 标签 (<example>, </example>) 一样组织信息,帮助 AI 理解结构。

引导思考过程:要求 AI 遵循"一步一步思考"(Step-by-step thinking)的逻辑,先分析再下结论,以提高准确性。 规避"幻觉":明确指示 AI 在信息不足或不确定时,要回答"不知道",而不是猜测或编造答案。

提示工程是一个不断测试和迭代的经验科学。从一个基础提示开始,根据 AI 的反馈逐步优化和完善,最终达到理想效果。

演讲全文如下

提示工程简介

大家好,感谢大家今天来参加我们的“提示工程101”讲座。我叫汉娜,是 Anthropic 应用人工智能团队的一员。

这位是克里斯蒂安,他也是应用人工智能团队的成员。

今天,我们将通过一个真实的场景,带大家了解一些提示工程的最佳实践,并一起构建一个提示。

什么是“提示工程”?

那么,什么是提示工程呢?你们可能已经对此有所了解了。

这是我们与语言模型沟通的方式,并试图让它做我们想做的事情。这包括为模型编写清晰的指令,为模型提供完成任务所需的上下文,并思考我们希望如何安排这些信息以获得最佳结果。

这里有很多细节,有很多不同的方式来构建提示。最好的学习方式就是不断练习。

实际操作场景

今天我们将通过一个实际操作的场景来学习。

我们会用一个真实的客户案例作为启发,这个案例是我们之前合作过的。

我们对客户实际要求我们做的事情进行了一些修改,但这是一个非常有趣的案例,涉及到分析一些图像,并从中获取事实信息,然后让 Claude 根据它找到的内容做出判断。

我其实不会说这些内容所用的语言,但幸运的是,克里斯蒂安和 Claude 都会。

那么,我把接力棒交给克里斯蒂安,让他来介绍这个场景和内容。

案例分析:汽车事故报告

在这个例子中,设想你在一家瑞典保险公司工作,每天都要处理汽车保险索赔。

你有两份信息,我们稍后会详细介绍。但从视觉上看,左边是一份汽车事故报告表,详细记录了事故发生前的情况。右边是一张手绘的事故发生示意图。

这两份信息是我们想要传递给 Claude 的。我们可以直接把这两份信息扔进控制台,看看会发生什么。

如果我们切换到控制台,就可以实际操作一下。在这种情况下,你可以看到我们这个漂亮又闪亮的 Anthropic 控制台。

我们用的是新的 Claude 4 Sonnet 模型。在这种情况下,我们将温度设置为零,并且设置了很高的最大令牌数,这样可以确保 Claude 的能力不受限制。

你可以看到,我用了一个非常简单的提示,为 Claude 设定了场景,说明了它需要做什么。

在这种情况下,就是审查一份事故报告表,并最终判断事故中发生了什么,以及谁有过错。

你可以看到,用这个非常简单的提示,如果我运行它,切换到预览模式,我们看到 Claude 认为这是一个发生在一条名为“Köpmangatan”的街道上的滑雪事故。

这在瑞典是一条很常见的街道名。从很多方面来说,你可以把这理解为一个无心的错误。

因为在我们的提示中,我们并没有做任何事情来设定 Claude 实际所处的情景。所以,它的第一次猜测还算不错,但我们仍然知道有很多直觉可以融入到 Claude 中。

如何写提示词

所以,如果我们回到幻灯片,可以看到,从很多方面来说,提示工程是一门非常依赖迭代和经验的科学。在这种情况下,我们可以有一个测试案例,让 Claude 明白这是一个关于汽车或车辆的环境,与滑雪无关。

然后,你可以通过这种方式迭代地构建你的提示,以确保它能真正解决你想要解决的问题。为了做到这一点,我们会介绍一些 Anthropic 内部和推荐给他人的最佳实践。

我们来谈谈开发一个好的提示的一些最佳实践。

首先,我们想谈谈一个好的提示结构是怎样的。你可能已经熟悉了与聊天机器人或 Claude 互动的方式,那种来回对话的风格。

当我们处理像这样的任务时,我们可能是在使用 API,并且我们希望一次性向 Claude 发送一条消息,让它一次就能完成任务,而不需要来回修改。

所以,我们推荐的结构是:首先设置任务描述,告诉 Claude 你在这里做什么,你的角色是什么,你想要完成什么任务

然后我们提供内容,在这种情况下就是克里斯蒂安展示的图片,即表格和事故示意图。这是我们的动态内容。这可能也是你从其他系统检索的内容,取决于你的用例。

我们会给 Claude 提供详细的任务指令,几乎就像一个分步列表,告诉它我们希望它如何完成任务,如何进行推理。

我们可能会给 Claude 一些例子。比如说,这是你可能会收到的一段内容,你应该如何回应。最后,我们通常会重复一些对 Claude 理解任务非常重要的事情。

这有点像和 Claude 一起回顾信息,强调一些特别关键的事情,然后告诉 Claude,“好了,现在开始工作吧。”

提供充足上下文

这是另一个视图。这里有更多的细节,更细致的分解。我们会逐一讲解这十个要点,并展示我们如何在控制台中构建它们。前几个要点,克里斯蒂安会讲讲任务上下文和语气上下文

好的。所以,如果我们从任务上下文开始,你会发现,在我之前的演示中,我们并没有详细说明 Claude 到底在处理什么场景。

正因为如此,你也可以看出,Claude 必须更多地猜测你想要什么。在我们的案例中,我们确实希望把它分解开来,确保我们能给出更清晰的指令。同时,我们也要确保我们了解我们要求 Claude 完成的任务。

其次,我们还会加入一些语气。这里的关键是,我们希望 Claude 保持事实性,保持自信。

所以,如果 Claude 无法理解它所看到的内容,我们不希望它猜测,从而误导我们。我们希望确保任何评估,在我们的案例中,是评估谁有过错,都是尽可能清晰和自信的。否则,我们就失去了重点。

所以,如果我们回到控制台,我们可以跳转到版本2。

提供背景信息

我还会展示一下数据,因为我们之前没有这样做,只是为了突出我们正在看的内容。我们看到的这份是汽车事故报告表。它只是17个不同的复选框,描述了实际发生的情况。

你可以看到有A车和B车,分别在左侧和右侧。这份表格的主要目的是确保 Claude 能够理解这份人工生成的数据,并评估实际情况。这需要通过示意图来证实,我们可以再看一下这个示意图。

在这种情况下,表格只是同一场景的不同数据点。我们希望将更多的信息融入我们的版本2中。通过这样做,我实际上会更详细地阐述发生了什么。你可以看到我指定了,这个AI助手正在帮助人类理赔员审查瑞典语的汽车事故报告文档。

我又说明了这是一个手绘的事故示意图,并且它不应该在没有完全自信的情况下做出评估。这一点非常关键,因为如果我们运行这个,你会看到,设置和之前一样,Claude 4,新的Sonnet模型,温度为零。

我们运行这个,你会看到它已经能够识别出这与汽车事故有关,而不是滑雪事故,这很棒。我们看到它能识别出车辆A在复选框1上被标记,车辆B在12上。往下滚动,我们仍然可以看到 Claude 缺少一些信息来做出完全自信的判断,确定谁有过错。这很好。

这符合我们设定的任务,确保你不会做出任何非事实的陈述,并确保你只有在你自信的时候才陈述事实。

但是还有很多信息我们没有提供,关于表格,表格到底是什么样的,以及所有这些信息。

我们希望将这些信息融入到这个LLM应用中。

最好的方式是将其添加到系统提示中,汉娜会详细介绍。

添加背景数据、文档和图像

我们要添加到提示的下一个内容是背景数据、文档和图像。

就像克里斯蒂安说的,我们对这个表格很了解。这个表格每次都会是相同的,它的形式不会改变。所以这是非常适合提供给 Claude 的信息类型。告诉 Claude,“这是你将要看到的表格的结构。” 我们知道这个结构在不同的查询之间不会改变。

表格的填写方式会变,但表格本身不会变。所以这是一种非常好的信息类型,可以放入系统提示中。如果你考虑使用提示缓存,这也是一个很好的选择。因为这部分总是相同的。

这会帮助 Claude 花更少的时间去弄清楚表格是什么,第一次看到表格时。它会更好地阅读表格,因为它已经知道会看到什么。

我想再提一点,关于我们如何组织提示中的信息。Claude 非常喜欢结构化,喜欢有条理。

所以我们推荐在你的提示中遵循一个标准的结构。还有一些其他的工具可以用来帮助 Claude 更好地理解信息。

我想说的是,我们所有的文档里都有这些内容,有很多很好的例子。所以,一定要拍照,但如果你忘了拍照,别担心。

所有这些内容都在网上,有很多例子,我们非常鼓励大家去看看。

你可以使用分隔符,比如 XML 标签。Markdown 对 Claude 也很有用,但 XML 标签的好处是你可以指定标签里的内容。所以我们可以告诉 Claude,“这是用户偏好。”

现在你要读一些内容,这些 XML 标签让你知道,标签里的所有内容都与用户的偏好有关。这有助于 Claude 在提示的后面部分引用这些信息。

引入对话历史

另一个我们想强调的话题,虽然我们在这个演示中没有做,那就是对话历史。这和示例的道理是一样的。我们用这个来确保 Claude 在处理你的事务时,有足够丰富的上下文信息。

在我们的案例中,这并不是一个面向用户的LLM应用。它更像是在后台运行。你可以想象,对于这家保险公司,他们有一个自动化的系统,会生成一些数据,然后可能在流程的最后有一个人在其中进行审核。

如果你要构建一个更面向用户的应用,比如你有一个很长的对话历史,你需要将其引入。这是在系统提示中引入的一个完美的位置,因为它丰富了 Claude 工作时所处的上下文。

提供示例

好的,现在我们回到幻灯片,谈谈一些我们在这个提示中没有真正用到,但对构建一个好的提示非常有帮助的其他内容。

我认为我们非常强调的一点是示例。“少样本学习”是一种能够非常有力地引导 Claude 的机制。

你可以想象,这在某种程度上是非同寻常的。比如你有一些对 Claude 来说很难处理的场景、情况,甚至是在这个案例中,一些具体的、棘手的事故,Claude 很难做出正确的判断,但你凭借你的人类直觉和你的人工标注数据,能够得出正确的结论。

你可以将这些信息融入到系统提示中,通过提供具体的示例。你可以有视觉示例,你可以直接用 Base64 编码一张图片,并将其作为数据的一部分传递给示例。

然后,你还可以描述如何分解和理解它。

这又回到了我们之前提到的,要分解 Claude 如何得出最终结论。这不仅更节省令牌,也是一个很好的方式,让你了解这些没有我们直觉的智能模型是如何处理我们提供的数据的。

因为这样,你可以真正地帮助 Claude,并将这些信息融入到系统提示中,让它变得更好。

定义输出格式

我们刚才已经看到了输出格式化的例子。你可以想象,如果你是一名正在处理这个 LLM 应用的数据工程师,所有这些华丽的前言虽然很好,但最终你想要的是你的那部分信息,并将其存储在,比如说你的 SQL 数据库里,或者任何你存储数据的地方。而

其余那些 Claude 用来做出判断的必要信息,对你的应用来说其实并不那么重要。

你想要的是具体的信息。为了做到这一点,你可以使用预填充响应。你可以想象,解析 XML 标签虽然不错,但也许你想要一个结构化的 JSON 输出,以确保它是 JSON 可序列化的,并且你可以在后续的调用中使用它。

这很简单,你只需要添加 Claude 需要以某种格式开始它的输出。这可以是一个花括号,或者像我们面前这个例子一样,是一个<itinerary>的 XML 标签。在我们的案例中,它也可以是那个<final_verdict> XML 标签。

这是一个很好的方式,再次,塑造 Claude 应该如何回应,而不需要所有那些前言,尽管那些前言对于塑造其输出,确保 Claude 按照我们想要的步骤进行推理是关键。

总结

所以,在我们的案例中,我们只是将它包装在最终的 verdict 中,然后解析出来。但你也可以使用预填充。所以你可以看到,在这次演示中,我们从一个滑雪事故,到一个不自信的,不确定的输出,也许是一个车祸的第二版,到现在一个更严格格式化的,自信的输出。

我们可以围绕它构建一个LLM应用,并真正帮助一个现实世界的汽车保险公司。

最后,在我们最终的提示中,我们还添加了一个简单的“重要指南”部分。

再次,这只是为了加强和重申我们希望 Claude 拥有的机械行为。我们希望确保摘要是清晰、简洁和准确的。我们希望确保没有任何东西妨碍 Claude 的评估,除了它正在分析的数据。

最后,关于输出格式化,在我的案例中,我会让 Claude 把它的最终结论,所有其他的东西我都会在我的应用中忽略,只看它实际评估了什么。

我可以将这个用于构建某种分析工具,或者如果我只是想要一个明确的判断,我可以用这种方式来做。

现在,你可以看到 Claude 已经开始按照这些步骤进行推理了。

好的,谢谢大家。