策略
本节包含针对特定需求或问题的示例和策略。要成功进行提示工程,您需要结合本文档中列举的所有策略的某个子集。不要害怕混合搭配——或者发明您自己的方法。
嵌入数据
在隐藏上下文中,您经常需要嵌入各种数据。具体策略将根据您嵌入的数据的类型和数量而有所不同。
简单列表
对于一次性对象,在普通项目符号列表中枚举字段+值效果很好:
它也适用于更大的事物集合,但对于数据列表,GPT 处理其他格式更可靠。无论如何,这里是一个例子:
Markdown 表格
Markdown 表格非常适合需要枚举许多相同类型项目的场景。
幸运的是,OpenAI 的模型在处理 Markdown 表格方面表现出色(可能是因为它们训练了大量的 GitHub 数据)。
我们可以使用 Markdown 表格重新构建上述示例:
🧠 请注意,在最后一个例子中,表格中的项目有明确的日期,2月2日。在我们的问题中,我们询问了"今天"。而在提示的早期,我们提到今天是2月2日。模型正确处理了传递推理——将"今天"转换为"2月2日",然后在表格中查找"2月2日"。
JSON
Markdown 表格在许多用例中效果很好,由于其密度和模型可靠处理它们的能力,应该优先使用,但您可能会遇到一些场景,即您有许多列,模型难以处理,或者每个项目都有一些自定义属性,拥有数十列空数据是没有意义的。
在这些场景中,JSON 是模型处理得很好的另一种格式。键
与其值
的接近性使模型能够轻松保持映射的正确性。
以下是与 Markdown 表格相同的示例,但使用 JSON:
自由文本
有时您会想在提示中包含自由文本,您希望将其与提示的其余部分区分开来——例如嵌入文档供机器人参考。在这些场景中,用三个反引号```包围文档效果很好。
嵌套数据
并非所有数据都是平面和线性的。有时您需要嵌入嵌套的数据或与其他数据有关系的数据。在这些场景中,依赖 JSON
:
(完整提示)
您是一个有用的助手。您回答关于用户的问题。以下是您对他们的了解:
{
"users": [
{
"id": 1,
"name": "John Doe",
"contact": {
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "12345"
},
"phone": "555-555-1234",
"email": "johndoe@example.com"
}
},
{
"id": 2,
"name": "Jane Smith",
"contact": {
"address": {
"street": "456 Elm St",
"city": "Sometown",
"state": "TX",
"zip": "54321"
},
"phone": "555-555-5678",
"email": "janesmith@example.com"
}
},
{
"id": 3,
"name": "Alice Johnson",
"contact": {
"address": {
"street": "789 Oak St",
"city": "Othertown",
"state": "NY",
"zip": "67890"
},
"phone": "555-555-2468",
"email": "alicejohnson@example.com"
}
},
{
"id": 4,
"name": "Bob Williams",
"contact": {
"address": {
"street": "135 Maple St",
"city": "Thistown",
"state": "FL",
"zip": "98765"
},
"phone": "555-555-8642",
"email": "bobwilliams@example.com"
}
},
{
"id": 5,
"name": "Charlie Brown",
"contact": {
"address": {
"street": "246 Pine St",
"city": "Thatstown",
"state": "WA",
"zip": "86420"
},
"phone": "555-555-7531",
"email": "charliebrown@example.com"
}
},
{
"id": 6,
"name": "Diane Davis",
"contact": {
"address": {
"street": "369 Willow St",
"city": "Sumtown",
"state": "CO",
"zip": "15980"
},
"phone": "555-555-9512",
"email": "dianedavis@example.com"
}
},
{
"id": 7,
"name": "Edward Martinez",
"contact": {
"address": {
"street": "482 Aspen St",
"city": "Newtown",
"state": "MI",
"zip": "35742"
},
"phone": "555-555-6813",
"email": "edwardmartinez@example.com"
}
},
{
"id": 8,
"name": "Fiona Taylor",
"contact": {
"address": {
"street": "531 Birch St",
"city": "Oldtown",
"state": "OH",
"zip": "85249"
},
"phone": "555-555-4268",
"email": "fionataylor@example.com"
}
},
{
"id": 9,
"name": "George Thompson",
"contact": {
"address": {
"street": "678 Cedar St",
"city": "Nexttown",
"state": "GA",
"zip": "74125"
},
"phone": "555-555-3142",
"email": "georgethompson@example.com"
}
},
{
"id": 10,
"name": "Helen White",
"contact": {
"address": {
"street": "852 Spruce St",
"city": "Lasttown",
"state": "VA",
"zip": "96321"
},
"phone": "555-555-7890",
"email": "helenwhite@example.com"
}
}
]
}
如果使用嵌套的 JSON
对您的 token 预算来说过于冗长,可以回退到用 Markdown
定义的关系表
:
(完整提示)
您是一个有用的助手。您回答关于用户的问题。以下是您对他们的了解:
表 1:用户
| id (PK) | name |
|---------|---------------|
| 1 | John Doe |
| 2 | Jane Smith |
| 3 | Alice Johnson |
| 4 | Bob Williams |
| 5 | Charlie Brown |
| 6 | Diane Davis |
| 7 | Edward Martinez |
| 8 | Fiona Taylor |
| 9 | George Thompson |
| 10 | Helen White |
表 2:地址
| id (PK) | user_id (FK) | street | city | state | zip |
|---------|--------------|-------------|------------|-------|-------|
| 1 | 1 | 123 Main St | Anytown | CA | 12345 |
| 2 | 2 | 456 Elm St | Sometown | TX | 54321 |
| 3 | 3 | 789 Oak St | Othertown | NY | 67890 |
| 4 | 4 | 135 Maple St | Thistown | FL | 98765 |
| 5 | 5 | 246 Pine St | Thatstown | WA | 86420 |
| 6 | 6 | 369 Willow St | Sumtown | CO | 15980 |
| 7 | 7 | 482 Aspen St | Newtown | MI | 35742 |
| 8 | 8 | 531 Birch St | Oldtown | OH | 85249 |
| 9 | 9 | 678 Cedar St | Nexttown | GA | 74125 |
| 10 | 10 | 852 Spruce St | Lasttown | VA | 96321 |
表 3:电话号码
| id (PK) | user_id (FK) | phone |
|---------|--------------|-------------|
| 1 | 1 | 555-555-1234 |
| 2 | 2 | 555-555-5678 |
| 3 | 3 | 555-555-2468 |
| 4 | 4 | 555-555-8642 |
| 5 | 5 | 555-555-7531 |
| 6 | 6 | 555-555-9512 |
| 7 | 7 | 555-555-6813 |
| 8 | 8 | 555-555-4268 |
| 9 | 9 | 555-555-3142 |
| 10 | 10 | 555-555-7890 |
表 4:邮箱
| id (PK) | user_id (FK) | email |
|---------|--------------|-----------------------|
| 1 | 1 | johndoe@example.com |
| 2 | 2 | janesmith@example.com |
| 3 | 3 | alicejohnson@example.com |
| 4 | 4 | bobwilliams@example.com |
| 5 | 5 | charliebrown@example.com |
| 6 | 6 | dianedavis@example.com |
| 7 | 7 | edwardmartinez@example.com |
| 8 | 8 | fionataylor@example.com |
| 9 | 9 | georgethompson@example.com |
| 10 | 10 | helenwhite@example.com |
表 5:城市
| id (PK) | name | state | population | median_income |
|---------|--------------|-------|------------|---------------|
| 1 | Anytown | CA | 50,000 | $70,000 |
| 2 | Sometown | TX | 100,000 | $60,000 |
| 3 | Othertown | NY | 25,000 | $80,000 |
| 4 | Thistown | FL | 75,000 | $65,000 |
| 5 | Thatstown | WA | 40,000 | $75,000 |
| 6 | Sumtown | CO | 20,000 | $85,000 |
| 7 | Newtown | MI | 60,000 | $55,000 |
| 8 | Oldtown | OH | 30,000 | $70,000 |
| 9 | Nexttown | GA | 15,000 | $90,000 |
| 10 | Lasttown | VA | 10,000 | $100,000 |
🧠 模型在第三范式数据方面表现良好,但可能在太多连接方面有困难。在实验中,它似乎可以处理至少三个级别的嵌套连接。在上面的例子中,模型成功地从
用户
连接到地址
再到城市
来推断George的可能收入——$90,000。
引用
通常,自然语言响应本身是不够的,您希望模型的输出引用它从哪里获取数据。
这里有一个有用的注意事项是,您可能想要引用的任何内容都应该有一个唯一的ID。最简单的方法就是要求模型链接到它引用的任何内容:
程序化消费
默认情况下,语言模型输出自然语言文本,但我们经常需要以超越简单地在屏幕上打印出来的程序化方式与此结果交互。您可以通过要求模型以您喜欢的序列化格式(JSON和YAML似乎效果最好)输出结果来实现这一点。
确保给模型一个您想要的输出格式的示例。基于我们之前的旅行示例,我们可以增强我们的提示来告诉它:
以JSON格式产生您的输出。格式应该是:
```
{
message: "要向用户显示的消息",
hotelId: 432,
flightId: 831
}
```
不要在您的消息中包含ID。
现在我们会得到这样的交互:
您可以想象这个UI将消息渲染为普通文本,但还添加了预订航班+酒店的离散按钮,或为用户自动填充表单。
作为另一个例子,让我们基于引用示例——但超越Markdown链接。我们可以要求它产生JSON,包含正常消息以及在创建该消息时使用的项目列表。在这种情况下,您不会确切地知道消息中哪里使用了引用,但您会知道它们在某处被使用了。
🧠 有趣的是,在模型对"我在Target花了多少钱?"的响应中,它提供了一个单一值,$188.16,但重要的是在
引用
数组中,它列出了用于计算该值的各个费用。
思维链
有时您会在提示上拼命尝试让模型输出可靠的结果,但无论您做什么,它就是不起作用。当机器人的最终输出需要中间思考,但您只要求机器人输出而不要求其他任何东西时,这种情况经常发生。
答案可能会让您感到惊讶:要求机器人展示其工作。2022年10月,谷歌发布了一篇论文"思维链提示在大型语言模型中引发推理",他们表明,如果在您的隐藏提示中,您给机器人展示工作的回答问题的例子,那么当您要求机器人回答某些问题时,它会展示其工作并产生更可靠的答案。
就在那篇论文发表几周后,在2022年10月底,东京大学和谷歌发布了论文"大型语言模型是零样本推理器",他们表明您甚至不需要提供例子——您只需要要求机器人逐步思考。
平均值计算
这里是一个例子,我们要求机器人计算平均费用,排除Target。实际答案是$136.77,机器人用$136.43几乎得到了正确答案。
如果我们简单地添加"让我们逐步思考",模型得到了正确答案:
解释代码
让我们重新审视之前的Python例子,并将思维链提示应用到我们的问题中。作为提醒,当我们要求机器人评估Python代码时,它得到了稍微错误的结果。正确答案是Hello, Brex!!Brex!!Brex!!!
,但机器人对要包含多少个!感到困惑。在下面的例子中,它输出Hello, Brex!!!Brex!!!Brex!!!
:
如果我们要求机器人展示其工作,那么它得到了正确答案:
分隔符
在许多场景中,您可能不想向最终用户显示机器人的所有思考,而只想显示最终答案。您可以要求机器人将最终答案与其思考区分开来。有许多方法可以做到这一点,但让我们使用JSON使其易于解析:
使用思维链提示将消耗更多tokens,导致成本和延迟增加,但对于许多场景,结果明显更可靠。当您需要机器人做复杂的事情并尽可能可靠时,这是一个有价值的工具。
微调
有时无论您对模型使用什么技巧,它就是不会按您想要的方式工作。在这些场景中,您有时可以回退到微调。一般来说,这应该是最后的手段。
微调是获取已经训练好的模型,然后给它数千个(或更多)输入:输出
对的过程。
它不能消除对隐藏提示的需要,因为您仍然需要嵌入动态数据,但它可能使提示更小且更可靠。
缺点
微调有许多缺点。如果可能的话,通过在提示中教导语言模型做某事来利用语言模型作为零样本、一样本和少样本学习者的特性,而不是微调。
一些缺点包括:
- 不可能:GPT-3.5/GPT-4不可微调,这是我们将使用的主要模型/API,所以我们根本无法依赖微调。
- 开销:微调需要手动创建大量数据。
- 速度:迭代循环变得更慢——每次您想添加新功能时,不是在提示中添加几行,而是需要创建一堆假数据,然后运行微调过程,然后使用新微调的模型。
- 成本:使用微调的GPT-3模型比标准
gpt-3.5-turbo
模型贵60倍。使用微调的GPT-3模型比标准GPT-4模型贵2倍。
⛔️ 如果您微调模型,绝不要使用真实客户数据。始终使用合成数据。模型可能会记住您提供的部分数据,并可能向不应该看到它的其他用户重新表述私人数据。
如果您从不微调模型,我们就不必担心意外将数据泄露到模型中。