完成了1和一部分2的校正,修复了部分bug并更新了翻译

This commit is contained in:
Yixin Zhang
2023-07-01 01:42:15 +08:00
parent aec843c887
commit d60514579c
2 changed files with 73 additions and 48 deletions

View File

@ -2,20 +2,21 @@
**作者 吴恩达教授**
欢迎来到本课程,我们将为开发人员介绍 ChatGPT 提示工程。本课程由 Isa Fulford 教授和我一起授课。Isa Fulford 是 OpenAI 的技术团队成员,曾开发过受欢迎的 ChatGPT 检索插件,并且在教授人们如何在产品中使用 LLM 或 LLM 技术方面做出了很大贡献。她还参与编写了教授人们使用 Prompt 的 OpenAI cookbook。
欢迎来到本课程,我们将为开发人员介绍 ChatGPT 提示工程Prompt Engineering。本课程由 Isa Fulford 教授和我一起授课。Isa 是 OpenAI 的技术团队成员,曾开发过受欢迎的 ChatGPT 检索插件,并且在教授 LLM Large Language Model,大语言模型)技术在产品中的应用方面做出了很大贡献。她还参与编写了教授人们使用 Prompt 的 OpenAI cookbook。
互联网上有很多有关提示的材料例如《30 prompts everyone has to know》之类的文章。这些文章主要集中在 ChatGPT Web 用户界面上,许多人在使用它执行特定的、通常是一次性的任务。但是,我认为 LLM 或大型语言模型作为开发人员的更强大功能是使用 API 调用到 LLM快速构建软件应用程序。我认为这方面还没有得到充分的重视。实际上,我们在 DeepLearning.AI 的姊妹公司 AI Fund 的团队一直在与许多初创公司合作,将这些技术应用于许多不同的应用程序上。看到 LLM API 能够让开发人员非常快速地构建应用程序,这真是令人兴奋。
互联网上有很多有关提示Prompt的材料例如《30 prompts everyone has to know》之类的文章。这些文章主要集中在 ChatGPT Web 用户界面上,许多人在使用它执行特定的、通常是一次性的任务。但是,我认为作为开发人员LLM的更强大功能是能通过 API 调用,从而快速构建软件应用程序。我认为这方面还没有得到充分的重视。
实际上,我们在 DeepLearning.AI 的姊妹公司 AI Fund 的团队一直在与许多初创公司合作,将这些技术应用于诸多应用程序上。很兴奋能看到 LLM API 能够让开发人员非常快速地构建应用程序。
在本课程中,我们将与您分享一些可能性以及如何实现它们的最佳实践
在本课程中,我们将与您分享一些技巧来挖掘LLM的潜力也会提供应用上的最佳实践。过程中会涉及大量材料。首先你会学习到用于软件开发的prompr最佳实践随后会涉及到几个常用使用例包括概括、推断、转换与扩展最后会利用LLM构建chatbot聊天机器人。希望这能激发你的想象力去开拓新应用
随着大型语言模型(LLM的发展,LLM 大致可以分为两种类型,基础LLM和指令微调LLM。基础LLM是基于文本训练数据训练出预测下一个单词能力的模型其通常在互联网和其他来源的大量数据上训练。例如如果你以“从前有一只独角兽”作为提示基础LLM可能会继续预测“生活在一个与所有独角兽朋友的神奇森林中”。但是如果你以“法国的首都是什么”为提示则基础LLM可能会根据互联网上的文章将答预测为“法国最大的城市是什么?法国的人口是多少?”,因为互联网上的文章很可能是有关法国国家的问答题目列表。
随着LLM的发展大致可以分为两种类型,后续称为基础LLM和指令微调Instruction TunedLLM。基础LLM是基于文本训练数据训练出预测下一个单词能力的模型其通常通过在互联网和其他来源的大量数据上训练,来确定紧接着出现的最可能的词。例如,如果你以“从前,有一只独角兽”作为提示基础LLM可能会继续预测“她与独角兽朋友共同生活在一片神奇森林中”。但是,如果你以“法国的首都是什么”为提示则基础LLM可能会根据互联网上的文章答预测为“法国最大的城市是什么?法国的人口是多少?”,因为互联网上的文章很可能是有关法国国家的问答题目列表。
许多 LLMs 的研究和实践的动力正在指令调整的 LLMs 上。指令调整的 LLMs 已经被训练来遵循指。因此,如果你问它,“法国的首都是什么?”,它有可能输出“法国的首都是巴黎”。指令调整的 LLMs 的训练通常是从已经训练好的基本 LLMs 开始,该模型已经在大量文本数据上进行了训练。然后,使用输入是指令、输出是其应该返回的结果的数据集来对其进行微调,要求它遵循这些指令。然后通常使用一种称为 RLHFreinforcement learning from human feedback人类反馈强化学习的技术进行进一步改进使系统更能够有帮助地遵循指令。
而对于指令微调的LLM相关研究和实践正甚嚣尘上训练它们来遵循指。因此,如果你问它,“法国的首都是什么?”,它有极大可能输出“法国的首都是巴黎”。指令微调的LLM的训练通常是基于预训练好的LLM的模型已经在大量文本数据上进行了训练。然后对其进行进一步训练与微调finetune使用的数据包括输入和理想输出输入是指令、输出是遵循这些指令的良好回答。然后通常使用一种称为 RLHFreinforcement learning from human feedback人类反馈强化学习的技术进行进一步改进使系统更能够有帮助地遵循指令。
因为指令调的 LLMs 已经被训练成有益、诚实和无害的所以与基础LLMs相比它们更不可能输出有问题的文本如有害输出。许多实际使用场景已经转向指令调的LLMs。您在互联网上找到的一些最佳实践可能更适用于基础LLMs但对于今天的大多数实际应用我们建议将注意力集中在指令调的LLMs上这些LLMs更容易使用而且由于OpenAI和其他LLM公司的工作它们变得更加安全和更加协调。
因为指令调的 LLM已经被训练成有益、诚实和无害的所以与基础LLMs相比它们更不可能输出有问题的文本如有害输出。许多实际使用场景已经转向指令调的LLMs。您在互联网上找到的一些最佳实践可能更适用于基础LLMs但对于今天的大多数实际应用我们建议将注意力集中在指令调的LLMs上这些LLMs更容易使用而且由于OpenAI和其他LLM公司的工作它们变得更加安全和更加协调。
因此,本课程将重点介绍针对指令调 LLM 的最佳实践,这是我们建议您用于大多数应用程序的。在继续之前,我想感谢 OpenAI 和 DeepLearning.ai 团队为 Izzy 和我所提供的材料作出的贡献。我非常感激 OpenAI 的 Andrew Main、Joe Palermo、Boris Power、Ted Sanders 和 Lillian Weng他们参与了我们的头脑风暴材料的制定和审核为这个短期课程编制了课程大纲。我也感激 Deep Learning 方面的 Geoff Ladwig、Eddy Shyu 和 Tommy Nelson 的工作。
因此,本课程将重点介绍针对指令调 LLM 的最佳实践,我们建议您将其用于大多数使用场景。在继续之前,我想感谢 OpenAI 和 DeepLearning.ai 团队为 Isa 和我所提供的材料作出的贡献。我非常感激 OpenAI 的 Andrew Main、Joe Palermo、Boris Power、Ted Sanders 和 Lillian Weng他们参与了我们的头脑风暴材料的制定和审核为这个短期课程编制了课程大纲。我也感激 Deep Learning 方面的 Geoff Ladwig、Eddy Shyu 和 Tommy Nelson 的工作。
当您使用指令调 LLM 时,类似于考虑向另一个人提供指令假设它是一个聪明但不知道您任务的具体细节的人。当 LLM 无法正常工作时,有时是因为指令不够清晰。例如,如果您“请为我写一些关于阿兰·图灵的东西”,清楚表明您希望文本专注于他的科学工作、个人生活、历史角色或其他方面可能会更有帮助。更多的,您还可以指定文本采取像专业记者写作的语调,或者更像是您向朋友写的随笔。
当您使用指令调 LLM 时,可以类似于向另一个人提供指令假设他很聪明但不知道您任务的具体细节)。因此,当 LLM 无法正常工作时,有时是因为指令不够清晰。例如,如果您想问“请为我写一些关于阿兰·图灵的东西”,在此基础上清楚表明您希望文本专注于他的科学工作、个人生活、历史角色或其他方面可能会更有帮助。另外您还可以指定回答的语调来更加满足您的需求,可选如专业记者写作,或者向朋友写的随笔
当然,如果你想象一下让一位新毕业的大学生为你完成这个任务,你甚至可以提前指定他们应该阅读哪些文本片段来写关于 Alan Turing的文本那么这能够帮助这位新毕业的大学生更好地成功完成这项任务。下一章你会看到如何让提示清晰明确,创建提示的一个重要原则,你还会从提示的第二个原则中学到给LLM时间去思考。
如果你将LLM视为一名新毕业的大学生,要求他完成这个任务,你甚至可以提前指定他们应该阅读哪些文本片段来写关于 Alan Turing的文本那么这能够帮助这位新毕业的大学生更好地完成这项任务。下一章你会看到提示词创建的两个原则,一是清晰明确,二是给LLM时间去思考。

View File

@ -1,15 +1,17 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 第二章 编写 Prompt 的原则\n",
"\n",
" 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,你将练习基于这两个原则来编写效的 Prompt从而便捷而有效地使用 LLM。"
" 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,你可以练习编写效的 Prompt从而便捷而有效地使用 LLM。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -17,6 +19,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -24,6 +27,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -71,10 +75,11 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"我们将在后续课程中深入探究 OpenAI 提供的 ChatCompletion API 的使用方法,在此处,我们先将它封装成一个函数,你无需知道其内部机理,仅需知道调用该函数输入 Prompt 其将会给出对应的 Completion 即可。"
"整个课程将以 gpt-3.5-turbo 模型为例。我们将在后续课程中深入探究 OpenAI 提供的 [Chat Completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 的使用方法,在此处,我们先将它封装成一个函数,你无需知道其内部机理,仅需知道调用该函数输入 Prompt 其将会给出对应的 Completion 即可。"
]
},
{
@ -86,7 +91,7 @@
"# 一个封装 OpenAI 接口的函数,参数为 Prompt返回对应结果\n",
"def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n",
" '''\n",
" prompt: 对应的提示\n",
" prompt: 对应的提示\n",
" model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4\n",
" '''\n",
" messages = [{\"role\": \"user\", \"content\": prompt}]\n",
@ -100,6 +105,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -107,38 +113,32 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### 原则一:编写清晰、具体的指令\n",
"\n",
"你应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并减少你得到无关或不正确响应的可能。编写清晰的指令不意味着简短的指令,因为在许多情况下,更长的提示实际上更清晰且提供了更多上下文,这实际上可能导致更详细更相关的输出。"
"你应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低你得到无关或不正确响应的可能。清晰的指令不意味着必须简短,因为在许多情况下,更长的提示实际上更清晰且提供了更多上下文,也就可能产生更详细更相关的输出。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略一:使用分隔符清晰地表示输入的不同部分**,分隔符可以是:```\"\"<>\\<tag><\\tag>等\n",
"**策略一:使用分隔符清晰地表示输入的不同部分**,分隔符可以是:```\"\"<>\\<tag> \\</tag>, : 等\n",
"\n",
"你可以使用任何明显的标点符号将特定的文本部分与提示的其余部分分开。这可以是任何可以使模型明确知道这是一个单独部分的标记。使用分隔符是一种可以避免提示注入的有用技术。提示注入是指如果用户将某些输入添加到提示中,则可能会向模型提供与您想要执行的操作相冲突的指令,从而使其遵循冲突的指令而不是执行您想要的操作。即,输入里面可能包含其他指令,会覆盖掉你的指令。对此,使用分隔符是一个不错的策略。\n",
"你可以使用任何明显的标点符号将特定的文本部分与提示的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示注入(Prompt injection)。提示注入是指如果允许用户将某些输入添加到(开发者预定义的)提示中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使LLM遵循用户输入的指令而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉你的指令。对此,使用分隔符是一个不错的策略。\n",
"\n",
"以下是一个例子,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符\n"
"以下例子,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"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.\n"
]
}
],
"outputs": [],
"source": [
"# 中文版见下一个 cell\n",
"text = f\"\"\"\n",
@ -163,24 +163,24 @@
]
},
{
"cell_type": "code",
"execution_count": 6,
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。\n"
]
}
],
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"text = f\"\"\"\n",
"你应该提供尽可能清晰、具体的指示,以表达你希望模型执行的任务。\\\n",
"这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\\\n",
"不要将写清晰的提示与写简短的提示混淆。\\\n",
"在许多情况下,更长的提示可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n",
"不要将写清晰的提示与写简短的提示混淆。\\\n",
"在许多情况下,更长的提示可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n",
"\"\"\"\n",
"# 需要总结的文本内容\n",
"prompt = f\"\"\"\n",
@ -193,19 +193,27 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
" "
"提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略二:要求一个结构化的输出**,可以是 Json、HTML 等格式\n",
"**策略二:寻求结构化的输出**,可以是 Json、HTML 等格式\n",
"\n",
"第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,你可以在 Python 中将其读入字典或列表中。\n",
"第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,你可以在 Python 中将其读入字典或列表中。\n",
"\n",
"在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"
]
@ -297,6 +305,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -304,12 +313,13 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略三:要求模型检查是否满足条件**\n",
"\n",
"如果任务做出的假设不一定满足,我们可以告诉模型先检查这些假设,如果不满足,指示并停止执行。你还可以考虑潜在的边缘情况及模型应该如何处理它们,以避免意外的错误或结果。\n",
"如果任务包含不一定满足的假设,我们可以告诉模型先检查这些假设,如果不满足,则指出并停止执行后续的完整流程。你还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n",
"\n",
"在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答未提供步骤。"
]
@ -433,7 +443,7 @@
}
],
"source": [
"# 有步骤的文本\n",
"# 满足条件的输入text中提供了步骤\n",
"text_1 = f\"\"\"\n",
"泡一杯茶很容易。首先,需要把水烧开。\\\n",
"在等待期间,拿一个杯子并把茶包放进去。\\\n",
@ -474,7 +484,7 @@
}
],
"source": [
"# 无步骤的文本\n",
"# 不满足条件的输入text中未提供步骤\n",
"text_2 = f\"\"\"\n",
"今天阳光明媚,鸟儿在歌唱。\\\n",
"这是一个去公园散步的美好日子。\\\n",
@ -500,6 +510,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -507,14 +518,15 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略四:提供少量示例**\n",
"**策略四:提供少量示例**少样本提示词Few-shot prompting\n",
"\n",
"即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n",
"\n",
"例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和一个祖父之间的对话的例子。孩子说,“教我耐心”,祖父用这些隐喻回答。因此,由于我们已经告诉模型要以一致的语气回答,现在我们说“教我韧性”,由于模型已经有了这个少样本示例,它将以类似的语气回答下一个任务。"
"例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“教我何为耐心”,祖父用下述风格的隐喻回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例(few-shot example),它将以类似的语气回答下一个任务。"
]
},
{
@ -575,6 +587,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -584,6 +597,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -593,6 +607,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -700,6 +715,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -787,6 +803,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -794,6 +811,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -883,6 +901,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -1042,6 +1061,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -1049,6 +1069,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -1121,6 +1142,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -1128,10 +1150,12 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**说明:在本教程中,我们使用 \\ 来使文本适应屏幕大小以提高阅读体验GPT 并不受 \\ 的影响,但在你调用其他大模型时,需额外考虑 \\ 是否会影响模型性能**"
"**关于反斜杠使用的说明:**\n",
"在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符\"\\n\"。GPT-3 并不受换行符newline characters的影响但在你调用其他大模型时需额外考虑换行符是否会影响模型性能"
]
}
],