Merge pull request #43 from YixinZ-NUS/dev3

Prompt Engineering 前四章初步校正
This commit is contained in:
Logan Zou
2023-07-10 12:19:59 +08:00
committed by GitHub
9 changed files with 595 additions and 1089 deletions

View File

@ -1,21 +1,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 的潜力,也会提供应用上的最佳实践。过程中会涉及大量材料。首先,你会学习到用于软件开发的 Prompt 最佳实践,随后会涉及到几个常用使用例,包括概括、推断、转换与扩展,最后会利用 LLM 构建 chatbot聊天机器人。希望这能激发你的想象力去开拓新应用
随着大型语言模型(LLM的发展,LLM 大致可以分为两种类型,基础LLM和指令微调LLM。基础LLM是基于文本训练数据训练出预测下一个单词能力的模型其通常在互联网和其他来源的大量数据上训练。例如,如果你以“从前有一只独角兽”作为提示基础LLM可能会继续预测“生活在一个与所有独角兽朋友的神奇森林中”。但是,如果你以“法国的首都是什么”为提示则基础LLM可能会根据互联网上的文章将答预测为“法国最大的城市是什么?法国的人口是多少?”,因为互联网上的文章很可能是有关法国国家的问答题目列表。
随着 LLM 的发展,大致可以分为两种类型,后续称为基础 LLM 和指令微调Instruction TunedLLM。基础LLM是基于文本训练数据训练出预测下一个单词能力的模型其通常通过在互联网和其他来源的大量数据上训练,来确定紧接着出现的最可能的词。例如,如果你以“从前,有一只独角兽”作为 Prompt ,基础 LLM 可能会继续预测“她与独角兽朋友共同生活在一片神奇森林中”。但是,如果你以“法国的首都是什么”为 Prompt ,则基础 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 已经被训练成有益、诚实无害的,所以与基础 LLM 相比,它们更不可能输出有问题的文本,如有害输出。许多实际使用场景已经转向指令微调的 LLM 。您在互联网上找到的一些最佳实践可能更适用于基础 LLM ,但对于今天的大多数实际应用,我们建议将注意力集中在指令微调的 LLM 上,这些 LLM 更容易使用,而且由于 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 )的东西”,在此基础上清楚表明您希望文本专注于他的科学工作、个人生活、历史角色或其他方面可能会更有帮助。另外您还可以指定回答的语调, 来更加满足您的需求,可选项包括*专业记者写作*,或者*向朋友写的随笔*等
当然,如果你想象一下让一位新毕业的大学生为你完成这个任务,你甚至可以提前指定他们应该阅读哪些文本片段来写关于 Alan Turing的文本那么这能够帮助这位新毕业的大学生更好地成功完成这项任务。下一章你会看到如何让提示清晰明确,创建提示的一个重要原则,你还会从提示的第二个原则中学到给LLM时间去思考。
如果你将 LLM 视为一名新毕业的大学生,要求他完成这个任务,你甚至可以提前指定他们应该阅读哪些文本片段来写关于 Alan Turing 的文本,这能够帮助这位新毕业的大学生更好地完成这项任务。下一章你会看到提示词创建的两个原则,一是**清晰明确**,二是**给LLM时间去思考**

View File

@ -1,15 +1,37 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 第二章 编写 Prompt 的原则\n",
"\n",
" 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,你将练习基于这两个原则来编写效的 Prompt从而便捷而有效地使用 LLM。"
" 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,您可以练习编写效的 Prompt从而便捷而有效地使用 LLM。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"toc\">\n",
" <ul class=\"toc-item\">\n",
" <li><span><a href=\"#一环境配置\" data-toc-modified-id=\"一、环境配置\">一、环境配置</a></span></li>\n",
" <li>\n",
" <span><a href=\"#二两个基本原则\" data-toc-modified-id=\"二、两个基本原则\">二、两个基本原则</a></span>\n",
" <ul class=\"toc-item\">\n",
" <li><span><a href=\"#21-原则一编写清晰具体的指令\" data-toc-modified-id=\"2.1 原则一:编写清晰、具体的指令\">2.1 原则一:编写清晰、具体的指令</a></span></li>\n",
" <li><span><a href=\"#22-给模型时间去思考\" data-toc-modified-id=\"2.2 原则二:给模型时间去思考\">2.2 原则二:给模型时间去思考</a></span></li>\n",
" </ul>\n",
" </li>\n",
" <li><span><a href=\"#三局限性\" data-toc-modified-id=\"三、局限性\">三、局限性</a></span>\n",
" </li>\n",
" </ul>\n",
"</div>"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -17,41 +39,24 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"本教程使用 OpenAI 所开放的 ChatGPT API因此需要首先拥有一个 ChatGPT 的 API_KEY也可以直接访问官方网址在线测试然后需要安装 openai 的第三方库"
"本教程使用 OpenAI 所开放的 ChatGPT API因此需要首先拥有一个 ChatGPT 的 API_KEY也可以直接访问官方网址在线测试然后需要安装 OpenAI 的第三方库。为了兼顾简便与兼容性,本教程将介绍在 ```Python 3``` 环境中基于 ```openai.api_key``` 方法的配置。另有基于环境变量的配置方法,详情请参考 [OpenAI 官方文档](https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety)。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"首先需要安装所需第三方库:\n",
"\n",
"openai\n",
"\n",
"首先需要安装 OpenAI 库:\n",
"```bash\n",
"pip install openai\n",
"```\n",
"\n",
"dotenv:\n",
"\n",
"```bash\n",
"pip install -U python-dotenv\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"# 将自己的 API-KEY 导入系统环境变量\n",
"!export OPENAI_API_KEY='api-key'"
]
},
{
"cell_type": "code",
"execution_count": 2,
@ -59,22 +64,24 @@
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"from dotenv import load_dotenv, find_dotenv\n",
"# 导入第三方库\n",
"\n",
"_ = load_dotenv(find_dotenv())\n",
"# 读取系统中的环境变量\n",
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY\n",
"\n",
"openai.api_key = os.getenv('OPENAI_API_KEY')\n",
"# 设置 API_KEY"
"# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。\n",
"# import openai\n",
"# import os\n",
"# OPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")\n",
"# openai.api_key = OPENAI_API_KEY\n"
]
},
{
"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 +93,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 +107,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -107,38 +115,34 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### 原则一:编写清晰、具体的指令\n",
"### 2.1 原则一:编写清晰、具体的指令\n",
"\n",
"应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并减少你得到无关或不正确响应的可能。编写清晰的指令不意味着简短的指令,因为在许多情况下,更长的提示实际上更清晰且提供了更多上下文,这实际上可能导致更详细更相关的输出。"
"应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰且提供了更多上下文,也就可能产生更详细更相关的输出。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略一:使用分隔符清晰地表示输入的不同部分**,分隔符可以是:```\"\"<>\\<tag><\\tag>等\n",
"**2.1.1 使用分隔符清晰地表示输入的不同部分**\n",
"\n",
"你可以使用任何明显的标点符号将特定的文本部分与提示的其余部分分开。这可以是任何可以使模型明确知道这是一个单独部分的标记。使用分隔符是一种可以避免提示注入的有用技术。提示注入是指如果用户将某些输入添加到提示中,则可能会向模型提供与您想要执行的操作相冲突的指令,从而使其遵循冲突的指令而不是执行您想要的操作。即,输入里面可能包含其他指令,会覆盖掉你的指令。对此,使用分隔符是一个不错的策略。\n",
"分隔符可以是:```\"\"<>:\\<tag> \\</tag>等。\n",
"\n",
"以下是一个例子,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符\n"
"您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n",
"\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 +167,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",
"# 需要总结的文本内容\n",
"prompt = f\"\"\"\n",
@ -193,19 +197,24 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
" "
"\n",
"提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略二:要求一个结构化的输出**,可以是 Json、HTML 等格式\n",
"**2.1.2 寻求结构化的输出**\n",
"\n",
"第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,你可以在 Python 中将其读入字典或列表中。。\n",
"输出可以是 Json、HTML 等格式。\n",
"\n",
"第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n",
"\n",
"在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"
]
@ -299,19 +308,18 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略三:要求模型检查是否满足条件**\n",
"**2.1.3 要求模型检查是否满足条件**\n",
"\n",
"如果任务做出的假设不一定满足,我们可以告诉模型先检查这些假设,如果不满足,指示并停止执行。你还可以考虑潜在的边缘情况及模型应该如何处理它们,以避免意外的错误或结果。\n",
"如果任务包含不一定满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n",
"\n",
"在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答未提供步骤。"
"在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答未提供步骤。"
]
},
{
@ -433,14 +441,14 @@
}
],
"source": [
"# 有步骤的文本\n",
"# 满足条件的输入text中提供了步骤\n",
"text_1 = f\"\"\"\n",
"泡一杯茶很容易。首先,需要把水烧开。\\\n",
"在等待期间,拿一个杯子并把茶包放进去。\\\n",
"一旦水足够热,就把它倒在茶包上。\\\n",
"等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n",
"如果愿意,可以加一些糖或牛奶调味。\\\n",
"就这样,可以享受一杯美味的茶了。\n",
"如果愿意,可以加一些糖或牛奶调味。\\\n",
"就这样,可以享受一杯美味的茶了。\n",
"\"\"\"\n",
"prompt = f\"\"\"\n",
"您将获得由三个引号括起来的文本。\\\n",
@ -474,7 +482,7 @@
}
],
"source": [
"# 无步骤的文本\n",
"# 不满足条件的输入text中未提供预期指令\n",
"text_2 = f\"\"\"\n",
"今天阳光明媚,鸟儿在歌唱。\\\n",
"这是一个去公园散步的美好日子。\\\n",
@ -502,19 +510,18 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略四:提供少量示例**\n",
"**2.1.4 提供少量示例**少样本提示词Few-shot prompting\n",
"\n",
"即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n",
"\n",
"例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和一个祖父之间的对话的例子。孩子说,“教我耐心”,祖父用这些隐喻回答。因此,由于我们已经告诉模型要以一致的语气回答,现在我们说“教我韧性”,由于模型已经有了这个少样本示例,它将以类似的语气回答下一个任务。"
"例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“教我何为耐心”,祖父用下述风格的隐喻回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。"
]
},
{
@ -562,7 +569,7 @@
],
"source": [
"prompt = f\"\"\"\n",
"的任务是以一致的风格回答问题。\n",
"的任务是以一致的风格回答问题。\n",
"\n",
"<孩子>: 教我耐心。\n",
"\n",
@ -575,28 +582,31 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### 原则二:给模型时间去思考\n",
"### 2.2 给模型时间去思考\n",
"\n",
"如果模型匆忙地得出了错误的结论,您应该尝试重新构思查询,请求模型在提供最终答案之前进行一系列相关推理。换句话说,如果您给模型一个在短时间或用少量文字无法完成的任务,它可能会猜测错误。这种情况对人来说也是一样的。如果您让某人在没有时间计算出答案的情况下完成复杂的数学问题,他们也可能会犯错误。因此,在这些情况下,您可以指示模型花更多时间思考问题,这意味着它在任务上花费更多计算资源。"
"如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理a chain or series of relevant reasoning。换句话说,如果您给模型一个在短时间或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,它在任务上花费更多计算资源。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略一:指定完成任务所需的步骤**\n",
"**2.2.1 指定完成任务所需的步骤**\n",
"\n",
"接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果"
"接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"首先我们描述了杰克和吉尔的故事,并给出一个指令。该指令是执行以下操作首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和名称数。然后我们要用换行符分隔答案。"
"首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和人名个数。要求输出以换行符分隔。"
]
},
{
@ -700,10 +710,18 @@
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语,因此,我们给出一个更好的 Prompt该 Prompt 指定了输出的格式"
"上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,对应指令第三步的输出为 'Noms:',为Name的法语这种行为难以预测并可能为导出带来困难\n",
"\n",
"因此我们将Prompt加以改进该 Prompt 前半部分不变,同时**确切指定了输出的格式**。"
]
},
{
@ -787,6 +805,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -794,14 +813,15 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**策略二:指导模型在下结论之前找出一个自己的解法**\n",
"**2.2.2 指导模型在下结论之前找出一个自己的解法**\n",
"\n",
"有时候,在明确指导模型在做决策之前要思考解决方案时,我们会得到更好的结果。\n",
"明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n",
"\n",
"接下来我们会给出一个问题和一学生的解答,要求模型判断解答是否正确"
"接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确"
]
},
{
@ -883,14 +903,20 @@
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"但是注意,学生的解决方案实际上是错误的。\n",
"但是注意,学生的解决方案实际上是错误的。*维护费用项100x应为10x总费用450x应为360x*\n",
"\n",
"我们可以通过指导模型先自行找出一个解法来解决这个问题。\n",
"\n",
"在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"
"在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"
]
},
{
@ -1008,7 +1034,8 @@
"步骤:\n",
"\n",
" 首先,自己解决问题。\n",
" 然后将的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。在自己完成问题之前,请勿决定学生的解决方案是否正确。\n",
" 然后将的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。\n",
" 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n",
"\n",
"使用以下格式:\n",
"\n",
@ -1042,6 +1069,12 @@
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -1049,14 +1082,18 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**开发大模型相关应用时请务必铭记:**\n",
"\n",
"\n",
"**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n",
"\n",
"如果模型在训练过程中接触了大量的知识,它并没有完全记住所见的信息,因此它并不很清楚自己知识的边界。这意味着它可能会尝试回答有关晦涩主题的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉。\n",
"虽然模型在训练过程中接触了大量的知识,它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉Hallucination。\n",
"\n",
"例如在如下示例中,我们要求告诉我们 Boie 公司生产的 AeroGlide UltraSlim Smart Toothbrush 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,模型则会一本正经地告诉我们编造的知识。\n",
"如下示例展示了大模型的幻觉。我们要求告诉我们 Boie 公司生产的 *AeroGlide UltraSlim Smart Toothbrush* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,模型一本正经地提供了它编造的知识,而且迷惑性很强。\n",
"\n"
]
},
@ -1123,15 +1160,26 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
"模型会输出看上去非常真实的编造知识,这有时会很危险。因此,请确保使用我们在本节中介绍的一些技巧,以尝试在构建自己的应用程序时避免这种情况。这是模型已知的一个弱点,也是我们正在积极努力解决的问题。在你希望模型根据文本生成答案的情况下,另一种减少幻觉的策略是先要求模型找到文本中的任何相关引用,然后要求它使用这些引用来回答问题,这种追溯源文档的方法通常对减少幻觉非常有帮助。"
]
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**说明:在本教程中,我们使用 \\ 来使文本适应屏幕大小以提高阅读体验GPT 并不受 \\ 的影响,但在你调用其他大模型时,需额外考虑 \\ 是否会影响模型性能**"
"由于很容易以假乱真请读者根据在本系列教程中所学知识在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷截至2023年7月OpenAI也在努力解决该问题。\n",
"\n",
"在您希望模型根据文本生成回答时另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息任何相关引用any relevant quotes然后要求它基于所引用的信息来回答问题这使得我们能根据答案追溯源文档通常对减少幻觉非常有帮助。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**关于反斜杠使用的说明:**\n",
"\n",
"在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符newline characters的影响但在您调用其他大模型时需额外考虑换行符是否会影响模型性能。"
]
}
],

View File

@ -1,23 +1,46 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# 迭代式提示开发\n",
"# 第三章 迭代优化\n",
"\n",
"当使用 LLM 构建应用程序时,我从来没有在第一次尝试就成功使用最终应用程序中所需的 Prompt。但这并不重要只要您有一个好的迭代过程来不断改进您的 Prompt那么就能够得到一个适合任务的 Prompt。我认为在提示方面,第一次成功的几率可能会高一些,但正如上所说,第一个提示是否有效并不重要。最重要的是为您的应用程序找到有效提示的过程。\n",
"当使用 LLM 构建应用程序时,实践层面上很难*第一次尝试*就成功获得适合最终应用的 Prompt。但这并不重要只要您有一个好的迭代过程来不断改进您的 Prompt那么就能够得到一个适合任务的 Prompt。虽然相比训练机器学习模型,在 Prompt 方面一次成功的几率可能会高一些,但正如上所说, Prompt 是否一次完善并不重要。最重要的是**层层迭代**为您的应用程序找到有效 Prompt 的过程。\n",
"\n",
"因此在本章中,我们将以产品说明书中生成营销文案这一示例,展示一些框架,提示思考如何迭代地分析和完善的 Prompt。\n",
"因此在本章中,我们将以产品说明书中生成营销文案例,展示一些流程框架,提示思考如何层层迭代地分析和完善的 Prompt。\n",
"\n",
"如果您之前与我一起上过机器学习课程,您可能见过我使用的一张图表,说明了机器学习开发的流程。通常是先有一个想法,然后再实现:编写代码,获取数据,训练模型,这会给您一个实验结果。然后您可以查看输出结果,进行错误分析,找出它在哪里起作用或不起作用,甚至可以更改您想要解决的问题的确切思路或方法,然后更改实现并运行另一个实验等,反复迭代,获得有效的机器学习模型。在编写 Prompt 以使用 LLM 开发应用程序时,这个过程可能非常相似,您有一个关于要完成的任务的想法,可以尝试编写第一个 Prompt满足上一章说过的两个原则:清晰明确,并且给系统足够的时间思考。然后您可以运行并查看结果。如果第一次效果不好,那么迭代的过程就是找出为什么指令不够清晰或为什么没有给算法足够的时间思考,以便改进想法、改进提示等等,循环多次,直到找到适合您的应用程序的 Prompt。\n"
"在吴恩达Andrew Ng原教程作者的机器学习课程中展示过一张图表,说明了机器学习开发的流程。通常是先有一个想法,然后再用以下流程实现:编写代码,获取数据,训练模型,获得实验结果。然后您可以查看结果,分析误差与错误,找出适用领域,甚至可以更改您对具体问题的具体思路或解决方法。此后再次更改实现并运行另一个实验等,反复迭代,最终获得有效的机器学习模型。在编写基于 LLM 应用程序的 Prompt 时,流程可能非常相似。您产生了关于要完成的任务的想法,可以尝试编写第一个 Prompt ,注意要满足上一章说过的两个原则:**清晰明确,并且给系统足够的时间思考**。然后您可以运行并查看结果。如果第一次效果不好,那么迭代的过程就是找出为什么指令不够清晰或为什么没有给算法足够的时间思考,以便改进想法、改进 Prompt 等等,循环多次,直到找到适合您的应用程序的 Prompt。\n",
"\n",
"很难有适用于世间万物的所谓“最佳 Prompt ”,更好的方法是找到有效的迭代过程,以便您可以快速地找到一个适合您的应用程序的 Prompt 。\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 环境配置\n",
"<div class=\"toc\">\n",
" <ul class=\"toc-item\">\n",
" <li><span><a href=\"#一环境配置\" data-toc-modified-id=\"一、环境配置\">一、环境配置</a></span></li>\n",
" <li>\n",
" <span><a href=\"#二任务从产品说明书生成一份营销产品描述\" data-toc-modified-id=\"二、任务——从产品说明书生成一份营销产品描述\">二、任务——从产品说明书生成一份营销产品描述</a></span>\n",
" <ul class=\"toc-item\">\n",
" <li><span><a href=\"#21-问题一生成文本太长\" data-toc-modified-id=\"2.1 问题一:生成文本太长\">2.1 问题一:生成文本太长</a></span></li>\n",
" <li><span><a href=\"#22-问题二抓错文本细节\" data-toc-modified-id=\"2.2 问题二:抓错文本细节\">2.2 问题二:抓错文本细节</a></span></li>\n",
" <li><span><a href=\"#23-问题三添加表格描述\" data-toc-modified-id=\"2.3 问题三:添加表格描述\">2.3 问题三:添加表格描述</a></span></li>\n",
" </ul>\n",
" </li>\n",
" </ul>\n",
"</div>"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 一、环境配置\n",
"\n",
"同上一章,我们首先需要配置使用 OpenAI API 的环境"
]
@ -29,15 +52,10 @@
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"from dotenv import load_dotenv, find_dotenv\n",
"# 导入第三方库\n",
"\n",
"_ = load_dotenv(find_dotenv())\n",
"# 读取系统中的环境变量\n",
"\n",
"openai.api_key = os.getenv('OPENAI_API_KEY')\n",
"# 设置 API_KEY"
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY\n"
]
},
{
@ -49,7 +67,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",
@ -63,17 +81,19 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 任务——从产品说明书生成一份营销产品描述"
"## 二、任务——从产品说明书生成一份营销产品描述"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"这里有一个椅子的产品说明书,描述说它是一个中世纪灵感家族的一部分,讨论了构造、尺寸、椅子选项、材料等等,产地是意大利。假设您想要使用这份说明书帮助营销团队为在线零售网站撰写营销描述"
"给定一份椅子的资料页。描述说它属于*中世纪灵感*系列,产自意大利,并介绍了材料、构造、尺寸、可选配件等参数。假设您想要使用这份说明书帮助营销团队为电商平台撰写营销描述稿:"
]
},
{
@ -147,7 +167,7 @@
}
],
"source": [
"# 提示:基于说明书生成营销描述\n",
"# Prompt :基于说明书生成营销描述\n",
"prompt = f\"\"\"\n",
"Your task is to help a marketing team create a \n",
"description for a retail website of a product based \n",
@ -238,9 +258,9 @@
}
],
"source": [
"# 提示:基于说明书创建营销描述\n",
"# Prompt :基于说明书创建营销描述\n",
"prompt = f\"\"\"\n",
"的任务是帮助营销团队基于技术说明书创建一个产品的营销描述。\n",
"的任务是帮助营销团队基于技术说明书创建一个产品的营销描述。\n",
"\n",
"根据```标记的技术说明书中提供的信息,编写一个产品描述。\n",
"\n",
@ -251,16 +271,15 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 问题一:生成文本太长\n",
"## 2.1 问题一:生成文本太长\n",
"\n",
"它似乎很好地写了一个描述,介绍了一个惊人的中世纪灵感办公椅,很好地完成了要求,即从技术说明书开始编写产品描述。但是当我看到这个时,我会觉得这个太长了。\n",
"它似乎很好地完成了要求,即从技术说明书开始编写产品描述,介绍了一个精致的中世纪风格办公椅。但是当我看到这个时,我会觉得这个太长了。\n",
"\n",
"所以我有了一个想法。我写了一个提示,得到了结果但是我对它不是很满意,因为它太长了所以我澄清我的提示,并说最多使用50个字。\n",
"\n",
"因此,我通过要求它限制生成文本长度来解决这一问题"
"所以在上述过程中,我产生想法后写了一个 Prompt ,并得到了结果但是我对它不是很满意,因为它太长了所以我澄清我的 Prompt ,要求它限制生成文本长度,要求最多使用50个字。\n"
]
},
{
@ -296,10 +315,11 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"取回答并根据空格拆分答案为54个字较好地完成了我的要求"
"取回答并根据空格拆分答案为54个字较好地完成了设计要求"
]
},
{
@ -372,17 +392,24 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
"LLM在遵循非常精确的字数限制方面表现得还可以但并不那么出色。有时它会输出60或65个单词的内容但这还算是合理的。这原因是 LLM 解释文本使用一种叫做分词器的东西,但它们往往在计算字符方面表现一般般。有很多不同的方法来尝试控制你得到的输出的长度。"
]
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 问题二:文本关注在错误的细节上\n",
"LLM在能堪堪胜任严格的字数限制但实现得并不精确。此例中英文输出要求控制在50个词但有时会输出60或65个单词的内容但这也还算合理。原因是 LLM 使用分词器tokenizer解释文本但它们往往在计算字符方面表现一般般。有很多不同的方法来尝试控制您得到的输出的长度如若干句话/词/个汉字/个字母 (characters) 等)。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.2 问题二:抓错文本细节\n",
"\n",
"我们会发现的第二个问题是,这个网站并不是直接向消费者销售,它实际上旨在向家具零售商销售家具,他们会更关心椅子的技术细节和材料。在这种情况下,可以修改这个提示,让它更精确地描述椅子的技术细节。\n",
"我们继续完善这段推广词,会发现的第二个问题是,这个网站并不是直接向消费者销售,它实际上面向的是家具零售商,他们会更关心椅子的技术细节和材料。在这种情况下,可以继续修改这个 Prompt ,让它更精确地描述椅子的技术细节。\n",
"\n",
"解决方法:要求它专注于与目标受众相关的方面。"
]
@ -454,10 +481,18 @@
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"我可能进一步想要在描述的结尾包括产品ID。因此我可以进一步改进这个提示要求在描述的结尾包括在技术说明中的每个7个字符产品ID。"
"可见,通过修改 Prompt ,模型的关注点倾向了具体特征与技术细节。\n",
"\n",
"我可能进一步想要在描述的结尾展示出产品ID。因此我可以进一步改进这个 Prompt 要求在描述的结尾展示出说明书中的7位产品ID。"
]
},
{
@ -533,15 +568,25 @@
"print(response)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 问题三:需要一个表格形式的描述\n",
"\n",
"以上是许多开发人员通常会经历的迭代提示开发的简短示例。我的建议是像上一章中所演示的那样Prompt 应该保持清晰和明确,并在必要时给模型一些思考时间。在这些要求的基础上,通常值得首先尝试编写 Prompt ,看看会发生什么,然后从那里开始迭代地完善 Prompt以逐渐接近所需的结果。因此许多成功的Prompt都是通过这种迭代过程得出的。我将向您展示一个更复杂的提示示例可能会让您对ChatGPT的能力有更深入的了解。\n",
"\n",
"这里我添加了一些额外的说明,要求它抽取信息并组织成表格,并指定表格的列、表名和格式,还要求它将所有内容格式化为可以在网页使用的 HTML。"
"以上是许多开发人员通常会经历的 Prompt 开发的迭代过程简短示例。我的建议是像上一章中所演示的那样Prompt 应该保持清晰和明确,并在必要时给模型一些思考时间。在这些要求的基础上,常见流程是首先尝试编写一版 Prompt ,看看会发生什么,然后继续迭代完善 Prompt以逐渐接近所需的结果。许多成功的 Prompt 都是通过这种迭代过程得出的。我将向您展示一个更复杂的 Prompt 示例,可能会让您对 ChatGPT 的能力有更深入的了解。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.3 问题三:添加表格描述\n",
"继续添加指引,要求提取产品尺寸信息并组织成表格,并指定表格的列、表名和格式;再将所有内容格式化为可以在网页使用的 HTML。"
]
},
{
@ -808,16 +853,19 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
"本章的主要内容是 LLM 在开发应用程序中的迭代式提示开发过程。开发者需要先尝试编写提示然后通过迭代逐步完善它直至得到需要的结果。关键在于拥有一种有效的开发Prompt的过程而不是知道完美的Prompt。对于一些更复杂的应用程序可以对多个样本进行迭代开发提示并进行评估。最后可以在更成熟的应用程序中测试多个Prompt在多个样本上的平均或最差性能。在使用 Jupyter 代码笔记本示例时,请尝试不同的变化并查看结果。"
]
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": []
"source": [
"本章的主要内容是 LLM 在开发应用程序中的迭代式 Prompt 开发过程。开发者需要先尝试编写 Prompt 然后通过迭代逐步完善它直至得到需要的结果。作为一名高效的提示词工程师Prompt Engineer关键在于掌握有效的开发Prompt的过程而不是去寻求得到“完美的”Prompt。对于一些更复杂的应用程序可以对多个样本如数百张说明书进行 Prompt 的迭代开发,并在样本集上进行评估。\n",
"\n",
"最后在更成熟的应用程序中可以观察多个Prompt在多个样本集上的表现测试平均或最差性能。但通常**仅当**应用较成型之后,才推荐您通过这种评估方式,来精益求精。\n",
"\n",
"请使用 Jupyter Notebook动手实践本节给出的示例并尝试不同的变化查看结果。"
]
}
],
"metadata": {

View File

@ -1,37 +1,76 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"id": "b58204ea",
"metadata": {},
"source": [
"# 文本概括 Summarizing"
"# 第四章 文本概括"
]
},
{
"cell_type": "markdown",
"id": "a190d6a1",
"metadata": {},
"source": [
"<div class=\"toc\">\n",
" <ul class=\"toc-item\">\n",
" <li><span><a href=\"#一引言\" data-toc-modified-id=\"一、引言\">一、引言</a></span></li>\n",
" <li>\n",
" <span><a href=\"#二单一文本概括\" data-toc-modified-id=\"二、单一文本概括实验\">二、单一文本概括实验</a></span>\n",
" <ul class=\"toc-item\">\n",
" <li><span><a href=\"#21-限制输出文本长度\" data-toc-modified-id=\"2.1 限制输出文本长度\">2.1 限制输出文本长度</a></span></li> \n",
" <li><span><a href=\"#22-设置关键角度侧重\" data-toc-modified-id=\"2.2 设置关键角度侧重\">2.2 设置关键角度侧重</a></span></li>\n",
" <li><span><a href=\"#23-关键信息提取\" data-toc-modified-id=\"2.3 关键信息提取\">2.3 关键信息提取</a></span></li>\n",
" </ul>\n",
" </li>\n",
" <li><span><a href=\"#三同时概括多条文本\" data-toc-modified-id=\"三、同时概括多条文本\">三、同时概括多条文本</a></span></li>\n",
" </ul>\n",
"</div>"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "b70ad003",
"metadata": {},
"source": [
"## 1 引言"
"## 一、引言"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "12fa9ea4",
"metadata": {},
"source": [
"当今世界上有太多的文本信息,几乎没有人能够拥有足够的时间去阅读所有我们想了解的东西。但令人感到欣喜的是目前LLM在文本概括任务上展现了强大的水准也已经有不少团队将这项功能插入了自己的软件应用中。\n",
"当今世界上文本信息浩如烟海,我们很难拥有足够的时间去阅读所有想了解的东西。但欣喜的是目前LLM在文本概括任务上展现了强大的水准也已经有不少团队将概括功能实现在多种应用中。\n",
"\n",
"本章节将介绍如何使用编程的方式调用API接口来实现“文本概括”功能。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "1de4fd1e",
"metadata": {},
"source": [
"首先我们需要OpenAI包加载API密钥定义getCompletion函数。"
"首先,我们需要引入 OpenAI 包,加载 API 密钥,定义 getCompletion 函数。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1b4bfa7f",
"metadata": {},
"outputs": [],
"source": [
"import openai\n",
"# 导入第三方库\n",
"\n",
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY\n"
]
},
{
@ -41,11 +80,6 @@
"metadata": {},
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"OPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")\n",
"openai.api_key = OPENAI_API_KEY\n",
"\n",
"def get_completion(prompt, model=\"gpt-3.5-turbo\"): \n",
" messages = [{\"role\": \"user\", \"content\": prompt}]\n",
" response = openai.ChatCompletion.create(\n",
@ -57,22 +91,25 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "9cca835b",
"metadata": {},
"source": [
"## 2 单一文本概括Prompt实验"
"## 二、单一文本概括"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "0c1e1b92",
"metadata": {},
"source": [
"这里我们举了个商品评论的例子。对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。"
"以商品评论的总结任务为例:对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "9dc2e2bc",
"metadata": {},
@ -100,6 +137,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "aad5bd2a",
"metadata": {},
@ -123,6 +161,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "662c9cd2",
"metadata": {},
@ -131,6 +170,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "a6d10814",
"metadata": {},
@ -168,6 +208,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "0df0eb90",
"metadata": {},
@ -191,7 +232,7 @@
],
"source": [
"prompt = f\"\"\"\n",
"的任务是从电子商务网站上生成一个产品评论的简短摘要。\n",
"的任务是从电子商务网站上生成一个产品评论的简短摘要。\n",
"\n",
"请对三个反引号之间的评论文本进行概括最多30个词汇。\n",
"\n",
@ -203,14 +244,16 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "e9ab145e",
"metadata": {},
"source": [
"### 2.2 关键角度侧重"
"### 2.2 设置关键角度侧重"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "f84d0123",
"metadata": {},
@ -221,11 +264,12 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "d6f8509a",
"metadata": {},
"source": [
"**侧重于运输**"
"**侧重于快递服务**"
]
},
{
@ -260,6 +304,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "0bd4243a",
"metadata": {},
@ -283,7 +328,7 @@
],
"source": [
"prompt = f\"\"\"\n",
"的任务是从电子商务网站上生成一个产品评论的简短摘要。\n",
"的任务是从电子商务网站上生成一个产品评论的简短摘要。\n",
"\n",
"请对三个反引号之间的评论文本进行概括最多30个词汇并且聚焦在产品运输上。\n",
"\n",
@ -295,6 +340,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "76c97fea",
"metadata": {},
@ -303,6 +349,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "83275907",
"metadata": {},
@ -343,6 +390,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "cf54fac4",
"metadata": {},
@ -366,7 +414,7 @@
],
"source": [
"prompt = f\"\"\"\n",
"的任务是从电子商务网站上生成一个产品评论的简短摘要。\n",
"的任务是从电子商务网站上生成一个产品评论的简短摘要。\n",
"\n",
"请对三个反引号之间的评论文本进行概括最多30个词汇并且聚焦在产品价格和质量上。\n",
"\n",
@ -378,6 +426,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "972dbb1b",
"metadata": {},
@ -386,6 +435,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "b3ed53d2",
"metadata": {},
@ -394,11 +444,12 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "ba6f5c25",
"metadata": {},
"source": [
"在2.2节中虽然我们通过添加关键角度侧重的Prompt使得文本摘要更侧重于某一特定方面但是可以发现结果中也会保留一些其他信息如价格与质量角度的概括中仍保留了“快递提前到货”的信息。有时这些信息是有帮助的,但如果我们只想要提取某一角度的信息并过滤掉其他所有信息则可以要求LLM进行“文本提取(Extract)”而非“文本概括(Summarize)”"
"在2.2节中,虽然我们通过添加关键角度侧重的 Prompt ,使得文本摘要更侧重于某一特定方面,但是可以发现,结果中也会保留一些其他信息,如偏重价格与质量角度的概括中仍保留了“快递提前到货”的信息。如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,则可以要求 LLM 进行“文本提取( Extract )”而非“概括( Summarize )”"
]
},
{
@ -433,6 +484,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "0339b877",
"metadata": {},
@ -456,7 +508,7 @@
],
"source": [
"prompt = f\"\"\"\n",
"的任务是从电子商务网站上的产品评论中提取相关信息。\n",
"的任务是从电子商务网站上的产品评论中提取相关信息。\n",
"\n",
"请从以下三个反引号之间的评论文本中提取产品运输相关的信息最多30个词汇。\n",
"\n",
@ -468,19 +520,21 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "50498a2b",
"metadata": {},
"source": [
"## 3 多条文本概括Prompt实验"
"## 三、同时概括多条文本"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "a291541a",
"metadata": {},
"source": [
"在实际的工作流中,我们往往有许许多多的评论文本,以下展示了一个基于for循环调用“文本概括”工具并依次打印的示例。当然在实际生产中对于上百万甚至上千万的评论文本使用for循环也是不现实的可能需要考虑整合评论、分布式等方法提升运算效率。"
"在实际的工作流中,我们往往有许许多多的评论文本,以下示例将多条用户评价放进列表,并利用 ```for``` 循环使用文本概括Summarize提示词将评价概括至小于 20 词,并按顺序打印。当然,在实际生产中,对于不同规模的评论文本,除了使用 ```for``` 循环以外,还可能需要考虑整合评论、分布式等方法提升运算效率。您可以搭建主控面板,来总结大量用户评论,来方便您或他人快速浏览,还可以点击查看原评论。这样您能高效掌握顾客的所有想法。"
]
},
{
@ -539,16 +593,16 @@
"where the blade locks into place doesnt look as good \\\n",
"as in previous editions from a few years ago, but I \\\n",
"plan to be very gentle with it (example, I crush \\\n",
"very hard items like beans, ice, rice, etc. in the \\ \n",
"very hard items like beans, ice, rice, etc. in the \\\n",
"blender first then pulverize them in the serving size \\\n",
"I want in the blender then switch to the whipping \\\n",
"blade for a finer flour, and use the cross cutting blade \\\n",
"first when making smoothies, then use the flat blade \\\n",
"if I need them finer/less pulpy). Special tip when making \\\n",
"smoothies, finely cut and freeze the fruits and \\\n",
"vegetables (if using spinach-lightly stew soften the \\ \n",
"vegetables (if using spinach-lightly stew soften the \\\n",
"spinach then freeze until ready for use-and if making \\\n",
"sorbet, use a small to medium sized food processor) \\ \n",
"sorbet, use a small to medium sized food processor) \\\n",
"that you plan to use that way you can avoid adding so \\\n",
"much ice if at all-when making your smoothie. \\\n",
"After about a year, the motor was making a funny noise. \\\n",
@ -587,7 +641,7 @@
"source": [
"for i in range(len(reviews)):\n",
" prompt = f\"\"\"\n",
" Your task is to generate a short summary of a product \\ \n",
" Your task is to generate a short summary of a product \\\n",
" review from an ecommerce site. \n",
"\n",
" Summarize the review below, delimited by triple \\\n",
@ -605,7 +659,26 @@
"id": "eb878522",
"metadata": {},
"outputs": [],
"source": []
"source": [
"for i in range(len(reviews)):\n",
" prompt = f\"\"\"\n",
" 你的任务是从电子商务网站上的产品评论中提取相关信息。\n",
"\n",
" 请对三个反引号之间的评论文本进行概括最多20个词汇。\n",
"\n",
" 评论文本: ```{reviews[i]}```\n",
" \"\"\"\n",
" response = get_completion(prompt)\n",
" print(i, response, \"\\n\")\n"
]
},
{
"cell_type": "markdown",
"id": "d757b389",
"metadata": {},
"source": [
"**回答暂缺**"
]
}
],
"metadata": {

View File

@ -27,10 +27,10 @@
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"# 导入第三方库\n",
"\n",
"OPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY2\")\n",
"openai.api_key = OPENAI_API_KEY"
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY"
]
},
{

View File

@ -1,6 +1,7 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"id": "78624add",
"metadata": {},
@ -9,16 +10,18 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "2fac57c2",
"metadata": {},
"source": [
"LLM非常擅长将输入转换成不同的格式例如多语种文本翻译、拼写及语法纠正、语气调整、格式转换等。\n",
"LLM非常擅长将输入转换成不同的格式典型应用包括多语种文本翻译、拼写及语法纠正、语气调整、格式转换等。\n",
"\n",
"本章节将介绍如何使用编程的方式调用API接口来实现“文本转换”功能。"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "f7816496",
"metadata": {},
@ -26,6 +29,20 @@
"首先我们需要OpenAI包加载API密钥定义getCompletion函数。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "acf125be",
"metadata": {},
"outputs": [],
"source": [
"import openai\n",
"# 导入第三方库\n",
"\n",
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
@ -33,12 +50,6 @@
"metadata": {},
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"import time\n",
"OPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY2\")\n",
"openai.api_key = OPENAI_API_KEY\n",
"\n",
"def get_completion(prompt, model=\"gpt-3.5-turbo\", temperature=0): \n",
" messages = [{\"role\": \"user\", \"content\": prompt}]\n",
" response = openai.ChatCompletion.create(\n",
@ -50,6 +61,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "bf3733d4",
"metadata": {},
@ -58,6 +70,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "1b418e32",
"metadata": {},
@ -65,6 +78,21 @@
"**中文转西班牙语**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5b521646",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"Translate the following English text to Spanish: \\ \n",
"```Hi, I would like to order a blender```\n",
"\"\"\"\n",
"response = get_completion(prompt)\n",
"print(response)"
]
},
{
"cell_type": "code",
"execution_count": 2,
@ -91,6 +119,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "e3e922b4",
"metadata": {},
@ -98,6 +127,21 @@
"**识别语种**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "769b6e2e",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"Tell me which language this is: \n",
"```Combien coûte le lampadaire?```\n",
"\"\"\"\n",
"response = get_completion(prompt)\n",
"print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
@ -122,6 +166,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "c1841354",
"metadata": {},
@ -129,6 +174,22 @@
"**多语种翻译**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a53bc53b",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"Translate the following text to French and Spanish\n",
"and English pirate: \\\n",
"```I want to order a basketball```\n",
"\"\"\"\n",
"response = get_completion(prompt)\n",
"print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
@ -156,6 +217,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "68723ba5",
"metadata": {},
@ -163,6 +225,22 @@
"**翻译+正式语气**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a4770dcc",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"Translate the following text to Spanish in both the \\\n",
"formal and informal forms: \n",
"'Would you like to order a pillow?'\n",
"\"\"\"\n",
"response = get_completion(prompt)\n",
"print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
@ -188,6 +266,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "b2dc4c56",
"metadata": {},
@ -196,6 +275,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "54b00aa4",
"metadata": {},
@ -219,6 +299,26 @@
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5cb69e31",
"metadata": {},
"outputs": [],
"source": [
"for issue in user_messages:\n",
" prompt = f\"Tell me what language this is: ```{issue}```\"\n",
" lang = get_completion(prompt)\n",
" print(f\"Original message ({lang}): {issue}\")\n",
"\n",
" prompt = f\"\"\"\n",
" Translate the following text to English \\\n",
" and Korean: ```{issue}```\n",
" \"\"\"\n",
" response = get_completion(prompt)\n",
" print(response, \"\\n\")\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
@ -276,14 +376,16 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "6ab558a2",
"metadata": {},
"source": [
"## 3 语气/风格调整"
"## 3 语气/ 写作风格调整"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "b85ae847",
"metadata": {},
@ -291,6 +393,21 @@
"写作的语气往往会根据受众对象而有所调整。例如,对于工作邮件,我们常常需要使用正式语气与书面用词,而对同龄朋友的微信聊天,可能更多地会使用轻松、口语化的语气。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d62ac977",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"Translate the following from slang to a business letter: \n",
"'Dude, This is Joe, check out this spec on this standing lamp.'\n",
"\"\"\"\n",
"response = get_completion(prompt)\n",
"print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
@ -325,6 +442,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "98df9009",
"metadata": {},
@ -333,6 +451,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "0bf9c074",
"metadata": {},
@ -354,6 +473,21 @@
"]}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7e904f70",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"Translate the following python dictionary from JSON to an HTML \\\n",
"table with column headers and title: {data_json}\n",
"\"\"\"\n",
"response = get_completion(prompt)\n",
"print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
@ -445,6 +579,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "29b7167b",
"metadata": {},
@ -453,13 +588,14 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "22776140",
"metadata": {},
"source": [
"拼写及语法的检查与纠正是一个十分常见的需求,特别是使用非母语语言,例如发表英文论文时,是一件十分重要的事情。\n",
"拼写及语法的检查与纠正是一个十分常见的需求,特别是使用非母语语言,例如,在论坛发帖时,或发表英文论文时,校对是一件十分重要的事情。\n",
"\n",
"以下给了一个例子,有一个句子列表,其中有些句子存在拼写或语法问题,有些则没有,我们循环遍历每个句子,要求模型校对文本,如果正确则输出“未发现错误”,如果错误则输出纠正后的文本。"
"下述例子给定了一个句子列表,其中有些句子存在拼写或语法问题,有些则没有,我们循环遍历每个句子,要求模型校对文本,如果正确则输出“未发现错误”,如果错误则输出纠正后的文本。"
]
},
{
@ -480,6 +616,23 @@
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d48f8d3f",
"metadata": {},
"outputs": [],
"source": [
"for t in text:\n",
" prompt = f\"\"\"Proofread and correct the following text\n",
" and rewrite the corrected version. If you don't find\n",
" and errors, just say \"No errors found\". Don't use \n",
" any punctuation around the text:\n",
" ```{t}```\"\"\"\n",
" response = get_completion(prompt)\n",
" print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
@ -515,11 +668,12 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "538181e0",
"metadata": {},
"source": [
"以下是一个简单的类Grammarly纠错示例输入原始文本,输出纠正后的文本并基于Redlines输出纠错过程。"
"以下是一个简单的语法纠错示例译注与Grammarly功能类似输入文本为一段关于熊猫玩偶的评价,输出纠正后的文本。本例使用的prompt较为简单你也可以进一步要求进行语调的更改。"
]
},
{
@ -541,6 +695,18 @@
"\"\"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8f3b2341",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"proofread and correct this review: ```{text}```\"\n",
"response = get_completion(prompt)\n",
"print(response)\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
@ -562,15 +728,12 @@
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "51de86c3",
"attachments": {},
"cell_type": "markdown",
"id": "2e2d1f6a",
"metadata": {},
"outputs": [],
"source": [
"response = \"\"\"\n",
"I got this for my daughter's birthday because she keeps taking mine from my room. Yes, adults also like pandas too. She takes it everywhere with her, and it's super soft and cute. However, one of the ears is a bit lower than the other, and I don't think that was designed to be asymmetrical. It's also a bit smaller than I expected for the price. I think there might be other options that are bigger for the same price. On the bright side, it arrived a day earlier than expected, so I got to play with it myself before giving it to my daughter.\n",
"\"\"\""
"引入Redlines包详细显示并对比纠错过程"
]
},
{
@ -612,11 +775,13 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "3ee5d487",
"metadata": {},
"source": [
"## 6 一个综合样例:文本翻译+拼写纠正+风格调整+格式转换"
"## 6 综合样例\n",
"下述例子展示了同一段评论用一段prompt同时进行文本翻译+拼写纠正+风格调整+格式转换。"
]
},
{
@ -638,6 +803,53 @@
"\"\"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "83235c7b",
"metadata": {},
"outputs": [],
"source": [
"prompt = f\"\"\"\n",
"proofread and correct this review. Make it more compelling. \n",
"Ensure it follows APA style guide and targets an advanced reader. \n",
"Output in markdown format.\n",
"Text: ```{text}```\n",
"\"\"\"\n",
"# 校对注APA style guide是APA Style Guide是一套用于心理学和相关领域的研究论文写作和格式化的规则。\n",
"# 它包括了文本的缩略版,旨在快速阅读,包括引用、解释和参考列表,\n",
"# 其详细内容可参考https://apastyle.apa.org/about-apa-style\n",
"# 下一单元格内的汉化prompt内容由译者进行了本地化处理仅供参考\n",
"response = get_completion(prompt)\n",
"display(Markdown(response))\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "4bd30c51",
"metadata": {},
"source": [
"\n",
"**Review of Panda Plush Toy**\n",
"\n",
"**Introduction**\n",
"\n",
"I bought this panda plush toy as a birthday gift for my daughter, who loves pandas as much as I do. This toy is very soft and adorable, and my daughter enjoys carrying it around with her everywhere. However, I also noticed some flaws in the toys design and size that made me question its value for money.\n",
"\n",
"**Appearance and Quality**\n",
"\n",
"The toy has a realistic black and white fur pattern and a cute expression on its face. It is made of high-quality material that feels smooth and gentle to the touch. One of the ears is slightly lower than the other, which may be a manufacturing defect or an intentional asymmetry to make it look more natural. The toy is also quite small, measuring about 12 inches in height. I expected it to be bigger for the price I paid, as I have seen other plush toys that are larger and cheaper.\n",
"\n",
"**Delivery and Service**\n",
"\n",
"The toy arrived a day earlier than the estimated delivery date, which was a pleasant surprise. It was well-packaged and in good condition when I received it. The seller also included a thank-you note and a coupon for my next purchase, which I appreciated.\n",
"\n",
"**Conclusion**\n",
"\n",
"Overall, this panda plush toy is a lovely and cuddly gift for any panda lover, especially children. It has a high-quality feel and a charming appearance, but it also has some minor flaws in its design and size that may affect its value. I would recommend this toy to anyone who is looking for a small and cute panda plush, but not to those who want a large and realistic one."
]
},
{
"cell_type": "code",
"execution_count": 24,
@ -687,14 +899,6 @@
"response = get_completion(prompt)\n",
"display(Markdown(response))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3d54f151",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@ -20,16 +20,6 @@
"同以上几章,你需要类似的代码来配置一个可以使用 OpenAI API 的环境"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 将自己的 API-KEY 导入系统环境变量\n",
"!export OPENAI_API_KEY='api-key'"
]
},
{
"cell_type": "code",
"execution_count": 1,
@ -37,15 +27,10 @@
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"from dotenv import load_dotenv, find_dotenv\n",
"# 导入第三方库\n",
"\n",
"_ = load_dotenv(find_dotenv())\n",
"# 读取系统中的环境变量\n",
"\n",
"openai.api_key = os.getenv('OPENAI_API_KEY')\n",
"# 设置 API_KEY"
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY\n"
]
},
{

File diff suppressed because one or more lines are too long

View File

@ -9,9 +9,9 @@
"source": [
"# ChatGPT与ChatGLM对比\n",
"\n",
"&emsp;&emsp;国产大模型有很多比如文心一言、通义千问、星火、MOSS和ChatGLM等等但现在明确可以部署在本地并且开放api的只有MOOS和ChatGLM。MOOS由于需要的GPU显存过大不量化的情况下需要80GB多轮对话还是会爆显存但ChatGLM可以在笔记本电脑部署int4版本只需要6GB显存即可。所以本文采用ChatGLM与ChatGPT做对比看看国产模型的优点和缺点。\n",
"国产大模型有很多比如文心一言、通义千问、星火、MOSS和ChatGLM等等但现在明确可以部署在本地并且开放api的只有MOOS和ChatGLM。MOOS由于需要的GPU显存过大不量化的情况下需要80GB多轮对话还是会爆显存但ChatGLM可以在笔记本电脑部署int4版本只需要6GB显存即可。所以本文采用ChatGLM与ChatGPT做对比看看国产模型的优点和缺点。\n",
"\n",
"&emsp;&emsp;会在选取本教程的各个方面进行对比最后会总结ChatGPT与ChatGLM各自的优缺点。"
"本文会选取本教程的各个方面进行对比最后会总结ChatGPT与ChatGLM各自的优缺点。另外本文也适用于没有 OpenAI api key的读者部署好chatglm-6B之后使用后续介绍的函数也可以学完整个课程。"
]
},
{
@ -118,31 +118,12 @@
"id": "b262731f-870d-4810-8b63-67da58a6a7b8",
"metadata": {},
"source": [
"&emsp;&emsp;本教程使用 OpenAI 所开放的 ChatGPT API因此你需要首先拥有一个 ChatGPT 的 API_KEY也可以直接访问官方网址在线测试然后需要安装 openai 的第三方库\n",
"\n",
"&emsp;&emsp;首先需要安装所需第三方库:\n",
"\n",
"```\n",
" openai\n",
"\n",
"引入 OpenAI 包,加载 API 密钥,定义 getCompletion 函数。\n",
"```bash\n",
" pip install openai\n",
" dotenv:\n",
"\n",
" pip install -U python-dotenv\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b6dbf0cd-8826-4e36-a8fc-357203cd0a34",
"metadata": {},
"outputs": [],
"source": [
"# 将自己的 API-KEY 导入系统环境变量\n",
"!export OPENAI_API_KEY='api-key'"
]
},
{
"cell_type": "code",
"execution_count": null,
@ -151,23 +132,10 @@
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"from dotenv import load_dotenv, find_dotenv\n",
"# 导入第三方库\n",
"\n",
"_ = load_dotenv(find_dotenv())\n",
"# 读取系统中的环境变量\n",
"\n",
"openai.api_key = os.getenv('OPENAI_API_KEY')\n",
"# 设置 API_KEY"
]
},
{
"cell_type": "markdown",
"id": "75927919-bdcd-4534-8b4c-e77acca05eae",
"metadata": {},
"source": [
"封装一个函数"
"openai.api_key = \"sk-...\"\n",
"# 设置 API_KEY, 请替换成您自己的 API_KEY\n"
]
},
{