跳转到主要内容
Chal1ce blog

吴恩达课程《面向开发者的Prompt工程》———— 学习笔记(一)

这是对吴恩达《面向开发者的Prompt工程》的学习笔记

吴恩达课程《面向开发者的Prompt工程》——— 学习笔记(一)

课程概述

吴恩达的《ChatGPT Prompt Engineering for Developers》课程中文版,主要教开发者如何编写Prompt并利用OpenAI API创建基于大型语言模型(LLM)的新应用。课程内容包括:

  • 编写Prompt的基本原则(这一章的笔记)
  • 文本总结(见后续笔记)
  • 文本推断(见后续笔记)
  • 文本转换(见后续笔记)
  • 扩展功能(见后续笔记)
  • 英文原版课程链接:ChatGPT Prompt Engineering for Developers(https://learn.deeplearning.ai/)

提示词原则

原则一:指令清晰、要求具体

1、通过提供尽量清晰和具体的指令来表达你希望模型执行的操作,这样可以引导模型给出准确的回答,减少出现无关或错误响应的几率。

2、编写清晰的指令并不等于简短的指令,因为在很多情况下,更长的提示词实际上更清晰(例如提供更多上下文信息),这会带来更详细和相关的输出。

  • 策略一:结构化输入,使用分隔符清晰地表示输入的不同部分,例如:###、\n\n等等。你可以用明显的标点符号将特定的文本部分与提示的其他部分分开,这样可以让模型清楚地知道这是一个独立的部分。

    例子:

prompt="""
##角色:
你是一名优秀的开发工程师
##任务:
你可以根据我的需求,帮助我写出符合我要求的代码
##要求:
{user_input}
"""
  • 策略二:结构化输出,生成结构化输出,如JSON或HTML格式,可使信息的解析变得更加简便和高效。这种格式化的输出有助于我们更快地理解和处理数据。例子:

输入:

prompt = f"""
请生成包括书名、作者和类别的三本虚构书籍清单,\
并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。
"""
response = get_completion(prompt)
print(response)

输出:

{
  "books": [
    {
      "book_id": 1,
      "title": "The Shadow of the Wind",
      "author": "Carlos Ruiz Zafón",
      "genre": "Mystery"
    },
    {
      "book_id": 2,
      "title": "The Name of the Wind",
      "author": "Patrick Rothfuss",
      "genre": "Fantasy"
    }]
}
  • 策略三:让模型自检是否符合条件。

如果任务的预设条件可能不被满足,我们可以设定模型先进行条件检查,若条件不被满足,则应提示并中止任务的执行。以下是两个示例,我们将为模型提供两段文本,一段是关于如何制作茶的步骤,另一段则是没有明确步骤的文本。我们的需求是让模型判断这些文本是否包含一连串的指令。

  • 如果包含,要求模型用给定的格式来重述这些指令;
  • 如果不包含,则回答没有提供具体步骤。

输入:

# 有步骤的文本text_1 = f"""泡一杯茶很容易。首先,需要把水烧开。\在等待期间,拿一个杯子并把茶包放进去。\一旦水足够热,就把它倒在茶包上。\等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\如果你愿意,可以加一些糖或牛奶调味。\就这样,你可以享受一杯美味的茶了。"""prompt = f"""您将获得由三个引号括起来的文本。\如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:第一步 - ...第二步 - ……第N步 - …如果文本中不包含一系列的指令,则直接写“未提供步骤”。"\"\"\"{text_1}\"\"\""""

response = get_completion(prompt)
print("Text 1 的总结:")
print(response)

输出:

Text 1 的总结:
第一步 - 把水烧开。
第二步 - 拿一个杯子并把茶包放进去。
第三步 - 把热水倒在茶包上。
第四步 - 等待几分钟,让茶叶浸泡。
第五步 - 取出茶包。
第六步 - 如果你愿意,可以加一些糖或牛奶调味。
第七步 - 就这样,你可以享受一杯美味的茶了。

输入:

# 无步骤的文本
text_2 = f"""
今天阳光明媚,鸟儿在歌唱。\
这是一个去公园散步的美好日子。\
鲜花盛开,树枝在微风中轻轻摇曳。\
人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\
这是一个完美的日子,可以在户外度过并欣赏大自然的美景。
"""
prompt = f"""
您将获得由三个引号括起来的文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:

第一步 - ...
第二步 - …
第N步 - …

如果文本中不包含一系列的指令,则直接写“未提供步骤”。"
\"\"\"{text_2}\"\"\"
"""
response = get_completion(prompt)
print("Text 2 的总结:")
print(response)

输出:

Text 2 的总结:
未提供步骤。
  • 策略四:提供少量示例(few shot)

在实际要求模型执行任务前,提供一些成功的示例是非常有帮助的。

例如,在下面的例子中,我们向模型说明其任务是以一致的风格回答问题,并首先提供一个孩子与祖父对话的示例。在这个对话中,孩子请求:“教我耐心”,祖父则以隐喻的方式进行回答。由于我们已经指明了回答应保持一致的风格,当我们接着提出“教我韧性”这一请求时,模型已经通过之前的示例学会了如何用类似的风格进行回答。

输入:

prompt = f"""
你的任务是以一致的风格回答问题。

<孩子>: 教我耐心。

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

<孩子>: 教我韧性。
"""
response = get_completion(prompt)
print(response)

输出:

<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。所以,当你遇到挫折和困难时,不要轻易放弃,要像树一样坚定地扎根,不断成长,最终成为一棵高大的树。

原则二:任务复杂时,给模型思考的时间

在处理复杂任务时,如果模型匆忙作出错误判断,应该重新设计提示词,让模型在给出最终答案前进行更深入的推理过程。换言之,如果一个任务在短时间内或仅凭少量信息难以完成,模型可能做出错误的猜测。

  • 策略一:指定完成任务所需的步骤。

我们将通过执行一个复杂的任务及其分步执行方法,来演示这种策略的效果。首先,我们介绍了一个关于杰克和吉尔的故事,并为此制定了一系列操作指令。这些操作包括:首先,用一句话总结三个用反引号标记的文本段落。接着,将这个摘要翻译成英语。然后,在英语摘要中标出所有的人名。最后,创建一个包含英语摘要和人名数量的 JSON 对象,并使用换行符来分隔这些答案。

文本:

text = f"""
在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\
他们一边唱着欢乐的歌,一边往上爬,\
然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\
虽然略有些摔伤,但他们还是回到了温馨的家中。\
尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。
"""

输入:

prompt_2 = f"""
1-用一句话概括下面用<>括起来的文本。
2-将摘要翻译成英语。
3-在英语摘要中列出每个名称。
4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。

请使用以下格式:
文本:<要总结的文本>
摘要:<摘要>
翻译:<摘要的翻译>
名称:<英语摘要中的名称列表>
输出 JSON:<带有 English_summary 和 num_names 的 JSON>

Text: <{text}>
"""
response = get_completion(prompt_2)
print("\nprompt 2:")
print(response)

输出:

prompt 2:
摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。
翻译:In a charming village, siblings Jack and Jill set out to fetch water from a mountaintop well. While climbing and singing, Jack trips on a stone and tumbles down the mountain, with Jill following closely behind. Despite some bruises, they make it back home safely. Their adventurous spirit remains undiminished as they continue to explore with joy.
名称:Jack,Jill
输出 JSON:{"English_summary": "In a charming village, siblings Jack and Jill set out to fetch water from a mountaintop well. While climbing and singing, Jack trips on a stone and tumbles down the mountain, with Jill following closely behind. Despite some bruises, they make it back home safely. Their adventurous spirit remains undiminished as they continue to explore with joy.", "num_names": 2}
  • 策略二:指导模型在下结论前,一步一步思考(Step by step),找出一个自己的解法

有时候,当我们明确要求模型在做出决策前仔细考虑各种解决方案时,我们通常能获得更佳的结果。

接着,我们将提出一个问题和一个学生的回答,并要求模型评估这个回答的正确性。

输入:

prompt = f"""
请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:

步骤:

    首先,自己解决问题。
    然后将你的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。在自己完成问题之前,请勿决定学生的解决方案是否正确。

使用以下格式:

    问题:问题文本
    学生的解决方案:学生的解决方案文本
    实际解决方案和步骤:实际解决方案和步骤文本
    学生的解决方案和实际解决方案是否相同:是或否
    学生的成绩:正确或不正确

问题:

    我正在建造一个太阳能发电站,需要帮助计算财务。
    - 土地费用为每平方英尺100美元
    - 我可以以每平方英尺250美元的价格购买太阳能电池板
    - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
    作为平方英尺数的函数,首年运营的总费用是多少。

学生的解决方案:

    设x为发电站的大小,单位为平方英尺。
    费用:
    1. 土地费用:100x
    2. 太阳能电池板费用:250x
    3. 维护费用:100,000+100x
    总费用:100x+250x+100,000+100x=450x+100,000

实际解决方案和步骤:
"""
response = get_completion(prompt)
print(response)

输出:

正确的解决方案和步骤:
    1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元
    2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元
    3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元
    4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元

学生的解决方案和实际解决方案是否相同:否

学生的成绩:不正确

Tip:请注意,尽管大模型会尽力提供准确的信息和解答,但它的输出仍然存在一定的不稳定性。我们建议在使用模型的答案或建议做出任何重要决策之前,自行进行核查和验证,这样做可以避免可能的错误。

Reference:

https://prompt-engineering.xiniushu.com/guides/guidelines


所有文章同步在微信公众号中

欢迎大家关注我的公众号Chal1ceAI