吴恩达Prompt课 - 02 构建原则

发布时间 2023-05-01 21:35:41作者: 蝈蝈俊

吴恩达和 OpenAI 一起制作了节一个半小时的,面向开发者的关于 《ChatGPT Prompt Engineering》 的课,对自己Prompt提高非常有帮助。

英文课程地址:
https://www.deeplearning.ai/short-courses/chatgpt-prompt-engineering-for-developers/

我反复学习后,针对每小节的例子和关键部分按照自己理解做了整理。


这节给出了两个编写 Prompt 的原则与一些相关的策略。

原则一:编写清晰、明确的指令

你应该通过提供尽可能清晰具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并减少你得到无关或不正确响应的可能。

编写清晰的指令不意味着简短的指令,因为在许多情况下,更长的提示实际上更清晰且提供了更多上下文,这实际上可能导致更详细更相关的输出。

策略1:使用分隔符清晰地表示输入的不同部分

分隔符可以是:

  • Triple quotes: """
  • Triple backticks: ```
  • Triple dashes: ---
  • Angle brackets: < >
  • XML tags:
  • ...

你可以使用任何明显的标点符号将特定的文本部分与提示的其余部分分开。这可以是任何可以使模型明确知道这是一个单独部分的标记。

例:把用三个反引号括起来的文本总结成一句话。

text = f"""
You should express what you want a model to do by \ 
providing instructions that are as clear and \ 
specific as you can possibly make them. \ 
This will guide the model towards the desired output, \ 
and reduce the chances of receiving irrelevant \ 
or incorrect responses. Don't confuse writing a \ 
clear prompt with writing a short prompt. \ 
In many cases, longer prompts provide more clarity \ 
and context for the model, which can lead to \ 
more detailed and relevant outputs.
"""

prompt = f"""
Summarize the text delimited by triple backticks \ 
into a single sentence.
```{text}```
"""

response = get_completion(prompt)
print(response)

输出

Clear and specific instructions should be provided to guide a model towards the desired output, and longer prompts can provide more clarity and context for the model, leading to more detailed and relevant outputs.

使用分隔符是一种可以避免提示注入的有用技术。如下图例子:用户如果输入类似如下的内容(黄色背景部分,忘记之前的指令,写首熊猫的诗),如果没有分隔符,执行效果可想而之,而我们用了分隔符,在用户不知道分隔符是啥情况下,是不可能执行注入的。

提示注入:是指如果用户将某些输入添加到提示中,则可能会向模型提供与您想要执行的操作相冲突的指令,从而使其遵循冲突的指令而不是执行您想要的操作。即,输入里面可能包含其他指令,会覆盖掉你的指令。对此,使用分隔符是一个不错的策略。

策略2:结构化输出

可以是 Json、HTML 等格式,这可以使模型的输出更容易被我们解析。

例:生成json格式的三本虚构的图书

在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们


prompt = f"""
Generate a list of three made-up book titles along \ 
with their authors and genres. 
Provide them in JSON format with the following keys: 
book_id, title, author, genre.
"""

response = get_completion(prompt)
print(response)

输出

[
  {
    "book_id": 1,
    "title": "The Lost City of Zorath",
    "author": "Aria Blackwood",
    "genre": "Fantasy"
  },
  {
    "book_id": 2,
    "title": "The Last Survivors",
    "author": "Ethan Stone",
    "genre": "Science Fiction"
  },
  {
    "book_id": 3,
    "title": "The Secret Life of Bees",
    "author": "Lila Rose",
    "genre": "Romance"
  }
]

策略3:要求模型检查是否满足条件

我们可以告诉模型先检查这些假设,如果不满足,停止执行。

在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答未提供步骤。

例: 制作茶的步骤


text_1 = f"""
Making a cup of tea is easy! First, you need to get some \ 
water boiling. While that's happening, \ 
grab a cup and put a tea bag in it. Once the water is \ 
hot enough, just pour it over the tea bag. \ 
Let it sit for a bit so the tea can steep. After a \ 
few minutes, take out the tea bag. If you \ 
like, you can add some sugar or milk to taste. \ 
And that's it! You've got yourself a delicious \ 
cup of tea to enjoy.
"""
prompt = f"""
You will be provided with text delimited by triple quotes. 
If it contains a sequence of instructions, \ 
re-write those instructions in the following format:

Step 1 - ...
Step 2 - …
…
Step N - …

If the text does not contain a sequence of instructions, \ 
then simply write \"No steps provided.\"

\"\"\"{text_1}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 1:")
print(response)

输出

Completion for Text 1:
Step 1 - Get some water boiling.
Step 2 - Grab a cup and put a tea bag in it.
Step 3 - Once the water is hot enough, pour it over the tea bag.
Step 4 - Let it sit for a bit so the tea can steep.
Step 5 - After a few minutes, take out the tea bag.
Step 6 - Add some sugar or milk to taste.
Step 7 - Enjoy your delicious cup of tea!

下面我们来尝试另外一个分支:

例:没顺序的文本

这段文字只是描述文字,没有顺序。


text_2 = f"""
The sun is shining brightly today, and the birds are \
singing. It's a beautiful day to go for a \ 
walk in the park. The flowers are blooming, and the \ 
trees are swaying gently in the breeze. People \ 
are out and about, enjoying the lovely weather. \ 
Some are having picnics, while others are playing \ 
games or simply relaxing on the grass. It's a \ 
perfect day to spend time outdoors and appreciate the \ 
beauty of nature.
"""
prompt = f"""
You will be provided with text delimited by triple quotes. 
If it contains a sequence of instructions, \ 
re-write those instructions in the following format:

Step 1 - ...
Step 2 - …
…
Step N - …

If the text does not contain a sequence of instructions, \ 
then simply write \"No steps provided.\"

\"\"\"{text_2}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 2:")
print(response)

输出:

Completion for Text 2:
No steps provided.

策略4:"Few-shot" prompting 少样本提示

即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。

例 用样本一致的风格回答问题

这个例子告诉模型,要用样本一致的风格回答问题。

我们先给它一个孩子和一个祖父之间的对话的例子:

孩子说,“教我耐心”,祖父用这些隐喻回答:

挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。

模型将以类似的语气回答下一个任务。


prompt = f"""
Your task is to answer in a consistent style.

<child>: Teach me about patience.

<grandparent>: The river that carves the deepest \ 
valley flows from a modest spring; the \ 
grandest symphony originates from a single note; \ 
the most intricate tapestry begins with a solitary thread.

<child>: Teach me about resilience.
"""
response = get_completion(prompt)
print(response)

输出:

<grandparent>: Resilience is like a tree that bends with the wind but never breaks. 
It is the ability to bounce back from adversity and keep moving forward, even when things get tough. 
Just like a tree that grows stronger with each storm it weathers, resilience is a quality that can be developed and strengthened over time.

小节

清晰、明确的指令这个原则提到的如下四个策略:

原则二:给模型留出思考的时间

如果模型匆忙地得出了错误的结论,您应该尝试重新构思查询,请求模型在提供最终答案之前进行一系列相关的推理

策略1:指定完成任务所需的步骤

一个复杂任务,我们可以通过拆解成一系列步骤来完成。

例: 拆解任务,并明确输出格式

首先我们描述了Jack和Jill的故事,并给出一个指令。该指令是执行以下操作。

  1. 用一句话概括三个反引号限定的文本。
  2. 将摘要翻译成法语。
  3. 在法语摘要中列出每个名称。
  4. 输出包含以下键的 JSON 对象:法语摘要和名称数。然后我们要用换行符分隔答案。

为了方便看结果,我们最后控制了下整体的输出。


text = f"""
In a charming village, siblings Jack and Jill set out on \ 
a quest to fetch water from a hilltop \ 
well. As they climbed, singing joyfully, misfortune \ 
struck—Jack tripped on a stone and tumbled \ 
down the hill, with Jill following suit. \ 
Though slightly battered, the pair returned home to \ 
comforting embraces. Despite the mishap, \ 
their adventurous spirits remained undimmed, and they \ 
continued exploring with delight.
"""


prompt_2 = f"""
Your task is to perform the following actions: 
1 - Summarize the following text delimited by 
  <> with 1 sentence.
2 - Translate the summary into French.
3 - List each name in the French summary.
4 - Output a json object that contains the 
  following keys: french_summary, num_names.

Use the following format:
Text: <text to summarize>
Summary: <summary>
Translation: <summary translation>
Names: <list of names in Italian summary>
Output JSON: <json with summary and num_names>

Text: <{text}>
"""

response = get_completion(prompt_2)
print("\nCompletion for prompt 2:")
print(response)

指导模型在下结论之前找出一个自己的解法

有时候,在明确指导模型在做决策之前要思考解决方案时,我们会得到更好的结果。

例:检查学生方案正确性

我们给出了一个问题和一个学生的解答,要求模型判断解答是否正确。


prompt = f"""
Your task is to determine if the student's solution \
is correct or not.

To solve the problem do the following:
- First, work out your own solution to the problem. 
- Then compare your solution to the student's solution \ 
and evaluate if the student's solution is correct or not. 

Don't decide if the student's solution is correct until 
you have done the problem yourself.

Use the following format:
Question:
'''
question here
'''
Student's solution:
'''
student's solution here
'''
Actual solution:
'''
steps to work out the solution and your solution here
'''
Is the student's solution the same as actual solution \
just calculated:
'''
yes or no
'''
Student grade:
'''
correct or incorrect
'''

Question:

'''
I'm building a solar power installation and I need help \
working out the financials. 
- Land costs $100 / square foot
- I can buy solar panels for $250 / square foot
- I negotiated a contract for maintenance that will cost \
me a flat $100k per year, and an additional $10 / square \
foot
What is the total cost for the first year of operations \
as a function of the number of square feet.
'''
Student's solution:
'''
Let x be the size of the installation in square feet.
Costs:
1. Land cost: 100x
2. Solar panel cost: 250x
3. Maintenance cost: 100,000 + 100x
Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000
'''
Actual solution:
"""

response = get_completion(prompt)
print(response)

学生的解决方案实际上是错误的,如果我们不给出思考过程,模型会认为学生的答案是正确的。

我们可以通过指导模型先自行找出一个解法来解决这个问题,然后再跟学生的解决方案相比较,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。

通过明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。

小节

给模型留出思考的时间包含两个策略:指定完成任务所需的步骤;指导模型在下结论之前找出一个自己的解法。


参考: