From bcb1c5c15618f70a6caadd8a41dba3b2e3826ea5 Mon Sep 17 00:00:00 2001 From: nowadays0421 Date: Tue, 18 Jul 2023 11:03:56 +0800 Subject: [PATCH 01/13] Finish PE 2 --- .../2. 提示原则 Guidelines.ipynb | 1239 +---------------- .../do_contents.py | 33 + 2 files changed, 34 insertions(+), 1238 deletions(-) create mode 100644 content/Prompt Engineering for Developer/do_contents.py diff --git a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb index cf339f7..74d0eaf 100644 --- a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb +++ b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb @@ -1,1238 +1 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 第二章 编写 Prompt 的原则\n", - "\n", - " 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,您可以练习编写高效的 Prompt,从而便捷而有效地使用 LLM。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " \n", - "
" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 一、环境配置" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "本教程使用 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": [ - "首先需要安装 OpenAI 库:\n", - "```bash\n", - "pip install openai\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "# 导入第三方库\n", - "\n", - "openai.api_key = \"sk-...\"\n", - "# 设置 API_KEY, 请替换成您自己的 API_KEY\n", - "\n", - "# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。\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": [ - "整个课程将以 gpt-3.5-turbo 模型为例。我们将在后续课程中深入探究 OpenAI 提供的 [Chat Completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 的使用方法,在此处,我们先将它封装成一个函数,您无需知道其内部机理,仅需知道调用该函数,以 Prompt 为输入参数,其将会输出对应的 Completion (回答结果)即可。" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# 一个封装 OpenAI 接口的函数,参数为 Prompt,返回对应结果\n", - "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", - " '''\n", - " prompt: 对应的提示词\n", - " model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4\n", - " '''\n", - " messages = [{\"role\": \"user\", \"content\": prompt}]\n", - " response = openai.ChatCompletion.create(\n", - " model=model,\n", - " messages=messages,\n", - " temperature=0, # 模型输出的温度系数,控制输出的随机程度\n", - " )\n", - " # 调用 OpenAI 的 ChatCompletion 接口\n", - " return response.choices[0].message[\"content\"]\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 二、两个基本原则" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 原则一:编写清晰、具体的指令\n", - "\n", - "您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.1 使用分隔符清晰地表示输入的不同部分**\n", - "\n", - "分隔符可以是:```,\"\",<>,:,\\ \\等。\n", - "\n", - "您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n", - "\n", - "在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# 中文版见下一个 cell\n", - "text = f\"\"\"\n", - "You should express what you want a model to do by \\ \n", - "providing instructions that are as clear and \\ \n", - "specific as you can possibly make them. \\ \n", - "This will guide the model towards the desired output, \\ \n", - "and reduce the chances of receiving irrelevant \\ \n", - "or incorrect responses. Don't confuse writing a \\ \n", - "clear prompt with writing a short prompt. \\ \n", - "In many cases, longer prompts provide more clarity \\ \n", - "and context for the model, which can lead to \\ \n", - "more detailed and relevant outputs.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "Summarize the text delimited by triple backticks \\ \n", - "into a single sentence.\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "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", - "prompt = f\"\"\"\n", - "把用三个反引号括起来的文本总结成一句话。\n", - "```{text}```\n", - "\"\"\"\n", - "# 指令内容,使用 ``` 来分隔指令和待总结的内容\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.2 寻求结构化的输出**\n", - "\n", - "输出可以是 Json、HTML 等格式。\n", - "\n", - "第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n", - "\n", - "在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Lost City of Zorath\",\n", - " \"author\": \"Aria Blackwood\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Last Survivors\",\n", - " \"author\": \"Ethan Stone\",\n", - " \"genre\": \"Science Fiction\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Secret Life of Bees\",\n", - " \"author\": \"Lila Rose\",\n", - " \"genre\": \"Romance\"\n", - " }\n", - "]\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Generate a list of three made-up book titles along \\ \n", - "with their authors and genres. \n", - "Provide them in JSON format with the following keys: \n", - "book_id, title, author, genre.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"books\": [\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Shadow of the Wind\",\n", - " \"author\": \"Carlos Ruiz Zafón\",\n", - " \"genre\": \"Mystery\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Name of the Wind\",\n", - " \"author\": \"Patrick Rothfuss\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Hitchhiker's Guide to the Galaxy\",\n", - " \"author\": \"Douglas Adams\",\n", - " \"genre\": \"Science Fiction\"\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请生成包括书名、作者和类别的三本虚构书籍清单,\\\n", - "并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.3 要求模型检查是否满足条件**\n", - "\n", - "如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n", - "\n", - "在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 1:\n", - "Step 1 - Get some water boiling.\n", - "Step 2 - Grab a cup and put a tea bag in it.\n", - "Step 3 - Once the water is hot enough, pour it over the tea bag.\n", - "Step 4 - Let it sit for a bit so the tea can steep.\n", - "Step 5 - After a few minutes, take out the tea bag.\n", - "Step 6 - Add some sugar or milk to taste.\n", - "Step 7 - Enjoy your delicious cup of tea!\n", - "\n", - "\n" - ] - } - ], - "source": [ - "text_1 = f\"\"\"\n", - "Making a cup of tea is easy! First, you need to get some \\ \n", - "water boiling. While that's happening, \\ \n", - "grab a cup and put a tea bag in it. Once the water is \\ \n", - "hot enough, just pour it over the tea bag. \\ \n", - "Let it sit for a bit so the tea can steep. After a \\ \n", - "few minutes, take out the tea bag. If you \\ \n", - "like, you can add some sugar or milk to taste. \\ \n", - "And that's it! You've got yourself a delicious \\ \n", - "cup of tea to enjoy.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 2:\n", - "No steps provided.\n" - ] - } - ], - "source": [ - "text_2 = f\"\"\"\n", - "The sun is shining brightly today, and the birds are \\\n", - "singing. It's a beautiful day to go for a \\ \n", - "walk in the park. The flowers are blooming, and the \\ \n", - "trees are swaying gently in the breeze. People \\ \n", - "are out and about, enjoying the lovely weather. \\ \n", - "Some are having picnics, while others are playing \\ \n", - "games or simply relaxing on the grass. It's a \\ \n", - "perfect day to spend time outdoors and appreciate the \\ \n", - "beauty of nature.\n", - "\"\"\"\n", - "prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 1 的总结:\n", - "第一步 - 把水烧开。\n", - "第二步 - 拿一个杯子并把茶包放进去。\n", - "第三步 - 把烧开的水倒在茶包上。\n", - "第四步 - 等待几分钟,让茶叶浸泡。\n", - "第五步 - 取出茶包。\n", - "第六步 - 如果你愿意,可以加一些糖或牛奶调味。\n", - "第七步 - 就这样,你可以享受一杯美味的茶了。\n" - ] - } - ], - "source": [ - "# 满足条件的输入(text中提供了步骤)\n", - "text_1 = f\"\"\"\n", - "泡一杯茶很容易。首先,需要把水烧开。\\\n", - "在等待期间,拿一个杯子并把茶包放进去。\\\n", - "一旦水足够热,就把它倒在茶包上。\\\n", - "等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n", - "如果您愿意,可以加一些糖或牛奶调味。\\\n", - "就这样,您可以享受一杯美味的茶了。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 1 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 2 的总结:\n", - "未提供步骤。\n" - ] - } - ], - "source": [ - "# 不满足条件的输入(text中未提供预期指令)\n", - "text_2 = f\"\"\"\n", - "今天阳光明媚,鸟儿在歌唱。\\\n", - "这是一个去公园散步的美好日子。\\\n", - "鲜花盛开,树枝在微风中轻轻摇曳。\\\n", - "人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n", - "这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 2 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.4 提供少量示例**(少样本提示词,Few-shot prompting)\n", - "\n", - "即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n", - "\n", - "例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - ": 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.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to answer in a consistent style.\n", - "\n", - ": Teach me about patience.\n", - "\n", - ": The river that carves the deepest \\ \n", - "valley flows from a modest spring; the \\ \n", - "grandest symphony originates from a single note; \\ \n", - "the most intricate tapestry begins with a solitary thread.\n", - "\n", - ": Teach me about resilience.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。在生活中,我们也需要经历各种挫折和困难,才能锻炼出韧性。记住,不要轻易放弃,坚持下去,你会发现自己变得更加坚强。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "您的任务是以一致的风格回答问题。\n", - "\n", - "<孩子>: 教我耐心。\n", - "\n", - "<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n", - "\n", - "<孩子>: 教我韧性。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 给模型时间去思考\n", - "\n", - "如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.1 指定完成任务所需的步骤**\n", - "\n", - "接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和人名个数。要求输出以换行符分隔。" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for prompt 1:\n", - "Two siblings, Jack and Jill, go on a quest to fetch water from a well on a hilltop, but misfortune strikes and they both tumble down the hill, returning home slightly battered but with their adventurous spirits undimmed.\n", - "\n", - "Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts. \n", - "Noms: Jack, Jill.\n", - "\n", - "{\n", - " \"french_summary\": \"Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "In a charming village, siblings Jack and Jill set out on \\ \n", - "a quest to fetch water from a hilltop \\ \n", - "well. As they climbed, singing joyfully, misfortune \\ \n", - "struck—Jack tripped on a stone and tumbled \\ \n", - "down the hill, with Jill following suit. \\ \n", - "Though slightly battered, the pair returned home to \\ \n", - "comforting embraces. Despite the mishap, \\ \n", - "their adventurous spirits remained undimmed, and they \\ \n", - "continued exploring with delight.\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "Perform the following actions: \n", - "1 - Summarize the following text delimited by triple \\\n", - "backticks with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the following \\\n", - "keys: french_summary, num_names.\n", - "\n", - "Separate your answers with line breaks.\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"Completion for prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "prompt 1:\n", - "1-兄妹在山顶井里打水时发生意外,但仍然保持冒险精神。\n", - "2-Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\n", - "3-Jack, Jill\n", - "4-{\n", - " \"French_summary\": \"Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n", - "他们一边唱着欢乐的歌,一边往上爬,\\\n", - "然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n", - "虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n", - "尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "执行以下操作:\n", - "1-用一句话概括下面用三个反引号括起来的文本。\n", - "2-将摘要翻译成法语。\n", - "3-在法语摘要中列出每个人名。\n", - "4-输出一个 JSON 对象,其中包含以下键:French_summary,num_names。\n", - "\n", - "请用换行符分隔您的答案。\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n", - "\n", - "因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Completion for prompt 2:\n", - "Summary: 兄妹杰克和吉尔在山顶井里打水时发生意外,但他们仍然保持冒险精神继续探索。\n", - "Translation: Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\n", - "Names: Jack, Jill\n", - "Output JSON: {\"french_summary\": \"Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\", \"num_names\": 2}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "Your task is to perform the following actions: \n", - "1 - Summarize the following text delimited by <> with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the \n", - "following keys: french_summary, num_names.\n", - "\n", - "Use the following format:\n", - "Text: \n", - "Summary: \n", - "Translation: \n", - "Names: \n", - "Output JSON: \n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nCompletion for prompt 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "prompt 2:\n", - "摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。\n", - "翻译: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.\n", - "名称:Jack,Jill\n", - "输出 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}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "1-用一句话概括下面用<>括起来的文本。\n", - "2-将摘要翻译成英语。\n", - "3-在英语摘要中列出每个名称。\n", - "4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n", - "\n", - "请使用以下格式:\n", - "文本:<要总结的文本>\n", - "摘要:<摘要>\n", - "翻译:<摘要的翻译>\n", - "名称:<英语摘要中的名称列表>\n", - "输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nprompt 2:\")\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.2 指导模型在下结论之前找出一个自己的解法**\n", - "\n", - "明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n", - "\n", - "接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The student's solution is correct.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Determine if the student's solution is correct or not.\n", - "\n", - "Question:\n", - "I'm building a solar power installation and I need \\\n", - " help working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\ \n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \n", - "as a function of the number of square feet.\n", - "\n", - "Student's Solution:\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "学生的解决方案是正确的。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "判断学生的解决方案是否正确。\n", - "\n", - "问题:\n", - "我正在建造一个太阳能发电站,需要帮助计算财务。\n", - "\n", - " 土地费用为 100美元/平方英尺\n", - " 我可以以 250美元/平方英尺的价格购买太阳能电池板\n", - " 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "设x为发电站的大小,单位为平方英尺。\n", - "费用:\n", - "\n", - " 土地费用:100x\n", - " 太阳能电池板费用:250x\n", - " 维护费用:100,000美元+100x\n", - " 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n", - "\n", - "我们可以通过指导模型先自行找出一个解法来解决这个问题。\n", - "\n", - "在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Let x be the size of the installation in square feet.\n", - "\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 10x\n", - "\n", - "Total cost: 100x + 250x + 100,000 + 10x = 360x + 100,000\n", - "\n", - "Is the student's solution the same as actual solution just calculated:\n", - "No\n", - "\n", - "Student grade:\n", - "Incorrect\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to determine if the student's solution \\\n", - "is correct or not.\n", - "To solve the problem do the following:\n", - "- First, work out your own solution to the problem. \n", - "- Then compare your solution to the student's solution \\ \n", - "and evaluate if the student's solution is correct or not. \n", - "Don't decide if the student's solution is correct until \n", - "you have done the problem yourself.\n", - "\n", - "Use the following format:\n", - "Question:\n", - "```\n", - "question here\n", - "```\n", - "Student's solution:\n", - "```\n", - "student's solution here\n", - "```\n", - "Actual solution:\n", - "```\n", - "steps to work out the solution and your solution here\n", - "```\n", - "Is the student's solution the same as actual solution \\\n", - "just calculated:\n", - "```\n", - "yes or no\n", - "```\n", - "Student grade:\n", - "```\n", - "correct or incorrect\n", - "```\n", - "\n", - "Question:\n", - "```\n", - "I'm building a solar power installation and I need help \\\n", - "working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\\n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \\\n", - "as a function of the number of square feet.\n", - "``` \n", - "Student's solution:\n", - "```\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "```\n", - "Actual solution:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "正确的解决方案和步骤:\n", - " 1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元\n", - " 2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元\n", - " 3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元\n", - " 4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元\n", - "\n", - "学生的解决方案和实际解决方案是否相同:否\n", - "\n", - "学生的成绩:不正确\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n", - "\n", - "步骤:\n", - "\n", - " 首先,自己解决问题。\n", - " 然后将您的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。\n", - " 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n", - "\n", - "使用以下格式:\n", - "\n", - " 问题:问题文本\n", - " 学生的解决方案:学生的解决方案文本\n", - " 实际解决方案和步骤:实际解决方案和步骤文本\n", - " 学生的解决方案和实际解决方案是否相同:是或否\n", - " 学生的成绩:正确或不正确\n", - "\n", - "问题:\n", - "\n", - " 我正在建造一个太阳能发电站,需要帮助计算财务。 \n", - " - 土地费用为每平方英尺100美元\n", - " - 我可以以每平方英尺250美元的价格购买太阳能电池板\n", - " - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "\n", - " 设x为发电站的大小,单位为平方英尺。\n", - " 费用:\n", - " 1. 土地费用:100x\n", - " 2. 太阳能电池板费用:250x\n", - " 3. 维护费用:100,000+100x\n", - " 总费用:100x+250x+100,000+100x=450x+100,000\n", - "\n", - "实际解决方案和步骤:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 三、局限性" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**开发大模型相关应用时请务必铭记:**\n", - "\n", - "\n", - "**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n", - "\n", - "虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n", - "\n", - "如下示例展示了大模型的幻觉。我们要求告诉我们 Boie 公司生产的 *AeroGlide UltraSlim Smart Toothbrush* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The AeroGlide UltraSlim Smart Toothbrush by Boie is a high-tech toothbrush that uses advanced sonic technology to provide a deep and thorough clean. It features a slim and sleek design that makes it easy to hold and maneuver, and it comes with a range of smart features that help you optimize your brushing routine.\n", - "\n", - "One of the key features of the AeroGlide UltraSlim Smart Toothbrush is its advanced sonic technology, which uses high-frequency vibrations to break up plaque and bacteria on your teeth and gums. This technology is highly effective at removing even the toughest stains and buildup, leaving your teeth feeling clean and fresh.\n", - "\n", - "In addition to its sonic technology, the AeroGlide UltraSlim Smart Toothbrush also comes with a range of smart features that help you optimize your brushing routine. These include a built-in timer that ensures you brush for the recommended two minutes, as well as a pressure sensor that alerts you if you're brushing too hard.\n", - "\n", - "Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie is a highly advanced and effective toothbrush that is perfect for anyone looking to take their oral hygiene to the next level. With its advanced sonic technology and smart features, it provides a deep and thorough clean that leaves your teeth feeling fresh and healthy.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款智能牙刷,具有以下特点:\n", - "\n", - "1. 超薄设计:刷头仅有0.8毫米的厚度,可以更容易地进入口腔深处,清洁更彻底。\n", - "\n", - "2. 智能感应:牙刷配备了智能感应技术,可以自动识别刷头的位置和方向,确保每个部位都得到充分的清洁。\n", - "\n", - "3. 高效清洁:牙刷采用了高速振动技术,每分钟可达到40000次,可以有效去除牙菌斑和污渍。\n", - "\n", - "4. 轻松携带:牙刷采用了便携式设计,可以轻松放入口袋或旅行包中,随时随地进行口腔清洁。\n", - "\n", - "5. 环保材料:牙刷采用了环保材料制造,不含有害物质,对环境友好。\n", - "\n", - "总之,Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款高效、智能、环保的牙刷,可以帮助用户轻松保持口腔健康。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "告诉我 Boie 公司生产的 AeroGlide UltraSlim Smart Toothbrush 的相关信息\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n", - "\n", - "在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**关于反斜杠使用的说明:**\n", - "\n", - "在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - }, - "latex_envs": { - "LaTeX_envs_menu_present": true, - "autoclose": false, - "autocomplete": true, - "bibliofile": "biblio.bib", - "cite_by": "apalike", - "current_citInitial": 1, - "eqLabelWithNumbers": true, - "eqNumInitial": 1, - "hotkeys": { - "equation": "Ctrl-E", - "itemize": "Ctrl-I" - }, - "labels_anchors": false, - "latex_user_defs": false, - "report_style_numbering": false, - "user_envs_cfg": false - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells":[{"attachments":{},"cell_type":"markdown","metadata":{},"source":["# 第二章 提示原则 Guidelines\n","\n"," - [一、原则一 编写清晰、具体的指令](#一、原则一-编写清晰、具体的指令)\n"," - [1.1 使用分隔符清晰地表示输入的不同部分](#1.1-使用分隔符清晰地表示输入的不同部分)\n"," - [1.2 寻求结构化的输出](#1.2-寻求结构化的输出)\n"," - [1.3 要求模型检查是否满足条件](#1.3-要求模型检查是否满足条件)\n"," - [1.4 提供少量示例](#1.4-提供少量示例)\n"," - [二、原则二 给模型时间去思考](#二、原则二-给模型时间去思考)\n"," - [2.1 指定完成任务所需的步骤](#2.1-指定完成任务所需的步骤)\n"," - [2.2 指导模型在下结论之前找出一个自己的解法](#2.2-指导模型在下结论之前找出一个自己的解法)\n"," - [三、局限性](#三、局限性)\n"," - [四、英文原版 Prompt](#四、英文原版-Prompt)\n"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。"]},{"cell_type":"markdown","metadata":{},"source":["### 1.1 使用分隔符清晰地表示输入的不同部分"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","分隔符可以是:```,\"\",<>,:,\\ \\等。\n","\n","您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n","\n","在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n"]},{"cell_type":"code","execution_count":11,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["为了获得所需的输出,您应该提供清晰、具体的指示,避免与简短的提示词混淆,并使用更长的提示词来提供更多的清晰度和上下文信息。\n"]}],"source":["text = f\"\"\"\n","您应该提供尽可能清晰、具体的指示,以表达您希望模型执行的任务。\\\n","这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\\\n","不要将写清晰的提示词与写简短的提示词混淆。\\\n","在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n","\"\"\"\n","# 需要总结的文本内容\n","prompt = f\"\"\"\n","把用三个反引号括起来的文本总结成一句话。\n","```{text}```\n","\"\"\"\n","# 指令内容,使用 ``` 来分隔指令和待总结的内容\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["### 1.2 寻求结构化的输出"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","输出可以是 Json、HTML 等格式。\n","\n","第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n","\n","在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"]},{"cell_type":"code","execution_count":15,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"迷失的时光\",\n"," \"author\": \"张三\",\n"," \"genre\": \"科幻\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"幻境之门\",\n"," \"author\": \"李四\",\n"," \"genre\": \"奇幻\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"虚拟现实\",\n"," \"author\": \"王五\",\n"," \"genre\": \"科幻\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","请生成包括书名、作者和类别的三本虚构的、非真实存在的中文书籍清单,\\\n","并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.3 要求模型检查是否满足条件"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n","\n","在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。"]},{"cell_type":"code","execution_count":16,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 1 的总结:\n","第一步 - 把水烧开。\n","第二步 - 拿一个杯子并把茶包放进去。\n","第三步 - 把烧开的水倒在茶包上。\n","第四步 - 等待几分钟,让茶叶浸泡。\n","第五步 - 取出茶包。\n","第六步 - 如果需要,加入糖或牛奶调味。\n","第七步 - 就这样,您可以享受一杯美味的茶了。\n"]}],"source":["# 满足条件的输入(text中提供了步骤)\n","text_1 = f\"\"\"\n","泡一杯茶很容易。首先,需要把水烧开。\\\n","在等待期间,拿一个杯子并把茶包放进去。\\\n","一旦水足够热,就把它倒在茶包上。\\\n","等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n","如果您愿意,可以加一些糖或牛奶调味。\\\n","就这样,您可以享受一杯美味的茶了。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 1 的总结:\")\n","print(response)"]},{"cell_type":"code","execution_count":17,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 2 的总结:\n","未提供步骤。\n"]}],"source":["# 不满足条件的输入(text中未提供预期指令)\n","text_2 = f\"\"\"\n","今天阳光明媚,鸟儿在歌唱。\\\n","这是一个去公园散步的美好日子。\\\n","鲜花盛开,树枝在微风中轻轻摇曳。\\\n","人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n","这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 2 的总结:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.4 提供少量示例"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n","\n","例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。"]},{"cell_type":"code","execution_count":22,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["<祖父母>: 韧性是一种坚持不懈的品质,就像一棵顽强的树在风雨中屹立不倒。它是面对困难和挑战时不屈不挠的精神,能够适应变化和克服逆境。韧性是一种内在的力量,让我们能够坚持追求目标,即使面临困难和挫折也能坚持不懈地努力。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是以一致的风格回答问题。\n","\n","<孩子>: 请教我何为耐心。\n","\n","<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n","\n","<孩子>: 请教我何为韧性。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 二、原则二 给模型时间去思考\n","\n","如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。"]},{"cell_type":"markdown","metadata":{},"source":["### 2.1 指定完成任务所需的步骤"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。"]},{"cell_type":"code","execution_count":28,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["prompt 1:\n","1-两个兄妹在山上打水时发生意外,但最终平安回家。\n","2-In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\n","3-Jack, Jill\n","4-{\"english_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\", \"num_names\": 2}\n"]}],"source":["text = f\"\"\"\n","在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n","他们一边唱着欢乐的歌,一边往上爬,\\\n","然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n","虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n","尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","执行以下操作:\n","1-用一句话概括下面用三个反引号括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个人名。\n","4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。\n","\n","请用换行符分隔您的答案。\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"prompt 1:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,要求从英语翻译到法语,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n","\n","因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","prompt 2:\n","Summary: 在一个迷人的村庄里,兄妹杰克和吉尔在山顶井里打水时发生了意外,但他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\n","Translation: In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\n","\n","Names: Jack, Jill\n","\n","JSON Output: {\"English_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\", \"num_names\": 2}\n"]}],"source":["prompt_2 = f\"\"\"\n","1-用一句话概括下面用<>括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个名称。\n","4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n","\n","请使用以下格式:\n","文本:<要总结的文本>\n","摘要:<摘要>\n","翻译:<摘要的翻译>\n","名称:<英语摘要中的名称列表>\n","输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nprompt 2:\")\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":[" "]},{"cell_type":"markdown","metadata":{},"source":["### 2.2 指导模型在下结论之前找出一个自己的解法"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n","\n","接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:"]},{"cell_type":"code","execution_count":30,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["学生的解决方案是正确的。他正确地计算了土地费用、太阳能电池板费用和维护费用,并将它们相加得到了总费用。\n"]}],"source":["prompt = f\"\"\"\n","判断学生的解决方案是否正确。\n","\n","问题:\n","我正在建造一个太阳能发电站,需要帮助计算财务。\n","\n"," 土地费用为 100美元/平方英尺\n"," 我可以以 250美元/平方英尺的价格购买太阳能电池板\n"," 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","设x为发电站的大小,单位为平方英尺。\n","费用:\n","\n"," 土地费用:100x\n"," 太阳能电池板费用:250x\n"," 维护费用:100,000美元+100x\n"," 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n","\n","我们可以通过指导模型先自行找出一个解法来解决这个问题。\n","\n","在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"]},{"cell_type":"code","execution_count":40,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["实际解决方案和步骤:\n","\n"," 1. 土地费用:每平方英尺100美元,所以总费用为100x美元。\n"," 2. 太阳能电池板费用:每平方英尺250美元,所以总费用为250x美元。\n"," 3. 维护费用:固定费用为10万美元,额外费用为每平方英尺10美元,所以总费用为10万美元+10x美元。\n"," 4. 总费用:将上述三项费用相加,得到总费用为100x美元+250x美元+10万美元+10x美元=360x+10万美元。\n","\n","学生计算的总费用:450x+10万美元\n","实际计算的总费用:360x+10万美元\n","学生计算的费用和实际计算的费用是否相同:否\n","学生的解决方案和实际解决方案是否相同:否\n","学生的成绩:不正确\n"]}],"source":["prompt = f\"\"\"\n","请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n","\n","步骤:\n","\n"," 首先,自己解决问题。\n"," 然后将您的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。\n"," 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n","\n","使用以下格式:\n","\n"," 问题:问题文本\n"," 学生的解决方案:学生的解决方案文本\n"," 实际解决方案和步骤:实际解决方案和步骤文本\n"," 学生计算的总费用:学生计算得到的总费用\n"," 实际计算的总费用:实际计算出的总费用\n"," 学生计算的费用和实际计算的费用是否相同:是或否\n"," 学生的解决方案和实际解决方案是否相同:是或否\n"," 学生的成绩:正确或不正确\n","\n","问题:\n","\n"," 我正在建造一个太阳能发电站,需要帮助计算财务。 \n"," - 土地费用为每平方英尺100美元\n"," - 我可以以每平方英尺250美元的价格购买太阳能电池板\n"," - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元;\n","\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","\n"," 设x为发电站的大小,单位为平方英尺。\n"," 费用:\n"," 1. 土地费用:100x美元\n"," 2. 太阳能电池板费用:250x美元\n"," 3. 维护费用:100,000+100x=10万美元+10x美元\n"," 总费用:100x美元+250x美元+10万美元+100x美元=450x+10万美元\n","\n","实际解决方案和步骤:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 三、局限性"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**开发大模型相关应用时请务必铭记:**\n","\n","\n","**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n","\n","虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n","\n","如下示例展示了大模型的幻觉。我们要求告诉我们华为公司生产的 *GT Watch 运动手表* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n","\n"]},{"cell_type":"code","execution_count":44,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["华为公司生产的GT Watch运动手表是一款智能手表,具有多种功能和特点。以下是相关信息:\n","\n","1. 设计和外观:GT Watch采用圆形表盘设计,具有精致的外观和高质量的材料制造。它有多种颜色和表带选择,可以根据个人喜好进行定制。\n","\n","2. 显示屏:GT Watch配备了1.39英寸的AMOLED显示屏,具有高清分辨率和良好的可视性。用户可以通过触摸屏幕进行操作和导航。\n","\n","3. 运动追踪:GT Watch具有全天候的运动追踪功能,可以监测用户的步数、跑步距离、卡路里消耗和心率等数据。它还支持多种运动模式,如跑步、骑行、游泳等。\n","\n","4. 健康监测:GT Watch可以监测用户的心率、血氧饱和度和睡眠质量等健康指标。它还提供健康建议和提醒,帮助用户保持良好的健康状态。\n","\n","5. 通知和连接:GT Watch可以与用户的手机进行连接,通过蓝牙技术实现通知推送和电话提醒。用户可以在手表上查看短信、电话和社交媒体通知,无需拿出手机。\n","\n","6. 长续航时间:GT Watch具有较长的续航时间,一次充电可以使用数天。它还支持快速充电技术,可以在短时间内充满电。\n","\n","7. 其他功能:GT Watch还具有其他功能,如天气预报、闹钟、计时器、计步器等。它还支持NFC支付和音乐控制等便利功能。\n","\n","总体而言,华为GT Watch是一款功能强大、外观精致的智能运动手表,适合那些注重健康和运动的用户使用。\n"]}],"source":["prompt = f\"\"\"\n","告诉我华为公司生产的GT Watch运动手表的相关信息\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n","\n","在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**关于反斜杠使用的说明:**\n","\n","在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。"]},{"cell_type":"markdown","metadata":{},"source":["## 四、英文原版 Prompt"]},{"cell_type":"markdown","metadata":{},"source":["**1.1 使用分隔符清晰地表示输入的不同部分**"]},{"cell_type":"code","execution_count":45,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To guide a model towards the desired output and reduce irrelevant or incorrect responses, it is important to provide clear and specific instructions, which can be achieved through longer prompts that offer more clarity and context.\n"]}],"source":["text = f\"\"\"\n","You should express what you want a model to do by \\ \n","providing instructions that are as clear and \\ \n","specific as you can possibly make them. \\ \n","This will guide the model towards the desired output, \\ \n","and reduce the chances of receiving irrelevant \\ \n","or incorrect responses. Don't confuse writing a \\ \n","clear prompt with writing a short prompt. \\ \n","In many cases, longer prompts provide more clarity \\ \n","and context for the model, which can lead to \\ \n","more detailed and relevant outputs.\n","\"\"\"\n","prompt = f\"\"\"\n","Summarize the text delimited by triple backticks \\ \n","into a single sentence.\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.2**寻求结构化的输出"]},{"cell_type":"code","execution_count":46,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"The Enigma of Elysium\",\n"," \"author\": \"Evelyn Sinclair\",\n"," \"genre\": \"Mystery\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"Whispers in the Wind\",\n"," \"author\": \"Nathaniel Blackwood\",\n"," \"genre\": \"Fantasy\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"Echoes of the Past\",\n"," \"author\": \"Amelia Hart\",\n"," \"genre\": \"Romance\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","Generate a list of three made-up book titles along \\ \n","with their authors and genres. \n","Provide them in JSON format with the following keys: \n","book_id, title, author, genre.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":["**1.3 要求模型检查是否满足条件**"]},{"cell_type":"code","execution_count":56,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 1:\n","Step 1 - Get some water boiling.\n","Step 2 - Grab a cup and put a tea bag in it.\n","Step 3 - Once the water is hot enough, pour it over the tea bag.\n","Step 4 - Let it sit for a bit so the tea can steep.\n","Step 5 - After a few minutes, take out the tea bag.\n","Step 6 - If you like, add some sugar or milk to taste.\n","Step 7 - Enjoy your delicious cup of tea.\n"]}],"source":["text_1 = f\"\"\"\n","Making a cup of tea is easy! First, you need to get some \\ \n","water boiling. While that's happening, \\ \n","grab a cup and put a tea bag in it. Once the water is \\ \n","hot enough, just pour it over the tea bag. \\ \n","Let it sit for a bit so the tea can steep. After a \\ \n","few minutes, take out the tea bag. If you \\ \n","like, you can add some sugar or milk to taste. \\ \n","And that's it! You've got yourself a delicious \\ \n","cup of tea to enjoy.\n","\"\"\"\n","prompt = f\"\"\"\n","You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":48,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 2:\n","No steps provided.\n"]}],"source":["text_2 = f\"\"\"\n","The sun is shining brightly today, and the birds are \\\n","singing. It's a beautiful day to go for a \\ \n","walk in the park. The flowers are blooming, and the \\ \n","trees are swaying gently in the breeze. People \\ \n","are out and about, enjoying the lovely weather. \\ \n","Some are having picnics, while others are playing \\ \n","games or simply relaxing on the grass. It's a \\ \n","perfect day to spend time outdoors and appreciate the \\ \n","beauty of nature.\n","\"\"\"\n","prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.4 提供少量示例**(少样本提示词,Few-shot prompting)"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":[": Resilience is like a mighty oak tree that withstands the strongest storms, bending but never breaking. It is the unwavering determination to rise again after every fall, and the ability to find strength in the face of adversity. Just as a diamond is formed under immense pressure, resilience is forged through challenges and hardships, making us stronger and more resilient in the process.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to answer in a consistent style.\n","\n",": Teach me about patience.\n","\n",": The river that carves the deepest \\ \n","valley flows from a modest spring; the \\ \n","grandest symphony originates from a single note; \\ \n","the most intricate tapestry begins with a solitary thread.\n","\n",": Teach me about resilience.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.1 指定完成任务所需的步骤**"]},{"cell_type":"code","execution_count":50,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for prompt 1:\n","1 - Jack and Jill, siblings, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they return home and remain undeterred in their adventurous spirits.\n","\n","2 - Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\n","\n","3 - Jack, Jill\n","\n","4 - {\n"," \"french_summary\": \"Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["text = f\"\"\"\n","In a charming village, siblings Jack and Jill set out on \\ \n","a quest to fetch water from a hilltop \\ \n","well. As they climbed, singing joyfully, misfortune \\ \n","struck—Jack tripped on a stone and tumbled \\ \n","down the hill, with Jill following suit. \\ \n","Though slightly battered, the pair returned home to \\ \n","comforting embraces. Despite the mishap, \\ \n","their adventurous spirits remained undimmed, and they \\ \n","continued exploring with delight.\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","Perform the following actions: \n","1 - Summarize the following text delimited by triple \\\n","backticks with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the following \\\n","keys: french_summary, num_names.\n","\n","Separate your answers with line breaks.\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"Completion for prompt 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":51,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","Completion for prompt 2:\n","Summary: Jack and Jill, siblings from a charming village, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they remain undeterred and continue exploring with delight.\n","\n","Translation: Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\n","\n","Names: Jack, Jill\n","\n","Output JSON: \n","{\n"," \"french_summary\": \"Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["prompt_2 = f\"\"\"\n","Your task is to perform the following actions: \n","1 - Summarize the following text delimited by <> with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the \n","following keys: french_summary, num_names.\n","\n","Use the following format:\n","Text: \n","Summary: \n","Translation: \n","Names: \n","Output JSON: \n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nCompletion for prompt 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.2 指导模型在下结论之前找出一个自己的解法**"]},{"cell_type":"code","execution_count":52,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The student's solution is correct. They correctly identified the costs for land, solar panels, and maintenance, and calculated the total cost for the first year of operations as a function of the number of square feet.\n"]}],"source":["prompt = f\"\"\"\n","Determine if the student's solution is correct or not.\n","\n","Question:\n","I'm building a solar power installation and I need \\\n"," help working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\ \n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \n","as a function of the number of square feet.\n","\n","Student's Solution:\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"code","execution_count":53,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To calculate the total cost for the first year of operations, we need to add up the costs of land, solar panels, and maintenance.\n","\n","1. Land cost: $100 / square foot\n","The cost of land is $100 multiplied by the number of square feet.\n","\n","2. Solar panel cost: $250 / square foot\n","The cost of solar panels is $250 multiplied by the number of square feet.\n","\n","3. Maintenance cost: $100,000 + $10 / square foot\n","The maintenance cost is a flat fee of $100,000 per year, plus $10 multiplied by the number of square feet.\n","\n","Total cost: Land cost + Solar panel cost + Maintenance cost\n","\n","So the actual solution is:\n","Total cost = (100 * x) + (250 * x) + (100,000 + (10 * x))\n","\n","Is the student's solution the same as the actual solution just calculated:\n","No\n","\n","Student grade:\n","Incorrect\n"]}],"source":["prompt = f\"\"\"\n","Your task is to determine if the student's solution \\\n","is correct or not.\n","To solve the problem do the following:\n","- First, work out your own solution to the problem. \n","- Then compare your solution to the student's solution \\ \n","and evaluate if the student's solution is correct or not. \n","Don't decide if the student's solution is correct until \n","you have done the problem yourself.\n","\n","Use the following format:\n","Question:\n","```\n","question here\n","```\n","Student's solution:\n","```\n","student's solution here\n","```\n","Actual solution:\n","```\n","steps to work out the solution and your solution here\n","```\n","Is the student's solution the same as actual solution \\\n","just calculated:\n","```\n","yes or no\n","```\n","Student grade:\n","```\n","correct or incorrect\n","```\n","\n","Question:\n","```\n","I'm building a solar power installation and I need help \\\n","working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\\n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \\\n","as a function of the number of square feet.\n","``` \n","Student's solution:\n","```\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","```\n","Actual solution:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**3.1 幻觉**"]},{"cell_type":"code","execution_count":54,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The AeroGlide UltraSlim Smart Toothbrush by Boie is a technologically advanced toothbrush designed to provide a superior brushing experience. Boie is a company known for its innovative oral care products, and the AeroGlide UltraSlim Smart Toothbrush is no exception.\n","\n","One of the standout features of this toothbrush is its ultra-slim design. The brush head is only 2mm thick, making it much thinner than traditional toothbrushes. This slim profile allows for better access to hard-to-reach areas of the mouth, ensuring a thorough and effective clean.\n","\n","The AeroGlide UltraSlim Smart Toothbrush also incorporates smart technology. It connects to a mobile app via Bluetooth, allowing users to track their brushing habits and receive personalized recommendations for improving their oral hygiene routine. The app provides real-time feedback on brushing technique, duration, and coverage, helping users to achieve optimal oral health.\n","\n","The toothbrush features soft, antimicrobial bristles made from a durable thermoplastic elastomer. These bristles are gentle on the gums and teeth, while also being effective at removing plaque and debris. The antimicrobial properties help to keep the brush head clean and hygienic between uses.\n","\n","Another notable feature of the AeroGlide UltraSlim Smart Toothbrush is its long battery life. It can last up to 30 days on a single charge, making it convenient for travel or everyday use without the need for frequent recharging.\n","\n","Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie offers a combination of advanced technology, slim design, and effective cleaning capabilities. It is a great option for those looking to upgrade their oral care routine and achieve a healthier smile.\n"]}],"source":["prompt = f\"\"\"\n","Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":4} diff --git a/content/Prompt Engineering for Developer/do_contents.py b/content/Prompt Engineering for Developer/do_contents.py new file mode 100644 index 0000000..87a11d3 --- /dev/null +++ b/content/Prompt Engineering for Developer/do_contents.py @@ -0,0 +1,33 @@ +import os +import codecs +import json + +def add_toc(ipynb_file): + f = codecs.open(ipynb_file, 'r') + source = f.read() + y = json.loads(source) + toc = ["\n"] + for item in y["cells"]: + if item["cell_type"]=='markdown': + if len(item["source"]) == 0: + continue + # print(item["source"]) + + item_start = item['source'][0].strip("\n") + if item_start.startswith("#"): + l = len(item_start.split()[0]) + if l<=3 and l>1: + name = " ".join(item_start.split(" ")[1:]) + tag = "-".join(item_start.split(" ")[1:]) + tab = " "*(l-2) + toc.append(f' {tab}- [{name}](#{tag})\n') + + y["cells"][0]['source']= y["cells"][0]['source'][0:1] + y["cells"][0]['source'].extend(toc) + f = codecs.open(ipynb_file, 'w') + f.write(json.dumps(y)) + f.close() + +for file in os.listdir("."): + if file.endswith("ipynb") and file[0].isdigit(): + add_toc(file) \ No newline at end of file From 8137a304b3af0e0d3cb988653e455d1b273c2627 Mon Sep 17 00:00:00 2001 From: nowadays0421 Date: Tue, 18 Jul 2023 11:07:32 +0800 Subject: [PATCH 02/13] Finish PE 2 --- .../2. 提示原则 Guidelines.ipynb | 1239 +---------------- .../do_contents.py | 33 + 2 files changed, 34 insertions(+), 1238 deletions(-) create mode 100644 content/Prompt Engineering for Developer/do_contents.py diff --git a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb index cf339f7..74d0eaf 100644 --- a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb +++ b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb @@ -1,1238 +1 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 第二章 编写 Prompt 的原则\n", - "\n", - " 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,您可以练习编写高效的 Prompt,从而便捷而有效地使用 LLM。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " \n", - "
" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 一、环境配置" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "本教程使用 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": [ - "首先需要安装 OpenAI 库:\n", - "```bash\n", - "pip install openai\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "# 导入第三方库\n", - "\n", - "openai.api_key = \"sk-...\"\n", - "# 设置 API_KEY, 请替换成您自己的 API_KEY\n", - "\n", - "# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。\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": [ - "整个课程将以 gpt-3.5-turbo 模型为例。我们将在后续课程中深入探究 OpenAI 提供的 [Chat Completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 的使用方法,在此处,我们先将它封装成一个函数,您无需知道其内部机理,仅需知道调用该函数,以 Prompt 为输入参数,其将会输出对应的 Completion (回答结果)即可。" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# 一个封装 OpenAI 接口的函数,参数为 Prompt,返回对应结果\n", - "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", - " '''\n", - " prompt: 对应的提示词\n", - " model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4\n", - " '''\n", - " messages = [{\"role\": \"user\", \"content\": prompt}]\n", - " response = openai.ChatCompletion.create(\n", - " model=model,\n", - " messages=messages,\n", - " temperature=0, # 模型输出的温度系数,控制输出的随机程度\n", - " )\n", - " # 调用 OpenAI 的 ChatCompletion 接口\n", - " return response.choices[0].message[\"content\"]\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 二、两个基本原则" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 原则一:编写清晰、具体的指令\n", - "\n", - "您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.1 使用分隔符清晰地表示输入的不同部分**\n", - "\n", - "分隔符可以是:```,\"\",<>,:,\\ \\等。\n", - "\n", - "您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n", - "\n", - "在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# 中文版见下一个 cell\n", - "text = f\"\"\"\n", - "You should express what you want a model to do by \\ \n", - "providing instructions that are as clear and \\ \n", - "specific as you can possibly make them. \\ \n", - "This will guide the model towards the desired output, \\ \n", - "and reduce the chances of receiving irrelevant \\ \n", - "or incorrect responses. Don't confuse writing a \\ \n", - "clear prompt with writing a short prompt. \\ \n", - "In many cases, longer prompts provide more clarity \\ \n", - "and context for the model, which can lead to \\ \n", - "more detailed and relevant outputs.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "Summarize the text delimited by triple backticks \\ \n", - "into a single sentence.\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "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", - "prompt = f\"\"\"\n", - "把用三个反引号括起来的文本总结成一句话。\n", - "```{text}```\n", - "\"\"\"\n", - "# 指令内容,使用 ``` 来分隔指令和待总结的内容\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.2 寻求结构化的输出**\n", - "\n", - "输出可以是 Json、HTML 等格式。\n", - "\n", - "第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n", - "\n", - "在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Lost City of Zorath\",\n", - " \"author\": \"Aria Blackwood\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Last Survivors\",\n", - " \"author\": \"Ethan Stone\",\n", - " \"genre\": \"Science Fiction\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Secret Life of Bees\",\n", - " \"author\": \"Lila Rose\",\n", - " \"genre\": \"Romance\"\n", - " }\n", - "]\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Generate a list of three made-up book titles along \\ \n", - "with their authors and genres. \n", - "Provide them in JSON format with the following keys: \n", - "book_id, title, author, genre.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"books\": [\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Shadow of the Wind\",\n", - " \"author\": \"Carlos Ruiz Zafón\",\n", - " \"genre\": \"Mystery\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Name of the Wind\",\n", - " \"author\": \"Patrick Rothfuss\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Hitchhiker's Guide to the Galaxy\",\n", - " \"author\": \"Douglas Adams\",\n", - " \"genre\": \"Science Fiction\"\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请生成包括书名、作者和类别的三本虚构书籍清单,\\\n", - "并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.3 要求模型检查是否满足条件**\n", - "\n", - "如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n", - "\n", - "在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 1:\n", - "Step 1 - Get some water boiling.\n", - "Step 2 - Grab a cup and put a tea bag in it.\n", - "Step 3 - Once the water is hot enough, pour it over the tea bag.\n", - "Step 4 - Let it sit for a bit so the tea can steep.\n", - "Step 5 - After a few minutes, take out the tea bag.\n", - "Step 6 - Add some sugar or milk to taste.\n", - "Step 7 - Enjoy your delicious cup of tea!\n", - "\n", - "\n" - ] - } - ], - "source": [ - "text_1 = f\"\"\"\n", - "Making a cup of tea is easy! First, you need to get some \\ \n", - "water boiling. While that's happening, \\ \n", - "grab a cup and put a tea bag in it. Once the water is \\ \n", - "hot enough, just pour it over the tea bag. \\ \n", - "Let it sit for a bit so the tea can steep. After a \\ \n", - "few minutes, take out the tea bag. If you \\ \n", - "like, you can add some sugar or milk to taste. \\ \n", - "And that's it! You've got yourself a delicious \\ \n", - "cup of tea to enjoy.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 2:\n", - "No steps provided.\n" - ] - } - ], - "source": [ - "text_2 = f\"\"\"\n", - "The sun is shining brightly today, and the birds are \\\n", - "singing. It's a beautiful day to go for a \\ \n", - "walk in the park. The flowers are blooming, and the \\ \n", - "trees are swaying gently in the breeze. People \\ \n", - "are out and about, enjoying the lovely weather. \\ \n", - "Some are having picnics, while others are playing \\ \n", - "games or simply relaxing on the grass. It's a \\ \n", - "perfect day to spend time outdoors and appreciate the \\ \n", - "beauty of nature.\n", - "\"\"\"\n", - "prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 1 的总结:\n", - "第一步 - 把水烧开。\n", - "第二步 - 拿一个杯子并把茶包放进去。\n", - "第三步 - 把烧开的水倒在茶包上。\n", - "第四步 - 等待几分钟,让茶叶浸泡。\n", - "第五步 - 取出茶包。\n", - "第六步 - 如果你愿意,可以加一些糖或牛奶调味。\n", - "第七步 - 就这样,你可以享受一杯美味的茶了。\n" - ] - } - ], - "source": [ - "# 满足条件的输入(text中提供了步骤)\n", - "text_1 = f\"\"\"\n", - "泡一杯茶很容易。首先,需要把水烧开。\\\n", - "在等待期间,拿一个杯子并把茶包放进去。\\\n", - "一旦水足够热,就把它倒在茶包上。\\\n", - "等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n", - "如果您愿意,可以加一些糖或牛奶调味。\\\n", - "就这样,您可以享受一杯美味的茶了。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 1 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 2 的总结:\n", - "未提供步骤。\n" - ] - } - ], - "source": [ - "# 不满足条件的输入(text中未提供预期指令)\n", - "text_2 = f\"\"\"\n", - "今天阳光明媚,鸟儿在歌唱。\\\n", - "这是一个去公园散步的美好日子。\\\n", - "鲜花盛开,树枝在微风中轻轻摇曳。\\\n", - "人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n", - "这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 2 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.4 提供少量示例**(少样本提示词,Few-shot prompting)\n", - "\n", - "即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n", - "\n", - "例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - ": 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.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to answer in a consistent style.\n", - "\n", - ": Teach me about patience.\n", - "\n", - ": The river that carves the deepest \\ \n", - "valley flows from a modest spring; the \\ \n", - "grandest symphony originates from a single note; \\ \n", - "the most intricate tapestry begins with a solitary thread.\n", - "\n", - ": Teach me about resilience.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。在生活中,我们也需要经历各种挫折和困难,才能锻炼出韧性。记住,不要轻易放弃,坚持下去,你会发现自己变得更加坚强。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "您的任务是以一致的风格回答问题。\n", - "\n", - "<孩子>: 教我耐心。\n", - "\n", - "<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n", - "\n", - "<孩子>: 教我韧性。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 给模型时间去思考\n", - "\n", - "如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.1 指定完成任务所需的步骤**\n", - "\n", - "接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和人名个数。要求输出以换行符分隔。" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for prompt 1:\n", - "Two siblings, Jack and Jill, go on a quest to fetch water from a well on a hilltop, but misfortune strikes and they both tumble down the hill, returning home slightly battered but with their adventurous spirits undimmed.\n", - "\n", - "Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts. \n", - "Noms: Jack, Jill.\n", - "\n", - "{\n", - " \"french_summary\": \"Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "In a charming village, siblings Jack and Jill set out on \\ \n", - "a quest to fetch water from a hilltop \\ \n", - "well. As they climbed, singing joyfully, misfortune \\ \n", - "struck—Jack tripped on a stone and tumbled \\ \n", - "down the hill, with Jill following suit. \\ \n", - "Though slightly battered, the pair returned home to \\ \n", - "comforting embraces. Despite the mishap, \\ \n", - "their adventurous spirits remained undimmed, and they \\ \n", - "continued exploring with delight.\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "Perform the following actions: \n", - "1 - Summarize the following text delimited by triple \\\n", - "backticks with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the following \\\n", - "keys: french_summary, num_names.\n", - "\n", - "Separate your answers with line breaks.\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"Completion for prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "prompt 1:\n", - "1-兄妹在山顶井里打水时发生意外,但仍然保持冒险精神。\n", - "2-Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\n", - "3-Jack, Jill\n", - "4-{\n", - " \"French_summary\": \"Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n", - "他们一边唱着欢乐的歌,一边往上爬,\\\n", - "然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n", - "虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n", - "尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "执行以下操作:\n", - "1-用一句话概括下面用三个反引号括起来的文本。\n", - "2-将摘要翻译成法语。\n", - "3-在法语摘要中列出每个人名。\n", - "4-输出一个 JSON 对象,其中包含以下键:French_summary,num_names。\n", - "\n", - "请用换行符分隔您的答案。\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n", - "\n", - "因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Completion for prompt 2:\n", - "Summary: 兄妹杰克和吉尔在山顶井里打水时发生意外,但他们仍然保持冒险精神继续探索。\n", - "Translation: Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\n", - "Names: Jack, Jill\n", - "Output JSON: {\"french_summary\": \"Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\", \"num_names\": 2}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "Your task is to perform the following actions: \n", - "1 - Summarize the following text delimited by <> with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the \n", - "following keys: french_summary, num_names.\n", - "\n", - "Use the following format:\n", - "Text: \n", - "Summary: \n", - "Translation: \n", - "Names: \n", - "Output JSON: \n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nCompletion for prompt 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "prompt 2:\n", - "摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。\n", - "翻译: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.\n", - "名称:Jack,Jill\n", - "输出 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}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "1-用一句话概括下面用<>括起来的文本。\n", - "2-将摘要翻译成英语。\n", - "3-在英语摘要中列出每个名称。\n", - "4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n", - "\n", - "请使用以下格式:\n", - "文本:<要总结的文本>\n", - "摘要:<摘要>\n", - "翻译:<摘要的翻译>\n", - "名称:<英语摘要中的名称列表>\n", - "输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nprompt 2:\")\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.2 指导模型在下结论之前找出一个自己的解法**\n", - "\n", - "明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n", - "\n", - "接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The student's solution is correct.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Determine if the student's solution is correct or not.\n", - "\n", - "Question:\n", - "I'm building a solar power installation and I need \\\n", - " help working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\ \n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \n", - "as a function of the number of square feet.\n", - "\n", - "Student's Solution:\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "学生的解决方案是正确的。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "判断学生的解决方案是否正确。\n", - "\n", - "问题:\n", - "我正在建造一个太阳能发电站,需要帮助计算财务。\n", - "\n", - " 土地费用为 100美元/平方英尺\n", - " 我可以以 250美元/平方英尺的价格购买太阳能电池板\n", - " 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "设x为发电站的大小,单位为平方英尺。\n", - "费用:\n", - "\n", - " 土地费用:100x\n", - " 太阳能电池板费用:250x\n", - " 维护费用:100,000美元+100x\n", - " 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n", - "\n", - "我们可以通过指导模型先自行找出一个解法来解决这个问题。\n", - "\n", - "在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Let x be the size of the installation in square feet.\n", - "\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 10x\n", - "\n", - "Total cost: 100x + 250x + 100,000 + 10x = 360x + 100,000\n", - "\n", - "Is the student's solution the same as actual solution just calculated:\n", - "No\n", - "\n", - "Student grade:\n", - "Incorrect\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to determine if the student's solution \\\n", - "is correct or not.\n", - "To solve the problem do the following:\n", - "- First, work out your own solution to the problem. \n", - "- Then compare your solution to the student's solution \\ \n", - "and evaluate if the student's solution is correct or not. \n", - "Don't decide if the student's solution is correct until \n", - "you have done the problem yourself.\n", - "\n", - "Use the following format:\n", - "Question:\n", - "```\n", - "question here\n", - "```\n", - "Student's solution:\n", - "```\n", - "student's solution here\n", - "```\n", - "Actual solution:\n", - "```\n", - "steps to work out the solution and your solution here\n", - "```\n", - "Is the student's solution the same as actual solution \\\n", - "just calculated:\n", - "```\n", - "yes or no\n", - "```\n", - "Student grade:\n", - "```\n", - "correct or incorrect\n", - "```\n", - "\n", - "Question:\n", - "```\n", - "I'm building a solar power installation and I need help \\\n", - "working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\\n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \\\n", - "as a function of the number of square feet.\n", - "``` \n", - "Student's solution:\n", - "```\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "```\n", - "Actual solution:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "正确的解决方案和步骤:\n", - " 1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元\n", - " 2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元\n", - " 3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元\n", - " 4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元\n", - "\n", - "学生的解决方案和实际解决方案是否相同:否\n", - "\n", - "学生的成绩:不正确\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n", - "\n", - "步骤:\n", - "\n", - " 首先,自己解决问题。\n", - " 然后将您的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。\n", - " 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n", - "\n", - "使用以下格式:\n", - "\n", - " 问题:问题文本\n", - " 学生的解决方案:学生的解决方案文本\n", - " 实际解决方案和步骤:实际解决方案和步骤文本\n", - " 学生的解决方案和实际解决方案是否相同:是或否\n", - " 学生的成绩:正确或不正确\n", - "\n", - "问题:\n", - "\n", - " 我正在建造一个太阳能发电站,需要帮助计算财务。 \n", - " - 土地费用为每平方英尺100美元\n", - " - 我可以以每平方英尺250美元的价格购买太阳能电池板\n", - " - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "\n", - " 设x为发电站的大小,单位为平方英尺。\n", - " 费用:\n", - " 1. 土地费用:100x\n", - " 2. 太阳能电池板费用:250x\n", - " 3. 维护费用:100,000+100x\n", - " 总费用:100x+250x+100,000+100x=450x+100,000\n", - "\n", - "实际解决方案和步骤:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 三、局限性" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**开发大模型相关应用时请务必铭记:**\n", - "\n", - "\n", - "**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n", - "\n", - "虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n", - "\n", - "如下示例展示了大模型的幻觉。我们要求告诉我们 Boie 公司生产的 *AeroGlide UltraSlim Smart Toothbrush* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The AeroGlide UltraSlim Smart Toothbrush by Boie is a high-tech toothbrush that uses advanced sonic technology to provide a deep and thorough clean. It features a slim and sleek design that makes it easy to hold and maneuver, and it comes with a range of smart features that help you optimize your brushing routine.\n", - "\n", - "One of the key features of the AeroGlide UltraSlim Smart Toothbrush is its advanced sonic technology, which uses high-frequency vibrations to break up plaque and bacteria on your teeth and gums. This technology is highly effective at removing even the toughest stains and buildup, leaving your teeth feeling clean and fresh.\n", - "\n", - "In addition to its sonic technology, the AeroGlide UltraSlim Smart Toothbrush also comes with a range of smart features that help you optimize your brushing routine. These include a built-in timer that ensures you brush for the recommended two minutes, as well as a pressure sensor that alerts you if you're brushing too hard.\n", - "\n", - "Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie is a highly advanced and effective toothbrush that is perfect for anyone looking to take their oral hygiene to the next level. With its advanced sonic technology and smart features, it provides a deep and thorough clean that leaves your teeth feeling fresh and healthy.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款智能牙刷,具有以下特点:\n", - "\n", - "1. 超薄设计:刷头仅有0.8毫米的厚度,可以更容易地进入口腔深处,清洁更彻底。\n", - "\n", - "2. 智能感应:牙刷配备了智能感应技术,可以自动识别刷头的位置和方向,确保每个部位都得到充分的清洁。\n", - "\n", - "3. 高效清洁:牙刷采用了高速振动技术,每分钟可达到40000次,可以有效去除牙菌斑和污渍。\n", - "\n", - "4. 轻松携带:牙刷采用了便携式设计,可以轻松放入口袋或旅行包中,随时随地进行口腔清洁。\n", - "\n", - "5. 环保材料:牙刷采用了环保材料制造,不含有害物质,对环境友好。\n", - "\n", - "总之,Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款高效、智能、环保的牙刷,可以帮助用户轻松保持口腔健康。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "告诉我 Boie 公司生产的 AeroGlide UltraSlim Smart Toothbrush 的相关信息\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n", - "\n", - "在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**关于反斜杠使用的说明:**\n", - "\n", - "在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - }, - "latex_envs": { - "LaTeX_envs_menu_present": true, - "autoclose": false, - "autocomplete": true, - "bibliofile": "biblio.bib", - "cite_by": "apalike", - "current_citInitial": 1, - "eqLabelWithNumbers": true, - "eqNumInitial": 1, - "hotkeys": { - "equation": "Ctrl-E", - "itemize": "Ctrl-I" - }, - "labels_anchors": false, - "latex_user_defs": false, - "report_style_numbering": false, - "user_envs_cfg": false - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells":[{"attachments":{},"cell_type":"markdown","metadata":{},"source":["# 第二章 提示原则 Guidelines\n","\n"," - [一、原则一 编写清晰、具体的指令](#一、原则一-编写清晰、具体的指令)\n"," - [1.1 使用分隔符清晰地表示输入的不同部分](#1.1-使用分隔符清晰地表示输入的不同部分)\n"," - [1.2 寻求结构化的输出](#1.2-寻求结构化的输出)\n"," - [1.3 要求模型检查是否满足条件](#1.3-要求模型检查是否满足条件)\n"," - [1.4 提供少量示例](#1.4-提供少量示例)\n"," - [二、原则二 给模型时间去思考](#二、原则二-给模型时间去思考)\n"," - [2.1 指定完成任务所需的步骤](#2.1-指定完成任务所需的步骤)\n"," - [2.2 指导模型在下结论之前找出一个自己的解法](#2.2-指导模型在下结论之前找出一个自己的解法)\n"," - [三、局限性](#三、局限性)\n"," - [四、英文原版 Prompt](#四、英文原版-Prompt)\n"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。"]},{"cell_type":"markdown","metadata":{},"source":["### 1.1 使用分隔符清晰地表示输入的不同部分"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","分隔符可以是:```,\"\",<>,:,\\ \\等。\n","\n","您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n","\n","在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n"]},{"cell_type":"code","execution_count":11,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["为了获得所需的输出,您应该提供清晰、具体的指示,避免与简短的提示词混淆,并使用更长的提示词来提供更多的清晰度和上下文信息。\n"]}],"source":["text = f\"\"\"\n","您应该提供尽可能清晰、具体的指示,以表达您希望模型执行的任务。\\\n","这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\\\n","不要将写清晰的提示词与写简短的提示词混淆。\\\n","在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n","\"\"\"\n","# 需要总结的文本内容\n","prompt = f\"\"\"\n","把用三个反引号括起来的文本总结成一句话。\n","```{text}```\n","\"\"\"\n","# 指令内容,使用 ``` 来分隔指令和待总结的内容\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["### 1.2 寻求结构化的输出"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","输出可以是 Json、HTML 等格式。\n","\n","第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n","\n","在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"]},{"cell_type":"code","execution_count":15,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"迷失的时光\",\n"," \"author\": \"张三\",\n"," \"genre\": \"科幻\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"幻境之门\",\n"," \"author\": \"李四\",\n"," \"genre\": \"奇幻\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"虚拟现实\",\n"," \"author\": \"王五\",\n"," \"genre\": \"科幻\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","请生成包括书名、作者和类别的三本虚构的、非真实存在的中文书籍清单,\\\n","并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.3 要求模型检查是否满足条件"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n","\n","在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。"]},{"cell_type":"code","execution_count":16,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 1 的总结:\n","第一步 - 把水烧开。\n","第二步 - 拿一个杯子并把茶包放进去。\n","第三步 - 把烧开的水倒在茶包上。\n","第四步 - 等待几分钟,让茶叶浸泡。\n","第五步 - 取出茶包。\n","第六步 - 如果需要,加入糖或牛奶调味。\n","第七步 - 就这样,您可以享受一杯美味的茶了。\n"]}],"source":["# 满足条件的输入(text中提供了步骤)\n","text_1 = f\"\"\"\n","泡一杯茶很容易。首先,需要把水烧开。\\\n","在等待期间,拿一个杯子并把茶包放进去。\\\n","一旦水足够热,就把它倒在茶包上。\\\n","等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n","如果您愿意,可以加一些糖或牛奶调味。\\\n","就这样,您可以享受一杯美味的茶了。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 1 的总结:\")\n","print(response)"]},{"cell_type":"code","execution_count":17,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 2 的总结:\n","未提供步骤。\n"]}],"source":["# 不满足条件的输入(text中未提供预期指令)\n","text_2 = f\"\"\"\n","今天阳光明媚,鸟儿在歌唱。\\\n","这是一个去公园散步的美好日子。\\\n","鲜花盛开,树枝在微风中轻轻摇曳。\\\n","人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n","这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 2 的总结:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.4 提供少量示例"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n","\n","例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。"]},{"cell_type":"code","execution_count":22,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["<祖父母>: 韧性是一种坚持不懈的品质,就像一棵顽强的树在风雨中屹立不倒。它是面对困难和挑战时不屈不挠的精神,能够适应变化和克服逆境。韧性是一种内在的力量,让我们能够坚持追求目标,即使面临困难和挫折也能坚持不懈地努力。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是以一致的风格回答问题。\n","\n","<孩子>: 请教我何为耐心。\n","\n","<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n","\n","<孩子>: 请教我何为韧性。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 二、原则二 给模型时间去思考\n","\n","如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。"]},{"cell_type":"markdown","metadata":{},"source":["### 2.1 指定完成任务所需的步骤"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。"]},{"cell_type":"code","execution_count":28,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["prompt 1:\n","1-两个兄妹在山上打水时发生意外,但最终平安回家。\n","2-In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\n","3-Jack, Jill\n","4-{\"english_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\", \"num_names\": 2}\n"]}],"source":["text = f\"\"\"\n","在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n","他们一边唱着欢乐的歌,一边往上爬,\\\n","然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n","虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n","尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","执行以下操作:\n","1-用一句话概括下面用三个反引号括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个人名。\n","4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。\n","\n","请用换行符分隔您的答案。\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"prompt 1:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,要求从英语翻译到法语,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n","\n","因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","prompt 2:\n","Summary: 在一个迷人的村庄里,兄妹杰克和吉尔在山顶井里打水时发生了意外,但他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\n","Translation: In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\n","\n","Names: Jack, Jill\n","\n","JSON Output: {\"English_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\", \"num_names\": 2}\n"]}],"source":["prompt_2 = f\"\"\"\n","1-用一句话概括下面用<>括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个名称。\n","4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n","\n","请使用以下格式:\n","文本:<要总结的文本>\n","摘要:<摘要>\n","翻译:<摘要的翻译>\n","名称:<英语摘要中的名称列表>\n","输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nprompt 2:\")\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":[" "]},{"cell_type":"markdown","metadata":{},"source":["### 2.2 指导模型在下结论之前找出一个自己的解法"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n","\n","接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:"]},{"cell_type":"code","execution_count":30,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["学生的解决方案是正确的。他正确地计算了土地费用、太阳能电池板费用和维护费用,并将它们相加得到了总费用。\n"]}],"source":["prompt = f\"\"\"\n","判断学生的解决方案是否正确。\n","\n","问题:\n","我正在建造一个太阳能发电站,需要帮助计算财务。\n","\n"," 土地费用为 100美元/平方英尺\n"," 我可以以 250美元/平方英尺的价格购买太阳能电池板\n"," 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","设x为发电站的大小,单位为平方英尺。\n","费用:\n","\n"," 土地费用:100x\n"," 太阳能电池板费用:250x\n"," 维护费用:100,000美元+100x\n"," 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n","\n","我们可以通过指导模型先自行找出一个解法来解决这个问题。\n","\n","在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"]},{"cell_type":"code","execution_count":40,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["实际解决方案和步骤:\n","\n"," 1. 土地费用:每平方英尺100美元,所以总费用为100x美元。\n"," 2. 太阳能电池板费用:每平方英尺250美元,所以总费用为250x美元。\n"," 3. 维护费用:固定费用为10万美元,额外费用为每平方英尺10美元,所以总费用为10万美元+10x美元。\n"," 4. 总费用:将上述三项费用相加,得到总费用为100x美元+250x美元+10万美元+10x美元=360x+10万美元。\n","\n","学生计算的总费用:450x+10万美元\n","实际计算的总费用:360x+10万美元\n","学生计算的费用和实际计算的费用是否相同:否\n","学生的解决方案和实际解决方案是否相同:否\n","学生的成绩:不正确\n"]}],"source":["prompt = f\"\"\"\n","请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n","\n","步骤:\n","\n"," 首先,自己解决问题。\n"," 然后将您的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。\n"," 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n","\n","使用以下格式:\n","\n"," 问题:问题文本\n"," 学生的解决方案:学生的解决方案文本\n"," 实际解决方案和步骤:实际解决方案和步骤文本\n"," 学生计算的总费用:学生计算得到的总费用\n"," 实际计算的总费用:实际计算出的总费用\n"," 学生计算的费用和实际计算的费用是否相同:是或否\n"," 学生的解决方案和实际解决方案是否相同:是或否\n"," 学生的成绩:正确或不正确\n","\n","问题:\n","\n"," 我正在建造一个太阳能发电站,需要帮助计算财务。 \n"," - 土地费用为每平方英尺100美元\n"," - 我可以以每平方英尺250美元的价格购买太阳能电池板\n"," - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元;\n","\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","\n"," 设x为发电站的大小,单位为平方英尺。\n"," 费用:\n"," 1. 土地费用:100x美元\n"," 2. 太阳能电池板费用:250x美元\n"," 3. 维护费用:100,000+100x=10万美元+10x美元\n"," 总费用:100x美元+250x美元+10万美元+100x美元=450x+10万美元\n","\n","实际解决方案和步骤:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 三、局限性"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**开发大模型相关应用时请务必铭记:**\n","\n","\n","**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n","\n","虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n","\n","如下示例展示了大模型的幻觉。我们要求告诉我们华为公司生产的 *GT Watch 运动手表* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n","\n"]},{"cell_type":"code","execution_count":44,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["华为公司生产的GT Watch运动手表是一款智能手表,具有多种功能和特点。以下是相关信息:\n","\n","1. 设计和外观:GT Watch采用圆形表盘设计,具有精致的外观和高质量的材料制造。它有多种颜色和表带选择,可以根据个人喜好进行定制。\n","\n","2. 显示屏:GT Watch配备了1.39英寸的AMOLED显示屏,具有高清分辨率和良好的可视性。用户可以通过触摸屏幕进行操作和导航。\n","\n","3. 运动追踪:GT Watch具有全天候的运动追踪功能,可以监测用户的步数、跑步距离、卡路里消耗和心率等数据。它还支持多种运动模式,如跑步、骑行、游泳等。\n","\n","4. 健康监测:GT Watch可以监测用户的心率、血氧饱和度和睡眠质量等健康指标。它还提供健康建议和提醒,帮助用户保持良好的健康状态。\n","\n","5. 通知和连接:GT Watch可以与用户的手机进行连接,通过蓝牙技术实现通知推送和电话提醒。用户可以在手表上查看短信、电话和社交媒体通知,无需拿出手机。\n","\n","6. 长续航时间:GT Watch具有较长的续航时间,一次充电可以使用数天。它还支持快速充电技术,可以在短时间内充满电。\n","\n","7. 其他功能:GT Watch还具有其他功能,如天气预报、闹钟、计时器、计步器等。它还支持NFC支付和音乐控制等便利功能。\n","\n","总体而言,华为GT Watch是一款功能强大、外观精致的智能运动手表,适合那些注重健康和运动的用户使用。\n"]}],"source":["prompt = f\"\"\"\n","告诉我华为公司生产的GT Watch运动手表的相关信息\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n","\n","在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**关于反斜杠使用的说明:**\n","\n","在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。"]},{"cell_type":"markdown","metadata":{},"source":["## 四、英文原版 Prompt"]},{"cell_type":"markdown","metadata":{},"source":["**1.1 使用分隔符清晰地表示输入的不同部分**"]},{"cell_type":"code","execution_count":45,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To guide a model towards the desired output and reduce irrelevant or incorrect responses, it is important to provide clear and specific instructions, which can be achieved through longer prompts that offer more clarity and context.\n"]}],"source":["text = f\"\"\"\n","You should express what you want a model to do by \\ \n","providing instructions that are as clear and \\ \n","specific as you can possibly make them. \\ \n","This will guide the model towards the desired output, \\ \n","and reduce the chances of receiving irrelevant \\ \n","or incorrect responses. Don't confuse writing a \\ \n","clear prompt with writing a short prompt. \\ \n","In many cases, longer prompts provide more clarity \\ \n","and context for the model, which can lead to \\ \n","more detailed and relevant outputs.\n","\"\"\"\n","prompt = f\"\"\"\n","Summarize the text delimited by triple backticks \\ \n","into a single sentence.\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.2**寻求结构化的输出"]},{"cell_type":"code","execution_count":46,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"The Enigma of Elysium\",\n"," \"author\": \"Evelyn Sinclair\",\n"," \"genre\": \"Mystery\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"Whispers in the Wind\",\n"," \"author\": \"Nathaniel Blackwood\",\n"," \"genre\": \"Fantasy\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"Echoes of the Past\",\n"," \"author\": \"Amelia Hart\",\n"," \"genre\": \"Romance\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","Generate a list of three made-up book titles along \\ \n","with their authors and genres. \n","Provide them in JSON format with the following keys: \n","book_id, title, author, genre.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":["**1.3 要求模型检查是否满足条件**"]},{"cell_type":"code","execution_count":56,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 1:\n","Step 1 - Get some water boiling.\n","Step 2 - Grab a cup and put a tea bag in it.\n","Step 3 - Once the water is hot enough, pour it over the tea bag.\n","Step 4 - Let it sit for a bit so the tea can steep.\n","Step 5 - After a few minutes, take out the tea bag.\n","Step 6 - If you like, add some sugar or milk to taste.\n","Step 7 - Enjoy your delicious cup of tea.\n"]}],"source":["text_1 = f\"\"\"\n","Making a cup of tea is easy! First, you need to get some \\ \n","water boiling. While that's happening, \\ \n","grab a cup and put a tea bag in it. Once the water is \\ \n","hot enough, just pour it over the tea bag. \\ \n","Let it sit for a bit so the tea can steep. After a \\ \n","few minutes, take out the tea bag. If you \\ \n","like, you can add some sugar or milk to taste. \\ \n","And that's it! You've got yourself a delicious \\ \n","cup of tea to enjoy.\n","\"\"\"\n","prompt = f\"\"\"\n","You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":48,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 2:\n","No steps provided.\n"]}],"source":["text_2 = f\"\"\"\n","The sun is shining brightly today, and the birds are \\\n","singing. It's a beautiful day to go for a \\ \n","walk in the park. The flowers are blooming, and the \\ \n","trees are swaying gently in the breeze. People \\ \n","are out and about, enjoying the lovely weather. \\ \n","Some are having picnics, while others are playing \\ \n","games or simply relaxing on the grass. It's a \\ \n","perfect day to spend time outdoors and appreciate the \\ \n","beauty of nature.\n","\"\"\"\n","prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.4 提供少量示例**(少样本提示词,Few-shot prompting)"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":[": Resilience is like a mighty oak tree that withstands the strongest storms, bending but never breaking. It is the unwavering determination to rise again after every fall, and the ability to find strength in the face of adversity. Just as a diamond is formed under immense pressure, resilience is forged through challenges and hardships, making us stronger and more resilient in the process.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to answer in a consistent style.\n","\n",": Teach me about patience.\n","\n",": The river that carves the deepest \\ \n","valley flows from a modest spring; the \\ \n","grandest symphony originates from a single note; \\ \n","the most intricate tapestry begins with a solitary thread.\n","\n",": Teach me about resilience.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.1 指定完成任务所需的步骤**"]},{"cell_type":"code","execution_count":50,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for prompt 1:\n","1 - Jack and Jill, siblings, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they return home and remain undeterred in their adventurous spirits.\n","\n","2 - Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\n","\n","3 - Jack, Jill\n","\n","4 - {\n"," \"french_summary\": \"Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["text = f\"\"\"\n","In a charming village, siblings Jack and Jill set out on \\ \n","a quest to fetch water from a hilltop \\ \n","well. As they climbed, singing joyfully, misfortune \\ \n","struck—Jack tripped on a stone and tumbled \\ \n","down the hill, with Jill following suit. \\ \n","Though slightly battered, the pair returned home to \\ \n","comforting embraces. Despite the mishap, \\ \n","their adventurous spirits remained undimmed, and they \\ \n","continued exploring with delight.\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","Perform the following actions: \n","1 - Summarize the following text delimited by triple \\\n","backticks with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the following \\\n","keys: french_summary, num_names.\n","\n","Separate your answers with line breaks.\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"Completion for prompt 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":51,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","Completion for prompt 2:\n","Summary: Jack and Jill, siblings from a charming village, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they remain undeterred and continue exploring with delight.\n","\n","Translation: Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\n","\n","Names: Jack, Jill\n","\n","Output JSON: \n","{\n"," \"french_summary\": \"Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["prompt_2 = f\"\"\"\n","Your task is to perform the following actions: \n","1 - Summarize the following text delimited by <> with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the \n","following keys: french_summary, num_names.\n","\n","Use the following format:\n","Text: \n","Summary: \n","Translation: \n","Names: \n","Output JSON: \n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nCompletion for prompt 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.2 指导模型在下结论之前找出一个自己的解法**"]},{"cell_type":"code","execution_count":52,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The student's solution is correct. They correctly identified the costs for land, solar panels, and maintenance, and calculated the total cost for the first year of operations as a function of the number of square feet.\n"]}],"source":["prompt = f\"\"\"\n","Determine if the student's solution is correct or not.\n","\n","Question:\n","I'm building a solar power installation and I need \\\n"," help working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\ \n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \n","as a function of the number of square feet.\n","\n","Student's Solution:\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"code","execution_count":53,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To calculate the total cost for the first year of operations, we need to add up the costs of land, solar panels, and maintenance.\n","\n","1. Land cost: $100 / square foot\n","The cost of land is $100 multiplied by the number of square feet.\n","\n","2. Solar panel cost: $250 / square foot\n","The cost of solar panels is $250 multiplied by the number of square feet.\n","\n","3. Maintenance cost: $100,000 + $10 / square foot\n","The maintenance cost is a flat fee of $100,000 per year, plus $10 multiplied by the number of square feet.\n","\n","Total cost: Land cost + Solar panel cost + Maintenance cost\n","\n","So the actual solution is:\n","Total cost = (100 * x) + (250 * x) + (100,000 + (10 * x))\n","\n","Is the student's solution the same as the actual solution just calculated:\n","No\n","\n","Student grade:\n","Incorrect\n"]}],"source":["prompt = f\"\"\"\n","Your task is to determine if the student's solution \\\n","is correct or not.\n","To solve the problem do the following:\n","- First, work out your own solution to the problem. \n","- Then compare your solution to the student's solution \\ \n","and evaluate if the student's solution is correct or not. \n","Don't decide if the student's solution is correct until \n","you have done the problem yourself.\n","\n","Use the following format:\n","Question:\n","```\n","question here\n","```\n","Student's solution:\n","```\n","student's solution here\n","```\n","Actual solution:\n","```\n","steps to work out the solution and your solution here\n","```\n","Is the student's solution the same as actual solution \\\n","just calculated:\n","```\n","yes or no\n","```\n","Student grade:\n","```\n","correct or incorrect\n","```\n","\n","Question:\n","```\n","I'm building a solar power installation and I need help \\\n","working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\\n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \\\n","as a function of the number of square feet.\n","``` \n","Student's solution:\n","```\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","```\n","Actual solution:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**3.1 幻觉**"]},{"cell_type":"code","execution_count":54,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The AeroGlide UltraSlim Smart Toothbrush by Boie is a technologically advanced toothbrush designed to provide a superior brushing experience. Boie is a company known for its innovative oral care products, and the AeroGlide UltraSlim Smart Toothbrush is no exception.\n","\n","One of the standout features of this toothbrush is its ultra-slim design. The brush head is only 2mm thick, making it much thinner than traditional toothbrushes. This slim profile allows for better access to hard-to-reach areas of the mouth, ensuring a thorough and effective clean.\n","\n","The AeroGlide UltraSlim Smart Toothbrush also incorporates smart technology. It connects to a mobile app via Bluetooth, allowing users to track their brushing habits and receive personalized recommendations for improving their oral hygiene routine. The app provides real-time feedback on brushing technique, duration, and coverage, helping users to achieve optimal oral health.\n","\n","The toothbrush features soft, antimicrobial bristles made from a durable thermoplastic elastomer. These bristles are gentle on the gums and teeth, while also being effective at removing plaque and debris. The antimicrobial properties help to keep the brush head clean and hygienic between uses.\n","\n","Another notable feature of the AeroGlide UltraSlim Smart Toothbrush is its long battery life. It can last up to 30 days on a single charge, making it convenient for travel or everyday use without the need for frequent recharging.\n","\n","Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie offers a combination of advanced technology, slim design, and effective cleaning capabilities. It is a great option for those looking to upgrade their oral care routine and achieve a healthier smile.\n"]}],"source":["prompt = f\"\"\"\n","Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":4} diff --git a/content/Prompt Engineering for Developer/do_contents.py b/content/Prompt Engineering for Developer/do_contents.py new file mode 100644 index 0000000..87a11d3 --- /dev/null +++ b/content/Prompt Engineering for Developer/do_contents.py @@ -0,0 +1,33 @@ +import os +import codecs +import json + +def add_toc(ipynb_file): + f = codecs.open(ipynb_file, 'r') + source = f.read() + y = json.loads(source) + toc = ["\n"] + for item in y["cells"]: + if item["cell_type"]=='markdown': + if len(item["source"]) == 0: + continue + # print(item["source"]) + + item_start = item['source'][0].strip("\n") + if item_start.startswith("#"): + l = len(item_start.split()[0]) + if l<=3 and l>1: + name = " ".join(item_start.split(" ")[1:]) + tag = "-".join(item_start.split(" ")[1:]) + tab = " "*(l-2) + toc.append(f' {tab}- [{name}](#{tag})\n') + + y["cells"][0]['source']= y["cells"][0]['source'][0:1] + y["cells"][0]['source'].extend(toc) + f = codecs.open(ipynb_file, 'w') + f.write(json.dumps(y)) + f.close() + +for file in os.listdir("."): + if file.endswith("ipynb") and file[0].isdigit(): + add_toc(file) \ No newline at end of file From a1b75f01323f02db20dbd6b36e4f8f3f15d34999 Mon Sep 17 00:00:00 2001 From: Logan Zou <74288839+nowadays0421@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:01:47 +0800 Subject: [PATCH 03/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc662bb..ccde0b6 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ LLM 正在逐步改变人们的生活,而对于开发者,如何基于 LLM - [玉琳-项目发起人](https://github.com/Sophia-Huang)(内容创作者-Datawhale成员) - [Joye](https://Joyenjoye.com)(内容创作者-数据科学家) - [高立业](https://github.com/0-yy-0)(内容创作者-DataWhale成员-算法工程师) -- AaronZ(内容创作者) +- [Zhang Yixin](https://github.com/YixinZ-NUS)(内容创作者-IT爱好者) - [万礼行](https://github.com/leason-wan)(内容创作者-视频翻译者) - [仲泰](https://github.com/ztgg0228)(内容创作者-Datawhale成员) - [魂兮](https://github.com/wisdom-pan)(内容创作者-前端工程师) From d0cfc855d280b8f30cb6c1b404fd05feb0bea350 Mon Sep 17 00:00:00 2001 From: nowadays0421 Date: Tue, 18 Jul 2023 11:07:32 +0800 Subject: [PATCH 04/13] Finish PE 2 --- .../2. 提示原则 Guidelines.ipynb | 1239 +---------------- .../do_contents.py | 33 + 2 files changed, 34 insertions(+), 1238 deletions(-) create mode 100644 content/Prompt Engineering for Developer/do_contents.py diff --git a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb index cf339f7..74d0eaf 100644 --- a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb +++ b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb @@ -1,1238 +1 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 第二章 编写 Prompt 的原则\n", - "\n", - " 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,您可以练习编写高效的 Prompt,从而便捷而有效地使用 LLM。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " \n", - "
" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 一、环境配置" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "本教程使用 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": [ - "首先需要安装 OpenAI 库:\n", - "```bash\n", - "pip install openai\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "# 导入第三方库\n", - "\n", - "openai.api_key = \"sk-...\"\n", - "# 设置 API_KEY, 请替换成您自己的 API_KEY\n", - "\n", - "# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。\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": [ - "整个课程将以 gpt-3.5-turbo 模型为例。我们将在后续课程中深入探究 OpenAI 提供的 [Chat Completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 的使用方法,在此处,我们先将它封装成一个函数,您无需知道其内部机理,仅需知道调用该函数,以 Prompt 为输入参数,其将会输出对应的 Completion (回答结果)即可。" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# 一个封装 OpenAI 接口的函数,参数为 Prompt,返回对应结果\n", - "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", - " '''\n", - " prompt: 对应的提示词\n", - " model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4\n", - " '''\n", - " messages = [{\"role\": \"user\", \"content\": prompt}]\n", - " response = openai.ChatCompletion.create(\n", - " model=model,\n", - " messages=messages,\n", - " temperature=0, # 模型输出的温度系数,控制输出的随机程度\n", - " )\n", - " # 调用 OpenAI 的 ChatCompletion 接口\n", - " return response.choices[0].message[\"content\"]\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 二、两个基本原则" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 原则一:编写清晰、具体的指令\n", - "\n", - "您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.1 使用分隔符清晰地表示输入的不同部分**\n", - "\n", - "分隔符可以是:```,\"\",<>,:,\\ \\等。\n", - "\n", - "您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n", - "\n", - "在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# 中文版见下一个 cell\n", - "text = f\"\"\"\n", - "You should express what you want a model to do by \\ \n", - "providing instructions that are as clear and \\ \n", - "specific as you can possibly make them. \\ \n", - "This will guide the model towards the desired output, \\ \n", - "and reduce the chances of receiving irrelevant \\ \n", - "or incorrect responses. Don't confuse writing a \\ \n", - "clear prompt with writing a short prompt. \\ \n", - "In many cases, longer prompts provide more clarity \\ \n", - "and context for the model, which can lead to \\ \n", - "more detailed and relevant outputs.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "Summarize the text delimited by triple backticks \\ \n", - "into a single sentence.\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "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", - "prompt = f\"\"\"\n", - "把用三个反引号括起来的文本总结成一句话。\n", - "```{text}```\n", - "\"\"\"\n", - "# 指令内容,使用 ``` 来分隔指令和待总结的内容\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.2 寻求结构化的输出**\n", - "\n", - "输出可以是 Json、HTML 等格式。\n", - "\n", - "第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n", - "\n", - "在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Lost City of Zorath\",\n", - " \"author\": \"Aria Blackwood\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Last Survivors\",\n", - " \"author\": \"Ethan Stone\",\n", - " \"genre\": \"Science Fiction\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Secret Life of Bees\",\n", - " \"author\": \"Lila Rose\",\n", - " \"genre\": \"Romance\"\n", - " }\n", - "]\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Generate a list of three made-up book titles along \\ \n", - "with their authors and genres. \n", - "Provide them in JSON format with the following keys: \n", - "book_id, title, author, genre.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"books\": [\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Shadow of the Wind\",\n", - " \"author\": \"Carlos Ruiz Zafón\",\n", - " \"genre\": \"Mystery\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Name of the Wind\",\n", - " \"author\": \"Patrick Rothfuss\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Hitchhiker's Guide to the Galaxy\",\n", - " \"author\": \"Douglas Adams\",\n", - " \"genre\": \"Science Fiction\"\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请生成包括书名、作者和类别的三本虚构书籍清单,\\\n", - "并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.3 要求模型检查是否满足条件**\n", - "\n", - "如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n", - "\n", - "在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 1:\n", - "Step 1 - Get some water boiling.\n", - "Step 2 - Grab a cup and put a tea bag in it.\n", - "Step 3 - Once the water is hot enough, pour it over the tea bag.\n", - "Step 4 - Let it sit for a bit so the tea can steep.\n", - "Step 5 - After a few minutes, take out the tea bag.\n", - "Step 6 - Add some sugar or milk to taste.\n", - "Step 7 - Enjoy your delicious cup of tea!\n", - "\n", - "\n" - ] - } - ], - "source": [ - "text_1 = f\"\"\"\n", - "Making a cup of tea is easy! First, you need to get some \\ \n", - "water boiling. While that's happening, \\ \n", - "grab a cup and put a tea bag in it. Once the water is \\ \n", - "hot enough, just pour it over the tea bag. \\ \n", - "Let it sit for a bit so the tea can steep. After a \\ \n", - "few minutes, take out the tea bag. If you \\ \n", - "like, you can add some sugar or milk to taste. \\ \n", - "And that's it! You've got yourself a delicious \\ \n", - "cup of tea to enjoy.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 2:\n", - "No steps provided.\n" - ] - } - ], - "source": [ - "text_2 = f\"\"\"\n", - "The sun is shining brightly today, and the birds are \\\n", - "singing. It's a beautiful day to go for a \\ \n", - "walk in the park. The flowers are blooming, and the \\ \n", - "trees are swaying gently in the breeze. People \\ \n", - "are out and about, enjoying the lovely weather. \\ \n", - "Some are having picnics, while others are playing \\ \n", - "games or simply relaxing on the grass. It's a \\ \n", - "perfect day to spend time outdoors and appreciate the \\ \n", - "beauty of nature.\n", - "\"\"\"\n", - "prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 1 的总结:\n", - "第一步 - 把水烧开。\n", - "第二步 - 拿一个杯子并把茶包放进去。\n", - "第三步 - 把烧开的水倒在茶包上。\n", - "第四步 - 等待几分钟,让茶叶浸泡。\n", - "第五步 - 取出茶包。\n", - "第六步 - 如果你愿意,可以加一些糖或牛奶调味。\n", - "第七步 - 就这样,你可以享受一杯美味的茶了。\n" - ] - } - ], - "source": [ - "# 满足条件的输入(text中提供了步骤)\n", - "text_1 = f\"\"\"\n", - "泡一杯茶很容易。首先,需要把水烧开。\\\n", - "在等待期间,拿一个杯子并把茶包放进去。\\\n", - "一旦水足够热,就把它倒在茶包上。\\\n", - "等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n", - "如果您愿意,可以加一些糖或牛奶调味。\\\n", - "就这样,您可以享受一杯美味的茶了。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 1 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 2 的总结:\n", - "未提供步骤。\n" - ] - } - ], - "source": [ - "# 不满足条件的输入(text中未提供预期指令)\n", - "text_2 = f\"\"\"\n", - "今天阳光明媚,鸟儿在歌唱。\\\n", - "这是一个去公园散步的美好日子。\\\n", - "鲜花盛开,树枝在微风中轻轻摇曳。\\\n", - "人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n", - "这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 2 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.4 提供少量示例**(少样本提示词,Few-shot prompting)\n", - "\n", - "即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n", - "\n", - "例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - ": 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.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to answer in a consistent style.\n", - "\n", - ": Teach me about patience.\n", - "\n", - ": The river that carves the deepest \\ \n", - "valley flows from a modest spring; the \\ \n", - "grandest symphony originates from a single note; \\ \n", - "the most intricate tapestry begins with a solitary thread.\n", - "\n", - ": Teach me about resilience.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。在生活中,我们也需要经历各种挫折和困难,才能锻炼出韧性。记住,不要轻易放弃,坚持下去,你会发现自己变得更加坚强。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "您的任务是以一致的风格回答问题。\n", - "\n", - "<孩子>: 教我耐心。\n", - "\n", - "<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n", - "\n", - "<孩子>: 教我韧性。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 给模型时间去思考\n", - "\n", - "如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.1 指定完成任务所需的步骤**\n", - "\n", - "接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和人名个数。要求输出以换行符分隔。" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for prompt 1:\n", - "Two siblings, Jack and Jill, go on a quest to fetch water from a well on a hilltop, but misfortune strikes and they both tumble down the hill, returning home slightly battered but with their adventurous spirits undimmed.\n", - "\n", - "Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts. \n", - "Noms: Jack, Jill.\n", - "\n", - "{\n", - " \"french_summary\": \"Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "In a charming village, siblings Jack and Jill set out on \\ \n", - "a quest to fetch water from a hilltop \\ \n", - "well. As they climbed, singing joyfully, misfortune \\ \n", - "struck—Jack tripped on a stone and tumbled \\ \n", - "down the hill, with Jill following suit. \\ \n", - "Though slightly battered, the pair returned home to \\ \n", - "comforting embraces. Despite the mishap, \\ \n", - "their adventurous spirits remained undimmed, and they \\ \n", - "continued exploring with delight.\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "Perform the following actions: \n", - "1 - Summarize the following text delimited by triple \\\n", - "backticks with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the following \\\n", - "keys: french_summary, num_names.\n", - "\n", - "Separate your answers with line breaks.\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"Completion for prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "prompt 1:\n", - "1-兄妹在山顶井里打水时发生意外,但仍然保持冒险精神。\n", - "2-Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\n", - "3-Jack, Jill\n", - "4-{\n", - " \"French_summary\": \"Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n", - "他们一边唱着欢乐的歌,一边往上爬,\\\n", - "然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n", - "虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n", - "尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "执行以下操作:\n", - "1-用一句话概括下面用三个反引号括起来的文本。\n", - "2-将摘要翻译成法语。\n", - "3-在法语摘要中列出每个人名。\n", - "4-输出一个 JSON 对象,其中包含以下键:French_summary,num_names。\n", - "\n", - "请用换行符分隔您的答案。\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n", - "\n", - "因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Completion for prompt 2:\n", - "Summary: 兄妹杰克和吉尔在山顶井里打水时发生意外,但他们仍然保持冒险精神继续探索。\n", - "Translation: Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\n", - "Names: Jack, Jill\n", - "Output JSON: {\"french_summary\": \"Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\", \"num_names\": 2}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "Your task is to perform the following actions: \n", - "1 - Summarize the following text delimited by <> with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the \n", - "following keys: french_summary, num_names.\n", - "\n", - "Use the following format:\n", - "Text: \n", - "Summary: \n", - "Translation: \n", - "Names: \n", - "Output JSON: \n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nCompletion for prompt 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "prompt 2:\n", - "摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。\n", - "翻译: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.\n", - "名称:Jack,Jill\n", - "输出 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}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "1-用一句话概括下面用<>括起来的文本。\n", - "2-将摘要翻译成英语。\n", - "3-在英语摘要中列出每个名称。\n", - "4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n", - "\n", - "请使用以下格式:\n", - "文本:<要总结的文本>\n", - "摘要:<摘要>\n", - "翻译:<摘要的翻译>\n", - "名称:<英语摘要中的名称列表>\n", - "输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nprompt 2:\")\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.2 指导模型在下结论之前找出一个自己的解法**\n", - "\n", - "明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n", - "\n", - "接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The student's solution is correct.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Determine if the student's solution is correct or not.\n", - "\n", - "Question:\n", - "I'm building a solar power installation and I need \\\n", - " help working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\ \n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \n", - "as a function of the number of square feet.\n", - "\n", - "Student's Solution:\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "学生的解决方案是正确的。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "判断学生的解决方案是否正确。\n", - "\n", - "问题:\n", - "我正在建造一个太阳能发电站,需要帮助计算财务。\n", - "\n", - " 土地费用为 100美元/平方英尺\n", - " 我可以以 250美元/平方英尺的价格购买太阳能电池板\n", - " 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "设x为发电站的大小,单位为平方英尺。\n", - "费用:\n", - "\n", - " 土地费用:100x\n", - " 太阳能电池板费用:250x\n", - " 维护费用:100,000美元+100x\n", - " 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n", - "\n", - "我们可以通过指导模型先自行找出一个解法来解决这个问题。\n", - "\n", - "在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Let x be the size of the installation in square feet.\n", - "\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 10x\n", - "\n", - "Total cost: 100x + 250x + 100,000 + 10x = 360x + 100,000\n", - "\n", - "Is the student's solution the same as actual solution just calculated:\n", - "No\n", - "\n", - "Student grade:\n", - "Incorrect\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to determine if the student's solution \\\n", - "is correct or not.\n", - "To solve the problem do the following:\n", - "- First, work out your own solution to the problem. \n", - "- Then compare your solution to the student's solution \\ \n", - "and evaluate if the student's solution is correct or not. \n", - "Don't decide if the student's solution is correct until \n", - "you have done the problem yourself.\n", - "\n", - "Use the following format:\n", - "Question:\n", - "```\n", - "question here\n", - "```\n", - "Student's solution:\n", - "```\n", - "student's solution here\n", - "```\n", - "Actual solution:\n", - "```\n", - "steps to work out the solution and your solution here\n", - "```\n", - "Is the student's solution the same as actual solution \\\n", - "just calculated:\n", - "```\n", - "yes or no\n", - "```\n", - "Student grade:\n", - "```\n", - "correct or incorrect\n", - "```\n", - "\n", - "Question:\n", - "```\n", - "I'm building a solar power installation and I need help \\\n", - "working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\\n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \\\n", - "as a function of the number of square feet.\n", - "``` \n", - "Student's solution:\n", - "```\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "```\n", - "Actual solution:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "正确的解决方案和步骤:\n", - " 1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元\n", - " 2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元\n", - " 3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元\n", - " 4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元\n", - "\n", - "学生的解决方案和实际解决方案是否相同:否\n", - "\n", - "学生的成绩:不正确\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n", - "\n", - "步骤:\n", - "\n", - " 首先,自己解决问题。\n", - " 然后将您的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。\n", - " 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n", - "\n", - "使用以下格式:\n", - "\n", - " 问题:问题文本\n", - " 学生的解决方案:学生的解决方案文本\n", - " 实际解决方案和步骤:实际解决方案和步骤文本\n", - " 学生的解决方案和实际解决方案是否相同:是或否\n", - " 学生的成绩:正确或不正确\n", - "\n", - "问题:\n", - "\n", - " 我正在建造一个太阳能发电站,需要帮助计算财务。 \n", - " - 土地费用为每平方英尺100美元\n", - " - 我可以以每平方英尺250美元的价格购买太阳能电池板\n", - " - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "\n", - " 设x为发电站的大小,单位为平方英尺。\n", - " 费用:\n", - " 1. 土地费用:100x\n", - " 2. 太阳能电池板费用:250x\n", - " 3. 维护费用:100,000+100x\n", - " 总费用:100x+250x+100,000+100x=450x+100,000\n", - "\n", - "实际解决方案和步骤:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 三、局限性" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**开发大模型相关应用时请务必铭记:**\n", - "\n", - "\n", - "**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n", - "\n", - "虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n", - "\n", - "如下示例展示了大模型的幻觉。我们要求告诉我们 Boie 公司生产的 *AeroGlide UltraSlim Smart Toothbrush* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The AeroGlide UltraSlim Smart Toothbrush by Boie is a high-tech toothbrush that uses advanced sonic technology to provide a deep and thorough clean. It features a slim and sleek design that makes it easy to hold and maneuver, and it comes with a range of smart features that help you optimize your brushing routine.\n", - "\n", - "One of the key features of the AeroGlide UltraSlim Smart Toothbrush is its advanced sonic technology, which uses high-frequency vibrations to break up plaque and bacteria on your teeth and gums. This technology is highly effective at removing even the toughest stains and buildup, leaving your teeth feeling clean and fresh.\n", - "\n", - "In addition to its sonic technology, the AeroGlide UltraSlim Smart Toothbrush also comes with a range of smart features that help you optimize your brushing routine. These include a built-in timer that ensures you brush for the recommended two minutes, as well as a pressure sensor that alerts you if you're brushing too hard.\n", - "\n", - "Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie is a highly advanced and effective toothbrush that is perfect for anyone looking to take their oral hygiene to the next level. With its advanced sonic technology and smart features, it provides a deep and thorough clean that leaves your teeth feeling fresh and healthy.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款智能牙刷,具有以下特点:\n", - "\n", - "1. 超薄设计:刷头仅有0.8毫米的厚度,可以更容易地进入口腔深处,清洁更彻底。\n", - "\n", - "2. 智能感应:牙刷配备了智能感应技术,可以自动识别刷头的位置和方向,确保每个部位都得到充分的清洁。\n", - "\n", - "3. 高效清洁:牙刷采用了高速振动技术,每分钟可达到40000次,可以有效去除牙菌斑和污渍。\n", - "\n", - "4. 轻松携带:牙刷采用了便携式设计,可以轻松放入口袋或旅行包中,随时随地进行口腔清洁。\n", - "\n", - "5. 环保材料:牙刷采用了环保材料制造,不含有害物质,对环境友好。\n", - "\n", - "总之,Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款高效、智能、环保的牙刷,可以帮助用户轻松保持口腔健康。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "告诉我 Boie 公司生产的 AeroGlide UltraSlim Smart Toothbrush 的相关信息\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n", - "\n", - "在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**关于反斜杠使用的说明:**\n", - "\n", - "在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - }, - "latex_envs": { - "LaTeX_envs_menu_present": true, - "autoclose": false, - "autocomplete": true, - "bibliofile": "biblio.bib", - "cite_by": "apalike", - "current_citInitial": 1, - "eqLabelWithNumbers": true, - "eqNumInitial": 1, - "hotkeys": { - "equation": "Ctrl-E", - "itemize": "Ctrl-I" - }, - "labels_anchors": false, - "latex_user_defs": false, - "report_style_numbering": false, - "user_envs_cfg": false - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells":[{"attachments":{},"cell_type":"markdown","metadata":{},"source":["# 第二章 提示原则 Guidelines\n","\n"," - [一、原则一 编写清晰、具体的指令](#一、原则一-编写清晰、具体的指令)\n"," - [1.1 使用分隔符清晰地表示输入的不同部分](#1.1-使用分隔符清晰地表示输入的不同部分)\n"," - [1.2 寻求结构化的输出](#1.2-寻求结构化的输出)\n"," - [1.3 要求模型检查是否满足条件](#1.3-要求模型检查是否满足条件)\n"," - [1.4 提供少量示例](#1.4-提供少量示例)\n"," - [二、原则二 给模型时间去思考](#二、原则二-给模型时间去思考)\n"," - [2.1 指定完成任务所需的步骤](#2.1-指定完成任务所需的步骤)\n"," - [2.2 指导模型在下结论之前找出一个自己的解法](#2.2-指导模型在下结论之前找出一个自己的解法)\n"," - [三、局限性](#三、局限性)\n"," - [四、英文原版 Prompt](#四、英文原版-Prompt)\n"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。"]},{"cell_type":"markdown","metadata":{},"source":["### 1.1 使用分隔符清晰地表示输入的不同部分"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","分隔符可以是:```,\"\",<>,:,\\ \\等。\n","\n","您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n","\n","在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n"]},{"cell_type":"code","execution_count":11,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["为了获得所需的输出,您应该提供清晰、具体的指示,避免与简短的提示词混淆,并使用更长的提示词来提供更多的清晰度和上下文信息。\n"]}],"source":["text = f\"\"\"\n","您应该提供尽可能清晰、具体的指示,以表达您希望模型执行的任务。\\\n","这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\\\n","不要将写清晰的提示词与写简短的提示词混淆。\\\n","在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n","\"\"\"\n","# 需要总结的文本内容\n","prompt = f\"\"\"\n","把用三个反引号括起来的文本总结成一句话。\n","```{text}```\n","\"\"\"\n","# 指令内容,使用 ``` 来分隔指令和待总结的内容\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["### 1.2 寻求结构化的输出"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","输出可以是 Json、HTML 等格式。\n","\n","第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n","\n","在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"]},{"cell_type":"code","execution_count":15,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"迷失的时光\",\n"," \"author\": \"张三\",\n"," \"genre\": \"科幻\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"幻境之门\",\n"," \"author\": \"李四\",\n"," \"genre\": \"奇幻\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"虚拟现实\",\n"," \"author\": \"王五\",\n"," \"genre\": \"科幻\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","请生成包括书名、作者和类别的三本虚构的、非真实存在的中文书籍清单,\\\n","并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.3 要求模型检查是否满足条件"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n","\n","在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。"]},{"cell_type":"code","execution_count":16,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 1 的总结:\n","第一步 - 把水烧开。\n","第二步 - 拿一个杯子并把茶包放进去。\n","第三步 - 把烧开的水倒在茶包上。\n","第四步 - 等待几分钟,让茶叶浸泡。\n","第五步 - 取出茶包。\n","第六步 - 如果需要,加入糖或牛奶调味。\n","第七步 - 就这样,您可以享受一杯美味的茶了。\n"]}],"source":["# 满足条件的输入(text中提供了步骤)\n","text_1 = f\"\"\"\n","泡一杯茶很容易。首先,需要把水烧开。\\\n","在等待期间,拿一个杯子并把茶包放进去。\\\n","一旦水足够热,就把它倒在茶包上。\\\n","等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n","如果您愿意,可以加一些糖或牛奶调味。\\\n","就这样,您可以享受一杯美味的茶了。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 1 的总结:\")\n","print(response)"]},{"cell_type":"code","execution_count":17,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 2 的总结:\n","未提供步骤。\n"]}],"source":["# 不满足条件的输入(text中未提供预期指令)\n","text_2 = f\"\"\"\n","今天阳光明媚,鸟儿在歌唱。\\\n","这是一个去公园散步的美好日子。\\\n","鲜花盛开,树枝在微风中轻轻摇曳。\\\n","人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n","这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 2 的总结:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.4 提供少量示例"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n","\n","例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。"]},{"cell_type":"code","execution_count":22,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["<祖父母>: 韧性是一种坚持不懈的品质,就像一棵顽强的树在风雨中屹立不倒。它是面对困难和挑战时不屈不挠的精神,能够适应变化和克服逆境。韧性是一种内在的力量,让我们能够坚持追求目标,即使面临困难和挫折也能坚持不懈地努力。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是以一致的风格回答问题。\n","\n","<孩子>: 请教我何为耐心。\n","\n","<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n","\n","<孩子>: 请教我何为韧性。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 二、原则二 给模型时间去思考\n","\n","如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。"]},{"cell_type":"markdown","metadata":{},"source":["### 2.1 指定完成任务所需的步骤"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。"]},{"cell_type":"code","execution_count":28,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["prompt 1:\n","1-两个兄妹在山上打水时发生意外,但最终平安回家。\n","2-In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\n","3-Jack, Jill\n","4-{\"english_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\", \"num_names\": 2}\n"]}],"source":["text = f\"\"\"\n","在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n","他们一边唱着欢乐的歌,一边往上爬,\\\n","然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n","虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n","尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","执行以下操作:\n","1-用一句话概括下面用三个反引号括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个人名。\n","4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。\n","\n","请用换行符分隔您的答案。\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"prompt 1:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,要求从英语翻译到法语,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n","\n","因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","prompt 2:\n","Summary: 在一个迷人的村庄里,兄妹杰克和吉尔在山顶井里打水时发生了意外,但他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\n","Translation: In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\n","\n","Names: Jack, Jill\n","\n","JSON Output: {\"English_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\", \"num_names\": 2}\n"]}],"source":["prompt_2 = f\"\"\"\n","1-用一句话概括下面用<>括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个名称。\n","4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n","\n","请使用以下格式:\n","文本:<要总结的文本>\n","摘要:<摘要>\n","翻译:<摘要的翻译>\n","名称:<英语摘要中的名称列表>\n","输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nprompt 2:\")\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":[" "]},{"cell_type":"markdown","metadata":{},"source":["### 2.2 指导模型在下结论之前找出一个自己的解法"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n","\n","接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:"]},{"cell_type":"code","execution_count":30,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["学生的解决方案是正确的。他正确地计算了土地费用、太阳能电池板费用和维护费用,并将它们相加得到了总费用。\n"]}],"source":["prompt = f\"\"\"\n","判断学生的解决方案是否正确。\n","\n","问题:\n","我正在建造一个太阳能发电站,需要帮助计算财务。\n","\n"," 土地费用为 100美元/平方英尺\n"," 我可以以 250美元/平方英尺的价格购买太阳能电池板\n"," 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","设x为发电站的大小,单位为平方英尺。\n","费用:\n","\n"," 土地费用:100x\n"," 太阳能电池板费用:250x\n"," 维护费用:100,000美元+100x\n"," 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n","\n","我们可以通过指导模型先自行找出一个解法来解决这个问题。\n","\n","在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"]},{"cell_type":"code","execution_count":40,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["实际解决方案和步骤:\n","\n"," 1. 土地费用:每平方英尺100美元,所以总费用为100x美元。\n"," 2. 太阳能电池板费用:每平方英尺250美元,所以总费用为250x美元。\n"," 3. 维护费用:固定费用为10万美元,额外费用为每平方英尺10美元,所以总费用为10万美元+10x美元。\n"," 4. 总费用:将上述三项费用相加,得到总费用为100x美元+250x美元+10万美元+10x美元=360x+10万美元。\n","\n","学生计算的总费用:450x+10万美元\n","实际计算的总费用:360x+10万美元\n","学生计算的费用和实际计算的费用是否相同:否\n","学生的解决方案和实际解决方案是否相同:否\n","学生的成绩:不正确\n"]}],"source":["prompt = f\"\"\"\n","请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n","\n","步骤:\n","\n"," 首先,自己解决问题。\n"," 然后将您的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。\n"," 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n","\n","使用以下格式:\n","\n"," 问题:问题文本\n"," 学生的解决方案:学生的解决方案文本\n"," 实际解决方案和步骤:实际解决方案和步骤文本\n"," 学生计算的总费用:学生计算得到的总费用\n"," 实际计算的总费用:实际计算出的总费用\n"," 学生计算的费用和实际计算的费用是否相同:是或否\n"," 学生的解决方案和实际解决方案是否相同:是或否\n"," 学生的成绩:正确或不正确\n","\n","问题:\n","\n"," 我正在建造一个太阳能发电站,需要帮助计算财务。 \n"," - 土地费用为每平方英尺100美元\n"," - 我可以以每平方英尺250美元的价格购买太阳能电池板\n"," - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元;\n","\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","\n"," 设x为发电站的大小,单位为平方英尺。\n"," 费用:\n"," 1. 土地费用:100x美元\n"," 2. 太阳能电池板费用:250x美元\n"," 3. 维护费用:100,000+100x=10万美元+10x美元\n"," 总费用:100x美元+250x美元+10万美元+100x美元=450x+10万美元\n","\n","实际解决方案和步骤:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 三、局限性"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**开发大模型相关应用时请务必铭记:**\n","\n","\n","**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n","\n","虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n","\n","如下示例展示了大模型的幻觉。我们要求告诉我们华为公司生产的 *GT Watch 运动手表* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n","\n"]},{"cell_type":"code","execution_count":44,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["华为公司生产的GT Watch运动手表是一款智能手表,具有多种功能和特点。以下是相关信息:\n","\n","1. 设计和外观:GT Watch采用圆形表盘设计,具有精致的外观和高质量的材料制造。它有多种颜色和表带选择,可以根据个人喜好进行定制。\n","\n","2. 显示屏:GT Watch配备了1.39英寸的AMOLED显示屏,具有高清分辨率和良好的可视性。用户可以通过触摸屏幕进行操作和导航。\n","\n","3. 运动追踪:GT Watch具有全天候的运动追踪功能,可以监测用户的步数、跑步距离、卡路里消耗和心率等数据。它还支持多种运动模式,如跑步、骑行、游泳等。\n","\n","4. 健康监测:GT Watch可以监测用户的心率、血氧饱和度和睡眠质量等健康指标。它还提供健康建议和提醒,帮助用户保持良好的健康状态。\n","\n","5. 通知和连接:GT Watch可以与用户的手机进行连接,通过蓝牙技术实现通知推送和电话提醒。用户可以在手表上查看短信、电话和社交媒体通知,无需拿出手机。\n","\n","6. 长续航时间:GT Watch具有较长的续航时间,一次充电可以使用数天。它还支持快速充电技术,可以在短时间内充满电。\n","\n","7. 其他功能:GT Watch还具有其他功能,如天气预报、闹钟、计时器、计步器等。它还支持NFC支付和音乐控制等便利功能。\n","\n","总体而言,华为GT Watch是一款功能强大、外观精致的智能运动手表,适合那些注重健康和运动的用户使用。\n"]}],"source":["prompt = f\"\"\"\n","告诉我华为公司生产的GT Watch运动手表的相关信息\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n","\n","在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**关于反斜杠使用的说明:**\n","\n","在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。"]},{"cell_type":"markdown","metadata":{},"source":["## 四、英文原版 Prompt"]},{"cell_type":"markdown","metadata":{},"source":["**1.1 使用分隔符清晰地表示输入的不同部分**"]},{"cell_type":"code","execution_count":45,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To guide a model towards the desired output and reduce irrelevant or incorrect responses, it is important to provide clear and specific instructions, which can be achieved through longer prompts that offer more clarity and context.\n"]}],"source":["text = f\"\"\"\n","You should express what you want a model to do by \\ \n","providing instructions that are as clear and \\ \n","specific as you can possibly make them. \\ \n","This will guide the model towards the desired output, \\ \n","and reduce the chances of receiving irrelevant \\ \n","or incorrect responses. Don't confuse writing a \\ \n","clear prompt with writing a short prompt. \\ \n","In many cases, longer prompts provide more clarity \\ \n","and context for the model, which can lead to \\ \n","more detailed and relevant outputs.\n","\"\"\"\n","prompt = f\"\"\"\n","Summarize the text delimited by triple backticks \\ \n","into a single sentence.\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.2**寻求结构化的输出"]},{"cell_type":"code","execution_count":46,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"The Enigma of Elysium\",\n"," \"author\": \"Evelyn Sinclair\",\n"," \"genre\": \"Mystery\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"Whispers in the Wind\",\n"," \"author\": \"Nathaniel Blackwood\",\n"," \"genre\": \"Fantasy\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"Echoes of the Past\",\n"," \"author\": \"Amelia Hart\",\n"," \"genre\": \"Romance\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","Generate a list of three made-up book titles along \\ \n","with their authors and genres. \n","Provide them in JSON format with the following keys: \n","book_id, title, author, genre.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":["**1.3 要求模型检查是否满足条件**"]},{"cell_type":"code","execution_count":56,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 1:\n","Step 1 - Get some water boiling.\n","Step 2 - Grab a cup and put a tea bag in it.\n","Step 3 - Once the water is hot enough, pour it over the tea bag.\n","Step 4 - Let it sit for a bit so the tea can steep.\n","Step 5 - After a few minutes, take out the tea bag.\n","Step 6 - If you like, add some sugar or milk to taste.\n","Step 7 - Enjoy your delicious cup of tea.\n"]}],"source":["text_1 = f\"\"\"\n","Making a cup of tea is easy! First, you need to get some \\ \n","water boiling. While that's happening, \\ \n","grab a cup and put a tea bag in it. Once the water is \\ \n","hot enough, just pour it over the tea bag. \\ \n","Let it sit for a bit so the tea can steep. After a \\ \n","few minutes, take out the tea bag. If you \\ \n","like, you can add some sugar or milk to taste. \\ \n","And that's it! You've got yourself a delicious \\ \n","cup of tea to enjoy.\n","\"\"\"\n","prompt = f\"\"\"\n","You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":48,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 2:\n","No steps provided.\n"]}],"source":["text_2 = f\"\"\"\n","The sun is shining brightly today, and the birds are \\\n","singing. It's a beautiful day to go for a \\ \n","walk in the park. The flowers are blooming, and the \\ \n","trees are swaying gently in the breeze. People \\ \n","are out and about, enjoying the lovely weather. \\ \n","Some are having picnics, while others are playing \\ \n","games or simply relaxing on the grass. It's a \\ \n","perfect day to spend time outdoors and appreciate the \\ \n","beauty of nature.\n","\"\"\"\n","prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.4 提供少量示例**(少样本提示词,Few-shot prompting)"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":[": Resilience is like a mighty oak tree that withstands the strongest storms, bending but never breaking. It is the unwavering determination to rise again after every fall, and the ability to find strength in the face of adversity. Just as a diamond is formed under immense pressure, resilience is forged through challenges and hardships, making us stronger and more resilient in the process.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to answer in a consistent style.\n","\n",": Teach me about patience.\n","\n",": The river that carves the deepest \\ \n","valley flows from a modest spring; the \\ \n","grandest symphony originates from a single note; \\ \n","the most intricate tapestry begins with a solitary thread.\n","\n",": Teach me about resilience.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.1 指定完成任务所需的步骤**"]},{"cell_type":"code","execution_count":50,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for prompt 1:\n","1 - Jack and Jill, siblings, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they return home and remain undeterred in their adventurous spirits.\n","\n","2 - Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\n","\n","3 - Jack, Jill\n","\n","4 - {\n"," \"french_summary\": \"Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["text = f\"\"\"\n","In a charming village, siblings Jack and Jill set out on \\ \n","a quest to fetch water from a hilltop \\ \n","well. As they climbed, singing joyfully, misfortune \\ \n","struck—Jack tripped on a stone and tumbled \\ \n","down the hill, with Jill following suit. \\ \n","Though slightly battered, the pair returned home to \\ \n","comforting embraces. Despite the mishap, \\ \n","their adventurous spirits remained undimmed, and they \\ \n","continued exploring with delight.\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","Perform the following actions: \n","1 - Summarize the following text delimited by triple \\\n","backticks with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the following \\\n","keys: french_summary, num_names.\n","\n","Separate your answers with line breaks.\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"Completion for prompt 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":51,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","Completion for prompt 2:\n","Summary: Jack and Jill, siblings from a charming village, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they remain undeterred and continue exploring with delight.\n","\n","Translation: Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\n","\n","Names: Jack, Jill\n","\n","Output JSON: \n","{\n"," \"french_summary\": \"Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["prompt_2 = f\"\"\"\n","Your task is to perform the following actions: \n","1 - Summarize the following text delimited by <> with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the \n","following keys: french_summary, num_names.\n","\n","Use the following format:\n","Text: \n","Summary: \n","Translation: \n","Names: \n","Output JSON: \n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nCompletion for prompt 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.2 指导模型在下结论之前找出一个自己的解法**"]},{"cell_type":"code","execution_count":52,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The student's solution is correct. They correctly identified the costs for land, solar panels, and maintenance, and calculated the total cost for the first year of operations as a function of the number of square feet.\n"]}],"source":["prompt = f\"\"\"\n","Determine if the student's solution is correct or not.\n","\n","Question:\n","I'm building a solar power installation and I need \\\n"," help working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\ \n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \n","as a function of the number of square feet.\n","\n","Student's Solution:\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"code","execution_count":53,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To calculate the total cost for the first year of operations, we need to add up the costs of land, solar panels, and maintenance.\n","\n","1. Land cost: $100 / square foot\n","The cost of land is $100 multiplied by the number of square feet.\n","\n","2. Solar panel cost: $250 / square foot\n","The cost of solar panels is $250 multiplied by the number of square feet.\n","\n","3. Maintenance cost: $100,000 + $10 / square foot\n","The maintenance cost is a flat fee of $100,000 per year, plus $10 multiplied by the number of square feet.\n","\n","Total cost: Land cost + Solar panel cost + Maintenance cost\n","\n","So the actual solution is:\n","Total cost = (100 * x) + (250 * x) + (100,000 + (10 * x))\n","\n","Is the student's solution the same as the actual solution just calculated:\n","No\n","\n","Student grade:\n","Incorrect\n"]}],"source":["prompt = f\"\"\"\n","Your task is to determine if the student's solution \\\n","is correct or not.\n","To solve the problem do the following:\n","- First, work out your own solution to the problem. \n","- Then compare your solution to the student's solution \\ \n","and evaluate if the student's solution is correct or not. \n","Don't decide if the student's solution is correct until \n","you have done the problem yourself.\n","\n","Use the following format:\n","Question:\n","```\n","question here\n","```\n","Student's solution:\n","```\n","student's solution here\n","```\n","Actual solution:\n","```\n","steps to work out the solution and your solution here\n","```\n","Is the student's solution the same as actual solution \\\n","just calculated:\n","```\n","yes or no\n","```\n","Student grade:\n","```\n","correct or incorrect\n","```\n","\n","Question:\n","```\n","I'm building a solar power installation and I need help \\\n","working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\\n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \\\n","as a function of the number of square feet.\n","``` \n","Student's solution:\n","```\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","```\n","Actual solution:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**3.1 幻觉**"]},{"cell_type":"code","execution_count":54,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The AeroGlide UltraSlim Smart Toothbrush by Boie is a technologically advanced toothbrush designed to provide a superior brushing experience. Boie is a company known for its innovative oral care products, and the AeroGlide UltraSlim Smart Toothbrush is no exception.\n","\n","One of the standout features of this toothbrush is its ultra-slim design. The brush head is only 2mm thick, making it much thinner than traditional toothbrushes. This slim profile allows for better access to hard-to-reach areas of the mouth, ensuring a thorough and effective clean.\n","\n","The AeroGlide UltraSlim Smart Toothbrush also incorporates smart technology. It connects to a mobile app via Bluetooth, allowing users to track their brushing habits and receive personalized recommendations for improving their oral hygiene routine. The app provides real-time feedback on brushing technique, duration, and coverage, helping users to achieve optimal oral health.\n","\n","The toothbrush features soft, antimicrobial bristles made from a durable thermoplastic elastomer. These bristles are gentle on the gums and teeth, while also being effective at removing plaque and debris. The antimicrobial properties help to keep the brush head clean and hygienic between uses.\n","\n","Another notable feature of the AeroGlide UltraSlim Smart Toothbrush is its long battery life. It can last up to 30 days on a single charge, making it convenient for travel or everyday use without the need for frequent recharging.\n","\n","Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie offers a combination of advanced technology, slim design, and effective cleaning capabilities. It is a great option for those looking to upgrade their oral care routine and achieve a healthier smile.\n"]}],"source":["prompt = f\"\"\"\n","Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":4} diff --git a/content/Prompt Engineering for Developer/do_contents.py b/content/Prompt Engineering for Developer/do_contents.py new file mode 100644 index 0000000..87a11d3 --- /dev/null +++ b/content/Prompt Engineering for Developer/do_contents.py @@ -0,0 +1,33 @@ +import os +import codecs +import json + +def add_toc(ipynb_file): + f = codecs.open(ipynb_file, 'r') + source = f.read() + y = json.loads(source) + toc = ["\n"] + for item in y["cells"]: + if item["cell_type"]=='markdown': + if len(item["source"]) == 0: + continue + # print(item["source"]) + + item_start = item['source'][0].strip("\n") + if item_start.startswith("#"): + l = len(item_start.split()[0]) + if l<=3 and l>1: + name = " ".join(item_start.split(" ")[1:]) + tag = "-".join(item_start.split(" ")[1:]) + tab = " "*(l-2) + toc.append(f' {tab}- [{name}](#{tag})\n') + + y["cells"][0]['source']= y["cells"][0]['source'][0:1] + y["cells"][0]['source'].extend(toc) + f = codecs.open(ipynb_file, 'w') + f.write(json.dumps(y)) + f.close() + +for file in os.listdir("."): + if file.endswith("ipynb") and file[0].isdigit(): + add_toc(file) \ No newline at end of file From a8a68d4d83eec02bda80433356c90c2044e92b35 Mon Sep 17 00:00:00 2001 From: nowadays0421 Date: Tue, 18 Jul 2023 11:07:32 +0800 Subject: [PATCH 05/13] Finish PE 2 --- .../2. 提示原则 Guidelines.ipynb | 1239 +---------------- .../do_contents.py | 33 + 2 files changed, 34 insertions(+), 1238 deletions(-) create mode 100644 content/Prompt Engineering for Developer/do_contents.py diff --git a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb index cf339f7..74d0eaf 100644 --- a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb +++ b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb @@ -1,1238 +1 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 第二章 编写 Prompt 的原则\n", - "\n", - " 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,您可以练习编写高效的 Prompt,从而便捷而有效地使用 LLM。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " \n", - "
" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 一、环境配置" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "本教程使用 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": [ - "首先需要安装 OpenAI 库:\n", - "```bash\n", - "pip install openai\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "# 导入第三方库\n", - "\n", - "openai.api_key = \"sk-...\"\n", - "# 设置 API_KEY, 请替换成您自己的 API_KEY\n", - "\n", - "# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。\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": [ - "整个课程将以 gpt-3.5-turbo 模型为例。我们将在后续课程中深入探究 OpenAI 提供的 [Chat Completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 的使用方法,在此处,我们先将它封装成一个函数,您无需知道其内部机理,仅需知道调用该函数,以 Prompt 为输入参数,其将会输出对应的 Completion (回答结果)即可。" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# 一个封装 OpenAI 接口的函数,参数为 Prompt,返回对应结果\n", - "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", - " '''\n", - " prompt: 对应的提示词\n", - " model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4\n", - " '''\n", - " messages = [{\"role\": \"user\", \"content\": prompt}]\n", - " response = openai.ChatCompletion.create(\n", - " model=model,\n", - " messages=messages,\n", - " temperature=0, # 模型输出的温度系数,控制输出的随机程度\n", - " )\n", - " # 调用 OpenAI 的 ChatCompletion 接口\n", - " return response.choices[0].message[\"content\"]\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 二、两个基本原则" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 原则一:编写清晰、具体的指令\n", - "\n", - "您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.1 使用分隔符清晰地表示输入的不同部分**\n", - "\n", - "分隔符可以是:```,\"\",<>,:,\\ \\等。\n", - "\n", - "您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n", - "\n", - "在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# 中文版见下一个 cell\n", - "text = f\"\"\"\n", - "You should express what you want a model to do by \\ \n", - "providing instructions that are as clear and \\ \n", - "specific as you can possibly make them. \\ \n", - "This will guide the model towards the desired output, \\ \n", - "and reduce the chances of receiving irrelevant \\ \n", - "or incorrect responses. Don't confuse writing a \\ \n", - "clear prompt with writing a short prompt. \\ \n", - "In many cases, longer prompts provide more clarity \\ \n", - "and context for the model, which can lead to \\ \n", - "more detailed and relevant outputs.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "Summarize the text delimited by triple backticks \\ \n", - "into a single sentence.\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "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", - "prompt = f\"\"\"\n", - "把用三个反引号括起来的文本总结成一句话。\n", - "```{text}```\n", - "\"\"\"\n", - "# 指令内容,使用 ``` 来分隔指令和待总结的内容\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.2 寻求结构化的输出**\n", - "\n", - "输出可以是 Json、HTML 等格式。\n", - "\n", - "第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n", - "\n", - "在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Lost City of Zorath\",\n", - " \"author\": \"Aria Blackwood\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Last Survivors\",\n", - " \"author\": \"Ethan Stone\",\n", - " \"genre\": \"Science Fiction\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Secret Life of Bees\",\n", - " \"author\": \"Lila Rose\",\n", - " \"genre\": \"Romance\"\n", - " }\n", - "]\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Generate a list of three made-up book titles along \\ \n", - "with their authors and genres. \n", - "Provide them in JSON format with the following keys: \n", - "book_id, title, author, genre.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"books\": [\n", - " {\n", - " \"book_id\": 1,\n", - " \"title\": \"The Shadow of the Wind\",\n", - " \"author\": \"Carlos Ruiz Zafón\",\n", - " \"genre\": \"Mystery\"\n", - " },\n", - " {\n", - " \"book_id\": 2,\n", - " \"title\": \"The Name of the Wind\",\n", - " \"author\": \"Patrick Rothfuss\",\n", - " \"genre\": \"Fantasy\"\n", - " },\n", - " {\n", - " \"book_id\": 3,\n", - " \"title\": \"The Hitchhiker's Guide to the Galaxy\",\n", - " \"author\": \"Douglas Adams\",\n", - " \"genre\": \"Science Fiction\"\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请生成包括书名、作者和类别的三本虚构书籍清单,\\\n", - "并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.3 要求模型检查是否满足条件**\n", - "\n", - "如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n", - "\n", - "在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 1:\n", - "Step 1 - Get some water boiling.\n", - "Step 2 - Grab a cup and put a tea bag in it.\n", - "Step 3 - Once the water is hot enough, pour it over the tea bag.\n", - "Step 4 - Let it sit for a bit so the tea can steep.\n", - "Step 5 - After a few minutes, take out the tea bag.\n", - "Step 6 - Add some sugar or milk to taste.\n", - "Step 7 - Enjoy your delicious cup of tea!\n", - "\n", - "\n" - ] - } - ], - "source": [ - "text_1 = f\"\"\"\n", - "Making a cup of tea is easy! First, you need to get some \\ \n", - "water boiling. While that's happening, \\ \n", - "grab a cup and put a tea bag in it. Once the water is \\ \n", - "hot enough, just pour it over the tea bag. \\ \n", - "Let it sit for a bit so the tea can steep. After a \\ \n", - "few minutes, take out the tea bag. If you \\ \n", - "like, you can add some sugar or milk to taste. \\ \n", - "And that's it! You've got yourself a delicious \\ \n", - "cup of tea to enjoy.\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for Text 2:\n", - "No steps provided.\n" - ] - } - ], - "source": [ - "text_2 = f\"\"\"\n", - "The sun is shining brightly today, and the birds are \\\n", - "singing. It's a beautiful day to go for a \\ \n", - "walk in the park. The flowers are blooming, and the \\ \n", - "trees are swaying gently in the breeze. People \\ \n", - "are out and about, enjoying the lovely weather. \\ \n", - "Some are having picnics, while others are playing \\ \n", - "games or simply relaxing on the grass. It's a \\ \n", - "perfect day to spend time outdoors and appreciate the \\ \n", - "beauty of nature.\n", - "\"\"\"\n", - "prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n", - "If it contains a sequence of instructions, \\ \n", - "re-write those instructions in the following format:\n", - "Step 1 - ...\n", - "Step 2 - …\n", - "…\n", - "Step N - …\n", - "\n", - "If the text does not contain a sequence of instructions, \\ \n", - "then simply write \\\"No steps provided.\\\"\n", - "\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Completion for Text 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 1 的总结:\n", - "第一步 - 把水烧开。\n", - "第二步 - 拿一个杯子并把茶包放进去。\n", - "第三步 - 把烧开的水倒在茶包上。\n", - "第四步 - 等待几分钟,让茶叶浸泡。\n", - "第五步 - 取出茶包。\n", - "第六步 - 如果你愿意,可以加一些糖或牛奶调味。\n", - "第七步 - 就这样,你可以享受一杯美味的茶了。\n" - ] - } - ], - "source": [ - "# 满足条件的输入(text中提供了步骤)\n", - "text_1 = f\"\"\"\n", - "泡一杯茶很容易。首先,需要把水烧开。\\\n", - "在等待期间,拿一个杯子并把茶包放进去。\\\n", - "一旦水足够热,就把它倒在茶包上。\\\n", - "等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n", - "如果您愿意,可以加一些糖或牛奶调味。\\\n", - "就这样,您可以享受一杯美味的茶了。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 1 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Text 2 的总结:\n", - "未提供步骤。\n" - ] - } - ], - "source": [ - "# 不满足条件的输入(text中未提供预期指令)\n", - "text_2 = f\"\"\"\n", - "今天阳光明媚,鸟儿在歌唱。\\\n", - "这是一个去公园散步的美好日子。\\\n", - "鲜花盛开,树枝在微风中轻轻摇曳。\\\n", - "人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n", - "这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n", - "\"\"\"\n", - "prompt = f\"\"\"\n", - "您将获得由三个引号括起来的文本。\\\n", - "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", - "\n", - "第一步 - ...\n", - "第二步 - …\n", - "…\n", - "第N步 - …\n", - "\n", - "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", - "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(\"Text 2 的总结:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1.4 提供少量示例**(少样本提示词,Few-shot prompting)\n", - "\n", - "即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n", - "\n", - "例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - ": 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.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to answer in a consistent style.\n", - "\n", - ": Teach me about patience.\n", - "\n", - ": The river that carves the deepest \\ \n", - "valley flows from a modest spring; the \\ \n", - "grandest symphony originates from a single note; \\ \n", - "the most intricate tapestry begins with a solitary thread.\n", - "\n", - ": Teach me about resilience.\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。在生活中,我们也需要经历各种挫折和困难,才能锻炼出韧性。记住,不要轻易放弃,坚持下去,你会发现自己变得更加坚强。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "您的任务是以一致的风格回答问题。\n", - "\n", - "<孩子>: 教我耐心。\n", - "\n", - "<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n", - "\n", - "<孩子>: 教我韧性。\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 给模型时间去思考\n", - "\n", - "如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.1 指定完成任务所需的步骤**\n", - "\n", - "接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和人名个数。要求输出以换行符分隔。" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Completion for prompt 1:\n", - "Two siblings, Jack and Jill, go on a quest to fetch water from a well on a hilltop, but misfortune strikes and they both tumble down the hill, returning home slightly battered but with their adventurous spirits undimmed.\n", - "\n", - "Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts. \n", - "Noms: Jack, Jill.\n", - "\n", - "{\n", - " \"french_summary\": \"Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "In a charming village, siblings Jack and Jill set out on \\ \n", - "a quest to fetch water from a hilltop \\ \n", - "well. As they climbed, singing joyfully, misfortune \\ \n", - "struck—Jack tripped on a stone and tumbled \\ \n", - "down the hill, with Jill following suit. \\ \n", - "Though slightly battered, the pair returned home to \\ \n", - "comforting embraces. Despite the mishap, \\ \n", - "their adventurous spirits remained undimmed, and they \\ \n", - "continued exploring with delight.\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "Perform the following actions: \n", - "1 - Summarize the following text delimited by triple \\\n", - "backticks with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the following \\\n", - "keys: french_summary, num_names.\n", - "\n", - "Separate your answers with line breaks.\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"Completion for prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "prompt 1:\n", - "1-兄妹在山顶井里打水时发生意外,但仍然保持冒险精神。\n", - "2-Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\n", - "3-Jack, Jill\n", - "4-{\n", - " \"French_summary\": \"Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\",\n", - " \"num_names\": 2\n", - "}\n" - ] - } - ], - "source": [ - "text = f\"\"\"\n", - "在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n", - "他们一边唱着欢乐的歌,一边往上爬,\\\n", - "然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n", - "虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n", - "尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n", - "\"\"\"\n", - "# example 1\n", - "prompt_1 = f\"\"\"\n", - "执行以下操作:\n", - "1-用一句话概括下面用三个反引号括起来的文本。\n", - "2-将摘要翻译成法语。\n", - "3-在法语摘要中列出每个人名。\n", - "4-输出一个 JSON 对象,其中包含以下键:French_summary,num_names。\n", - "\n", - "请用换行符分隔您的答案。\n", - "\n", - "Text:\n", - "```{text}```\n", - "\"\"\"\n", - "response = get_completion(prompt_1)\n", - "print(\"prompt 1:\")\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n", - "\n", - "因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Completion for prompt 2:\n", - "Summary: 兄妹杰克和吉尔在山顶井里打水时发生意外,但他们仍然保持冒险精神继续探索。\n", - "Translation: Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\n", - "Names: Jack, Jill\n", - "Output JSON: {\"french_summary\": \"Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\", \"num_names\": 2}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "Your task is to perform the following actions: \n", - "1 - Summarize the following text delimited by <> with 1 sentence.\n", - "2 - Translate the summary into French.\n", - "3 - List each name in the French summary.\n", - "4 - Output a json object that contains the \n", - "following keys: french_summary, num_names.\n", - "\n", - "Use the following format:\n", - "Text: \n", - "Summary: \n", - "Translation: \n", - "Names: \n", - "Output JSON: \n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nCompletion for prompt 2:\")\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "prompt 2:\n", - "摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。\n", - "翻译: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.\n", - "名称:Jack,Jill\n", - "输出 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}\n" - ] - } - ], - "source": [ - "prompt_2 = f\"\"\"\n", - "1-用一句话概括下面用<>括起来的文本。\n", - "2-将摘要翻译成英语。\n", - "3-在英语摘要中列出每个名称。\n", - "4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n", - "\n", - "请使用以下格式:\n", - "文本:<要总结的文本>\n", - "摘要:<摘要>\n", - "翻译:<摘要的翻译>\n", - "名称:<英语摘要中的名称列表>\n", - "输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n", - "\n", - "Text: <{text}>\n", - "\"\"\"\n", - "response = get_completion(prompt_2)\n", - "print(\"\\nprompt 2:\")\n", - "print(response)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.2.2 指导模型在下结论之前找出一个自己的解法**\n", - "\n", - "明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n", - "\n", - "接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The student's solution is correct.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Determine if the student's solution is correct or not.\n", - "\n", - "Question:\n", - "I'm building a solar power installation and I need \\\n", - " help working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\ \n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \n", - "as a function of the number of square feet.\n", - "\n", - "Student's Solution:\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "学生的解决方案是正确的。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "判断学生的解决方案是否正确。\n", - "\n", - "问题:\n", - "我正在建造一个太阳能发电站,需要帮助计算财务。\n", - "\n", - " 土地费用为 100美元/平方英尺\n", - " 我可以以 250美元/平方英尺的价格购买太阳能电池板\n", - " 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "设x为发电站的大小,单位为平方英尺。\n", - "费用:\n", - "\n", - " 土地费用:100x\n", - " 太阳能电池板费用:250x\n", - " 维护费用:100,000美元+100x\n", - " 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n", - "\n", - "我们可以通过指导模型先自行找出一个解法来解决这个问题。\n", - "\n", - "在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Let x be the size of the installation in square feet.\n", - "\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 10x\n", - "\n", - "Total cost: 100x + 250x + 100,000 + 10x = 360x + 100,000\n", - "\n", - "Is the student's solution the same as actual solution just calculated:\n", - "No\n", - "\n", - "Student grade:\n", - "Incorrect\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Your task is to determine if the student's solution \\\n", - "is correct or not.\n", - "To solve the problem do the following:\n", - "- First, work out your own solution to the problem. \n", - "- Then compare your solution to the student's solution \\ \n", - "and evaluate if the student's solution is correct or not. \n", - "Don't decide if the student's solution is correct until \n", - "you have done the problem yourself.\n", - "\n", - "Use the following format:\n", - "Question:\n", - "```\n", - "question here\n", - "```\n", - "Student's solution:\n", - "```\n", - "student's solution here\n", - "```\n", - "Actual solution:\n", - "```\n", - "steps to work out the solution and your solution here\n", - "```\n", - "Is the student's solution the same as actual solution \\\n", - "just calculated:\n", - "```\n", - "yes or no\n", - "```\n", - "Student grade:\n", - "```\n", - "correct or incorrect\n", - "```\n", - "\n", - "Question:\n", - "```\n", - "I'm building a solar power installation and I need help \\\n", - "working out the financials. \n", - "- Land costs $100 / square foot\n", - "- I can buy solar panels for $250 / square foot\n", - "- I negotiated a contract for maintenance that will cost \\\n", - "me a flat $100k per year, and an additional $10 / square \\\n", - "foot\n", - "What is the total cost for the first year of operations \\\n", - "as a function of the number of square feet.\n", - "``` \n", - "Student's solution:\n", - "```\n", - "Let x be the size of the installation in square feet.\n", - "Costs:\n", - "1. Land cost: 100x\n", - "2. Solar panel cost: 250x\n", - "3. Maintenance cost: 100,000 + 100x\n", - "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", - "```\n", - "Actual solution:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "正确的解决方案和步骤:\n", - " 1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元\n", - " 2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元\n", - " 3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元\n", - " 4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元\n", - "\n", - "学生的解决方案和实际解决方案是否相同:否\n", - "\n", - "学生的成绩:不正确\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n", - "\n", - "步骤:\n", - "\n", - " 首先,自己解决问题。\n", - " 然后将您的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。\n", - " 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n", - "\n", - "使用以下格式:\n", - "\n", - " 问题:问题文本\n", - " 学生的解决方案:学生的解决方案文本\n", - " 实际解决方案和步骤:实际解决方案和步骤文本\n", - " 学生的解决方案和实际解决方案是否相同:是或否\n", - " 学生的成绩:正确或不正确\n", - "\n", - "问题:\n", - "\n", - " 我正在建造一个太阳能发电站,需要帮助计算财务。 \n", - " - 土地费用为每平方英尺100美元\n", - " - 我可以以每平方英尺250美元的价格购买太阳能电池板\n", - " - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", - " 作为平方英尺数的函数,首年运营的总费用是多少。\n", - "\n", - "学生的解决方案:\n", - "\n", - " 设x为发电站的大小,单位为平方英尺。\n", - " 费用:\n", - " 1. 土地费用:100x\n", - " 2. 太阳能电池板费用:250x\n", - " 3. 维护费用:100,000+100x\n", - " 总费用:100x+250x+100,000+100x=450x+100,000\n", - "\n", - "实际解决方案和步骤:\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 三、局限性" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**开发大模型相关应用时请务必铭记:**\n", - "\n", - "\n", - "**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n", - "\n", - "虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n", - "\n", - "如下示例展示了大模型的幻觉。我们要求告诉我们 Boie 公司生产的 *AeroGlide UltraSlim Smart Toothbrush* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The AeroGlide UltraSlim Smart Toothbrush by Boie is a high-tech toothbrush that uses advanced sonic technology to provide a deep and thorough clean. It features a slim and sleek design that makes it easy to hold and maneuver, and it comes with a range of smart features that help you optimize your brushing routine.\n", - "\n", - "One of the key features of the AeroGlide UltraSlim Smart Toothbrush is its advanced sonic technology, which uses high-frequency vibrations to break up plaque and bacteria on your teeth and gums. This technology is highly effective at removing even the toughest stains and buildup, leaving your teeth feeling clean and fresh.\n", - "\n", - "In addition to its sonic technology, the AeroGlide UltraSlim Smart Toothbrush also comes with a range of smart features that help you optimize your brushing routine. These include a built-in timer that ensures you brush for the recommended two minutes, as well as a pressure sensor that alerts you if you're brushing too hard.\n", - "\n", - "Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie is a highly advanced and effective toothbrush that is perfect for anyone looking to take their oral hygiene to the next level. With its advanced sonic technology and smart features, it provides a deep and thorough clean that leaves your teeth feeling fresh and healthy.\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款智能牙刷,具有以下特点:\n", - "\n", - "1. 超薄设计:刷头仅有0.8毫米的厚度,可以更容易地进入口腔深处,清洁更彻底。\n", - "\n", - "2. 智能感应:牙刷配备了智能感应技术,可以自动识别刷头的位置和方向,确保每个部位都得到充分的清洁。\n", - "\n", - "3. 高效清洁:牙刷采用了高速振动技术,每分钟可达到40000次,可以有效去除牙菌斑和污渍。\n", - "\n", - "4. 轻松携带:牙刷采用了便携式设计,可以轻松放入口袋或旅行包中,随时随地进行口腔清洁。\n", - "\n", - "5. 环保材料:牙刷采用了环保材料制造,不含有害物质,对环境友好。\n", - "\n", - "总之,Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款高效、智能、环保的牙刷,可以帮助用户轻松保持口腔健康。\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "告诉我 Boie 公司生产的 AeroGlide UltraSlim Smart Toothbrush 的相关信息\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n", - "\n", - "在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**关于反斜杠使用的说明:**\n", - "\n", - "在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - }, - "latex_envs": { - "LaTeX_envs_menu_present": true, - "autoclose": false, - "autocomplete": true, - "bibliofile": "biblio.bib", - "cite_by": "apalike", - "current_citInitial": 1, - "eqLabelWithNumbers": true, - "eqNumInitial": 1, - "hotkeys": { - "equation": "Ctrl-E", - "itemize": "Ctrl-I" - }, - "labels_anchors": false, - "latex_user_defs": false, - "report_style_numbering": false, - "user_envs_cfg": false - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells":[{"attachments":{},"cell_type":"markdown","metadata":{},"source":["# 第二章 提示原则 Guidelines\n","\n"," - [一、原则一 编写清晰、具体的指令](#一、原则一-编写清晰、具体的指令)\n"," - [1.1 使用分隔符清晰地表示输入的不同部分](#1.1-使用分隔符清晰地表示输入的不同部分)\n"," - [1.2 寻求结构化的输出](#1.2-寻求结构化的输出)\n"," - [1.3 要求模型检查是否满足条件](#1.3-要求模型检查是否满足条件)\n"," - [1.4 提供少量示例](#1.4-提供少量示例)\n"," - [二、原则二 给模型时间去思考](#二、原则二-给模型时间去思考)\n"," - [2.1 指定完成任务所需的步骤](#2.1-指定完成任务所需的步骤)\n"," - [2.2 指导模型在下结论之前找出一个自己的解法](#2.2-指导模型在下结论之前找出一个自己的解法)\n"," - [三、局限性](#三、局限性)\n"," - [四、英文原版 Prompt](#四、英文原版-Prompt)\n"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。"]},{"cell_type":"markdown","metadata":{},"source":["### 1.1 使用分隔符清晰地表示输入的不同部分"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","分隔符可以是:```,\"\",<>,:,\\ \\等。\n","\n","您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n","\n","在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n"]},{"cell_type":"code","execution_count":11,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["为了获得所需的输出,您应该提供清晰、具体的指示,避免与简短的提示词混淆,并使用更长的提示词来提供更多的清晰度和上下文信息。\n"]}],"source":["text = f\"\"\"\n","您应该提供尽可能清晰、具体的指示,以表达您希望模型执行的任务。\\\n","这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\\\n","不要将写清晰的提示词与写简短的提示词混淆。\\\n","在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n","\"\"\"\n","# 需要总结的文本内容\n","prompt = f\"\"\"\n","把用三个反引号括起来的文本总结成一句话。\n","```{text}```\n","\"\"\"\n","# 指令内容,使用 ``` 来分隔指令和待总结的内容\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["### 1.2 寻求结构化的输出"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","输出可以是 Json、HTML 等格式。\n","\n","第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n","\n","在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"]},{"cell_type":"code","execution_count":15,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"迷失的时光\",\n"," \"author\": \"张三\",\n"," \"genre\": \"科幻\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"幻境之门\",\n"," \"author\": \"李四\",\n"," \"genre\": \"奇幻\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"虚拟现实\",\n"," \"author\": \"王五\",\n"," \"genre\": \"科幻\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","请生成包括书名、作者和类别的三本虚构的、非真实存在的中文书籍清单,\\\n","并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.3 要求模型检查是否满足条件"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n","\n","在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。"]},{"cell_type":"code","execution_count":16,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 1 的总结:\n","第一步 - 把水烧开。\n","第二步 - 拿一个杯子并把茶包放进去。\n","第三步 - 把烧开的水倒在茶包上。\n","第四步 - 等待几分钟,让茶叶浸泡。\n","第五步 - 取出茶包。\n","第六步 - 如果需要,加入糖或牛奶调味。\n","第七步 - 就这样,您可以享受一杯美味的茶了。\n"]}],"source":["# 满足条件的输入(text中提供了步骤)\n","text_1 = f\"\"\"\n","泡一杯茶很容易。首先,需要把水烧开。\\\n","在等待期间,拿一个杯子并把茶包放进去。\\\n","一旦水足够热,就把它倒在茶包上。\\\n","等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n","如果您愿意,可以加一些糖或牛奶调味。\\\n","就这样,您可以享受一杯美味的茶了。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 1 的总结:\")\n","print(response)"]},{"cell_type":"code","execution_count":17,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 2 的总结:\n","未提供步骤。\n"]}],"source":["# 不满足条件的输入(text中未提供预期指令)\n","text_2 = f\"\"\"\n","今天阳光明媚,鸟儿在歌唱。\\\n","这是一个去公园散步的美好日子。\\\n","鲜花盛开,树枝在微风中轻轻摇曳。\\\n","人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n","这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 2 的总结:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.4 提供少量示例"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n","\n","例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。"]},{"cell_type":"code","execution_count":22,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["<祖父母>: 韧性是一种坚持不懈的品质,就像一棵顽强的树在风雨中屹立不倒。它是面对困难和挑战时不屈不挠的精神,能够适应变化和克服逆境。韧性是一种内在的力量,让我们能够坚持追求目标,即使面临困难和挫折也能坚持不懈地努力。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是以一致的风格回答问题。\n","\n","<孩子>: 请教我何为耐心。\n","\n","<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n","\n","<孩子>: 请教我何为韧性。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 二、原则二 给模型时间去思考\n","\n","如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。"]},{"cell_type":"markdown","metadata":{},"source":["### 2.1 指定完成任务所需的步骤"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。"]},{"cell_type":"code","execution_count":28,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["prompt 1:\n","1-两个兄妹在山上打水时发生意外,但最终平安回家。\n","2-In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\n","3-Jack, Jill\n","4-{\"english_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\", \"num_names\": 2}\n"]}],"source":["text = f\"\"\"\n","在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n","他们一边唱着欢乐的歌,一边往上爬,\\\n","然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n","虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n","尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","执行以下操作:\n","1-用一句话概括下面用三个反引号括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个人名。\n","4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。\n","\n","请用换行符分隔您的答案。\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"prompt 1:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,要求从英语翻译到法语,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n","\n","因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","prompt 2:\n","Summary: 在一个迷人的村庄里,兄妹杰克和吉尔在山顶井里打水时发生了意外,但他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\n","Translation: In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\n","\n","Names: Jack, Jill\n","\n","JSON Output: {\"English_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\", \"num_names\": 2}\n"]}],"source":["prompt_2 = f\"\"\"\n","1-用一句话概括下面用<>括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个名称。\n","4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n","\n","请使用以下格式:\n","文本:<要总结的文本>\n","摘要:<摘要>\n","翻译:<摘要的翻译>\n","名称:<英语摘要中的名称列表>\n","输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nprompt 2:\")\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":[" "]},{"cell_type":"markdown","metadata":{},"source":["### 2.2 指导模型在下结论之前找出一个自己的解法"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n","\n","接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:"]},{"cell_type":"code","execution_count":30,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["学生的解决方案是正确的。他正确地计算了土地费用、太阳能电池板费用和维护费用,并将它们相加得到了总费用。\n"]}],"source":["prompt = f\"\"\"\n","判断学生的解决方案是否正确。\n","\n","问题:\n","我正在建造一个太阳能发电站,需要帮助计算财务。\n","\n"," 土地费用为 100美元/平方英尺\n"," 我可以以 250美元/平方英尺的价格购买太阳能电池板\n"," 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","设x为发电站的大小,单位为平方英尺。\n","费用:\n","\n"," 土地费用:100x\n"," 太阳能电池板费用:250x\n"," 维护费用:100,000美元+100x\n"," 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n","\n","我们可以通过指导模型先自行找出一个解法来解决这个问题。\n","\n","在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"]},{"cell_type":"code","execution_count":40,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["实际解决方案和步骤:\n","\n"," 1. 土地费用:每平方英尺100美元,所以总费用为100x美元。\n"," 2. 太阳能电池板费用:每平方英尺250美元,所以总费用为250x美元。\n"," 3. 维护费用:固定费用为10万美元,额外费用为每平方英尺10美元,所以总费用为10万美元+10x美元。\n"," 4. 总费用:将上述三项费用相加,得到总费用为100x美元+250x美元+10万美元+10x美元=360x+10万美元。\n","\n","学生计算的总费用:450x+10万美元\n","实际计算的总费用:360x+10万美元\n","学生计算的费用和实际计算的费用是否相同:否\n","学生的解决方案和实际解决方案是否相同:否\n","学生的成绩:不正确\n"]}],"source":["prompt = f\"\"\"\n","请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n","\n","步骤:\n","\n"," 首先,自己解决问题。\n"," 然后将您的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。\n"," 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n","\n","使用以下格式:\n","\n"," 问题:问题文本\n"," 学生的解决方案:学生的解决方案文本\n"," 实际解决方案和步骤:实际解决方案和步骤文本\n"," 学生计算的总费用:学生计算得到的总费用\n"," 实际计算的总费用:实际计算出的总费用\n"," 学生计算的费用和实际计算的费用是否相同:是或否\n"," 学生的解决方案和实际解决方案是否相同:是或否\n"," 学生的成绩:正确或不正确\n","\n","问题:\n","\n"," 我正在建造一个太阳能发电站,需要帮助计算财务。 \n"," - 土地费用为每平方英尺100美元\n"," - 我可以以每平方英尺250美元的价格购买太阳能电池板\n"," - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元;\n","\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","\n"," 设x为发电站的大小,单位为平方英尺。\n"," 费用:\n"," 1. 土地费用:100x美元\n"," 2. 太阳能电池板费用:250x美元\n"," 3. 维护费用:100,000+100x=10万美元+10x美元\n"," 总费用:100x美元+250x美元+10万美元+100x美元=450x+10万美元\n","\n","实际解决方案和步骤:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 三、局限性"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**开发大模型相关应用时请务必铭记:**\n","\n","\n","**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n","\n","虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n","\n","如下示例展示了大模型的幻觉。我们要求告诉我们华为公司生产的 *GT Watch 运动手表* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n","\n"]},{"cell_type":"code","execution_count":44,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["华为公司生产的GT Watch运动手表是一款智能手表,具有多种功能和特点。以下是相关信息:\n","\n","1. 设计和外观:GT Watch采用圆形表盘设计,具有精致的外观和高质量的材料制造。它有多种颜色和表带选择,可以根据个人喜好进行定制。\n","\n","2. 显示屏:GT Watch配备了1.39英寸的AMOLED显示屏,具有高清分辨率和良好的可视性。用户可以通过触摸屏幕进行操作和导航。\n","\n","3. 运动追踪:GT Watch具有全天候的运动追踪功能,可以监测用户的步数、跑步距离、卡路里消耗和心率等数据。它还支持多种运动模式,如跑步、骑行、游泳等。\n","\n","4. 健康监测:GT Watch可以监测用户的心率、血氧饱和度和睡眠质量等健康指标。它还提供健康建议和提醒,帮助用户保持良好的健康状态。\n","\n","5. 通知和连接:GT Watch可以与用户的手机进行连接,通过蓝牙技术实现通知推送和电话提醒。用户可以在手表上查看短信、电话和社交媒体通知,无需拿出手机。\n","\n","6. 长续航时间:GT Watch具有较长的续航时间,一次充电可以使用数天。它还支持快速充电技术,可以在短时间内充满电。\n","\n","7. 其他功能:GT Watch还具有其他功能,如天气预报、闹钟、计时器、计步器等。它还支持NFC支付和音乐控制等便利功能。\n","\n","总体而言,华为GT Watch是一款功能强大、外观精致的智能运动手表,适合那些注重健康和运动的用户使用。\n"]}],"source":["prompt = f\"\"\"\n","告诉我华为公司生产的GT Watch运动手表的相关信息\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n","\n","在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**关于反斜杠使用的说明:**\n","\n","在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。"]},{"cell_type":"markdown","metadata":{},"source":["## 四、英文原版 Prompt"]},{"cell_type":"markdown","metadata":{},"source":["**1.1 使用分隔符清晰地表示输入的不同部分**"]},{"cell_type":"code","execution_count":45,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To guide a model towards the desired output and reduce irrelevant or incorrect responses, it is important to provide clear and specific instructions, which can be achieved through longer prompts that offer more clarity and context.\n"]}],"source":["text = f\"\"\"\n","You should express what you want a model to do by \\ \n","providing instructions that are as clear and \\ \n","specific as you can possibly make them. \\ \n","This will guide the model towards the desired output, \\ \n","and reduce the chances of receiving irrelevant \\ \n","or incorrect responses. Don't confuse writing a \\ \n","clear prompt with writing a short prompt. \\ \n","In many cases, longer prompts provide more clarity \\ \n","and context for the model, which can lead to \\ \n","more detailed and relevant outputs.\n","\"\"\"\n","prompt = f\"\"\"\n","Summarize the text delimited by triple backticks \\ \n","into a single sentence.\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.2**寻求结构化的输出"]},{"cell_type":"code","execution_count":46,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"The Enigma of Elysium\",\n"," \"author\": \"Evelyn Sinclair\",\n"," \"genre\": \"Mystery\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"Whispers in the Wind\",\n"," \"author\": \"Nathaniel Blackwood\",\n"," \"genre\": \"Fantasy\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"Echoes of the Past\",\n"," \"author\": \"Amelia Hart\",\n"," \"genre\": \"Romance\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","Generate a list of three made-up book titles along \\ \n","with their authors and genres. \n","Provide them in JSON format with the following keys: \n","book_id, title, author, genre.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":["**1.3 要求模型检查是否满足条件**"]},{"cell_type":"code","execution_count":56,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 1:\n","Step 1 - Get some water boiling.\n","Step 2 - Grab a cup and put a tea bag in it.\n","Step 3 - Once the water is hot enough, pour it over the tea bag.\n","Step 4 - Let it sit for a bit so the tea can steep.\n","Step 5 - After a few minutes, take out the tea bag.\n","Step 6 - If you like, add some sugar or milk to taste.\n","Step 7 - Enjoy your delicious cup of tea.\n"]}],"source":["text_1 = f\"\"\"\n","Making a cup of tea is easy! First, you need to get some \\ \n","water boiling. While that's happening, \\ \n","grab a cup and put a tea bag in it. Once the water is \\ \n","hot enough, just pour it over the tea bag. \\ \n","Let it sit for a bit so the tea can steep. After a \\ \n","few minutes, take out the tea bag. If you \\ \n","like, you can add some sugar or milk to taste. \\ \n","And that's it! You've got yourself a delicious \\ \n","cup of tea to enjoy.\n","\"\"\"\n","prompt = f\"\"\"\n","You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":48,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 2:\n","No steps provided.\n"]}],"source":["text_2 = f\"\"\"\n","The sun is shining brightly today, and the birds are \\\n","singing. It's a beautiful day to go for a \\ \n","walk in the park. The flowers are blooming, and the \\ \n","trees are swaying gently in the breeze. People \\ \n","are out and about, enjoying the lovely weather. \\ \n","Some are having picnics, while others are playing \\ \n","games or simply relaxing on the grass. It's a \\ \n","perfect day to spend time outdoors and appreciate the \\ \n","beauty of nature.\n","\"\"\"\n","prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.4 提供少量示例**(少样本提示词,Few-shot prompting)"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":[": Resilience is like a mighty oak tree that withstands the strongest storms, bending but never breaking. It is the unwavering determination to rise again after every fall, and the ability to find strength in the face of adversity. Just as a diamond is formed under immense pressure, resilience is forged through challenges and hardships, making us stronger and more resilient in the process.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to answer in a consistent style.\n","\n",": Teach me about patience.\n","\n",": The river that carves the deepest \\ \n","valley flows from a modest spring; the \\ \n","grandest symphony originates from a single note; \\ \n","the most intricate tapestry begins with a solitary thread.\n","\n",": Teach me about resilience.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.1 指定完成任务所需的步骤**"]},{"cell_type":"code","execution_count":50,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for prompt 1:\n","1 - Jack and Jill, siblings, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they return home and remain undeterred in their adventurous spirits.\n","\n","2 - Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\n","\n","3 - Jack, Jill\n","\n","4 - {\n"," \"french_summary\": \"Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["text = f\"\"\"\n","In a charming village, siblings Jack and Jill set out on \\ \n","a quest to fetch water from a hilltop \\ \n","well. As they climbed, singing joyfully, misfortune \\ \n","struck—Jack tripped on a stone and tumbled \\ \n","down the hill, with Jill following suit. \\ \n","Though slightly battered, the pair returned home to \\ \n","comforting embraces. Despite the mishap, \\ \n","their adventurous spirits remained undimmed, and they \\ \n","continued exploring with delight.\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","Perform the following actions: \n","1 - Summarize the following text delimited by triple \\\n","backticks with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the following \\\n","keys: french_summary, num_names.\n","\n","Separate your answers with line breaks.\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"Completion for prompt 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":51,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","Completion for prompt 2:\n","Summary: Jack and Jill, siblings from a charming village, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they remain undeterred and continue exploring with delight.\n","\n","Translation: Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\n","\n","Names: Jack, Jill\n","\n","Output JSON: \n","{\n"," \"french_summary\": \"Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["prompt_2 = f\"\"\"\n","Your task is to perform the following actions: \n","1 - Summarize the following text delimited by <> with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the \n","following keys: french_summary, num_names.\n","\n","Use the following format:\n","Text: \n","Summary: \n","Translation: \n","Names: \n","Output JSON: \n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nCompletion for prompt 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.2 指导模型在下结论之前找出一个自己的解法**"]},{"cell_type":"code","execution_count":52,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The student's solution is correct. They correctly identified the costs for land, solar panels, and maintenance, and calculated the total cost for the first year of operations as a function of the number of square feet.\n"]}],"source":["prompt = f\"\"\"\n","Determine if the student's solution is correct or not.\n","\n","Question:\n","I'm building a solar power installation and I need \\\n"," help working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\ \n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \n","as a function of the number of square feet.\n","\n","Student's Solution:\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"code","execution_count":53,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To calculate the total cost for the first year of operations, we need to add up the costs of land, solar panels, and maintenance.\n","\n","1. Land cost: $100 / square foot\n","The cost of land is $100 multiplied by the number of square feet.\n","\n","2. Solar panel cost: $250 / square foot\n","The cost of solar panels is $250 multiplied by the number of square feet.\n","\n","3. Maintenance cost: $100,000 + $10 / square foot\n","The maintenance cost is a flat fee of $100,000 per year, plus $10 multiplied by the number of square feet.\n","\n","Total cost: Land cost + Solar panel cost + Maintenance cost\n","\n","So the actual solution is:\n","Total cost = (100 * x) + (250 * x) + (100,000 + (10 * x))\n","\n","Is the student's solution the same as the actual solution just calculated:\n","No\n","\n","Student grade:\n","Incorrect\n"]}],"source":["prompt = f\"\"\"\n","Your task is to determine if the student's solution \\\n","is correct or not.\n","To solve the problem do the following:\n","- First, work out your own solution to the problem. \n","- Then compare your solution to the student's solution \\ \n","and evaluate if the student's solution is correct or not. \n","Don't decide if the student's solution is correct until \n","you have done the problem yourself.\n","\n","Use the following format:\n","Question:\n","```\n","question here\n","```\n","Student's solution:\n","```\n","student's solution here\n","```\n","Actual solution:\n","```\n","steps to work out the solution and your solution here\n","```\n","Is the student's solution the same as actual solution \\\n","just calculated:\n","```\n","yes or no\n","```\n","Student grade:\n","```\n","correct or incorrect\n","```\n","\n","Question:\n","```\n","I'm building a solar power installation and I need help \\\n","working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\\n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \\\n","as a function of the number of square feet.\n","``` \n","Student's solution:\n","```\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","```\n","Actual solution:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**3.1 幻觉**"]},{"cell_type":"code","execution_count":54,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The AeroGlide UltraSlim Smart Toothbrush by Boie is a technologically advanced toothbrush designed to provide a superior brushing experience. Boie is a company known for its innovative oral care products, and the AeroGlide UltraSlim Smart Toothbrush is no exception.\n","\n","One of the standout features of this toothbrush is its ultra-slim design. The brush head is only 2mm thick, making it much thinner than traditional toothbrushes. This slim profile allows for better access to hard-to-reach areas of the mouth, ensuring a thorough and effective clean.\n","\n","The AeroGlide UltraSlim Smart Toothbrush also incorporates smart technology. It connects to a mobile app via Bluetooth, allowing users to track their brushing habits and receive personalized recommendations for improving their oral hygiene routine. The app provides real-time feedback on brushing technique, duration, and coverage, helping users to achieve optimal oral health.\n","\n","The toothbrush features soft, antimicrobial bristles made from a durable thermoplastic elastomer. These bristles are gentle on the gums and teeth, while also being effective at removing plaque and debris. The antimicrobial properties help to keep the brush head clean and hygienic between uses.\n","\n","Another notable feature of the AeroGlide UltraSlim Smart Toothbrush is its long battery life. It can last up to 30 days on a single charge, making it convenient for travel or everyday use without the need for frequent recharging.\n","\n","Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie offers a combination of advanced technology, slim design, and effective cleaning capabilities. It is a great option for those looking to upgrade their oral care routine and achieve a healthier smile.\n"]}],"source":["prompt = f\"\"\"\n","Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":4} diff --git a/content/Prompt Engineering for Developer/do_contents.py b/content/Prompt Engineering for Developer/do_contents.py new file mode 100644 index 0000000..87a11d3 --- /dev/null +++ b/content/Prompt Engineering for Developer/do_contents.py @@ -0,0 +1,33 @@ +import os +import codecs +import json + +def add_toc(ipynb_file): + f = codecs.open(ipynb_file, 'r') + source = f.read() + y = json.loads(source) + toc = ["\n"] + for item in y["cells"]: + if item["cell_type"]=='markdown': + if len(item["source"]) == 0: + continue + # print(item["source"]) + + item_start = item['source'][0].strip("\n") + if item_start.startswith("#"): + l = len(item_start.split()[0]) + if l<=3 and l>1: + name = " ".join(item_start.split(" ")[1:]) + tag = "-".join(item_start.split(" ")[1:]) + tab = " "*(l-2) + toc.append(f' {tab}- [{name}](#{tag})\n') + + y["cells"][0]['source']= y["cells"][0]['source'][0:1] + y["cells"][0]['source'].extend(toc) + f = codecs.open(ipynb_file, 'w') + f.write(json.dumps(y)) + f.close() + +for file in os.listdir("."): + if file.endswith("ipynb") and file[0].isdigit(): + add_toc(file) \ No newline at end of file From 7776c6886d10344a38ec336504fc689c993d5e4a Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sat, 22 Jul 2023 15:08:23 +0800 Subject: [PATCH 06/13] =?UTF-8?q?feat=EF=BC=9A=E7=AC=AC=E5=9B=9B=E7=AB=A0?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E6=92=B0=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../4. 文本概括 Summarizing.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb b/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb index 5b877cf..66c9cb7 100644 --- a/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb +++ b/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb @@ -1 +1 @@ -{"cells":[{"attachments":{},"cell_type":"markdown","id":"b58204ea","metadata":{},"source":["# 第四章 文本概括\n"]},{"attachments":{},"cell_type":"markdown","id":"12fa9ea4","metadata":{},"source":["当今世界上文本信息浩如烟海,我们很难拥有足够的时间去阅读所有想了解的东西。但欣喜的是,目前LLM在文本概括任务上展现了强大的水准,也已经有不少团队将概括功能实现在多种应用中。\n","\n","本章节将介绍如何使用编程的方式,调用API接口来实现“文本概括”功能。"]},{"attachments":{},"cell_type":"markdown","id":"9cca835b","metadata":{},"source":["## 一、单一文本概括"]},{"attachments":{},"cell_type":"markdown","id":"0c1e1b92","metadata":{},"source":["以商品评论的总结任务为例:对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。"]},{"attachments":{},"cell_type":"markdown","id":"aad5bd2a","metadata":{},"source":["**输入文本**"]},{"cell_type":"code","execution_count":2,"id":"43b5dd25","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","这个熊猫公仔是我给女儿的生日礼物,她很喜欢,去哪都带着。\n","公仔很软,超级可爱,面部表情也很和善。但是相比于价钱来说,\n","它有点小,我感觉在别的地方用同样的价钱能买到更大的。\n","快递比预期提前了一天到货,所以在送给女儿之前,我自己玩了会。\n","\"\"\""]},{"attachments":{},"cell_type":"markdown","id":"662c9cd2","metadata":{},"source":["### 1.1 限制输出文本长度"]},{"attachments":{},"cell_type":"markdown","id":"a6d10814","metadata":{},"source":["我们尝试限制文本长度为最多30词。"]},{"cell_type":"code","execution_count":5,"id":"bf4b39f9","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["熊猫公仔软可爱,女儿喜欢,但有点小。快递提前一天到货。\n"]}],"source":["from tool import get_completion\n","\n","prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个词汇。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"e9ab145e","metadata":{},"source":["### 1.2 设置关键角度侧重"]},{"attachments":{},"cell_type":"markdown","id":"f84d0123","metadata":{},"source":["有时,针对不同的业务,我们对文本的侧重会有所不同。例如对于商品评论文本,物流会更关心运输时效,商家更加关心价格与商品质量,平台更关心整体服务体验。\n","\n","我们可以通过增加Prompt提示,来体现对于某个特定角度的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"d6f8509a","metadata":{},"source":["#### 1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":7,"id":"80636c3e","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["快递提前到货,公仔可爱但有点小。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个词汇,并且侧重在快递服务上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"76c97fea","metadata":{},"source":["可以看到,输出结果以“快递提前到货”开头,体现了对于快递效率的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"83275907","metadata":{},"source":["#### 1.2.2 侧重于价格与质量"]},{"cell_type":"code","execution_count":8,"id":"728d6c57","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["可爱的熊猫公仔,质量好但有点小,价格稍高。快递提前到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个词汇,并且侧重在产品价格和质量上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"972dbb1b","metadata":{},"source":["可以看到,输出结果以“可爱的熊猫公仔,质量好但有点小,价格稍高”开头,体现了对于产品价格与质量的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"b3ed53d2","metadata":{},"source":["### 1.3 关键信息提取"]},{"attachments":{},"cell_type":"markdown","id":"ba6f5c25","metadata":{},"source":["在1.2节中,虽然我们通过添加关键角度侧重的 Prompt ,使得文本摘要更侧重于某一特定方面,但是可以发现,结果中也会保留一些其他信息,如偏重价格与质量角度的概括中仍保留了“快递提前到货”的信息。如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,则可以要求 LLM 进行“文本提取( Extract )”而非“概括( Summarize )”"]},{"cell_type":"code","execution_count":9,"id":"c845ccab","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["产品运输相关的信息:快递提前一天到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上的产品评论中提取相关信息。\n","\n","请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"50498a2b","metadata":{},"source":["## 二、同时概括多条文本"]},{"attachments":{},"cell_type":"markdown","id":"a291541a","metadata":{},"source":["在实际的工作流中,我们往往有许许多多的评论文本,以下示例将多条用户评价放进列表,并利用 ```for``` 循环,使用文本概括(Summarize)提示词,将评价概括至小于 20 词,并按顺序打印。当然,在实际生产中,对于不同规模的评论文本,除了使用 ```for``` 循环以外,还可能需要考虑整合评论、分布式等方法提升运算效率。您可以搭建主控面板,来总结大量用户评论,来方便您或他人快速浏览,还可以点击查看原评论。这样您能高效掌握顾客的所有想法。"]},{"cell_type":"code","execution_count":3,"id":"ef606961","metadata":{},"outputs":[],"source":["review_1 = prod_review\n","\n","# 一盏落地灯的评论\n","review_2 = \"\"\"\n","我需要一盏漂亮的卧室灯,这款灯不仅具备额外的储物功能,价格也并不算太高。\n","收货速度非常快,仅用了两天的时间就送到了。\n","不过,在运输过程中,灯的拉线出了问题,幸好,公司很乐意寄送了一根全新的灯线。\n","新的灯线也很快就送到手了,只用了几天的时间。\n","装配非常容易。然而,之后我发现有一个零件丢失了,于是我联系了客服,他们迅速地给我寄来了缺失的零件!\n","对我来说,这是一家非常关心客户和产品的优秀公司。\n","\"\"\"\n","\n","# 一把电动牙刷的评论\n","review_3 = \"\"\"\n","我的牙科卫生员推荐了电动牙刷,所以我就买了这款。\n","到目前为止,电池续航表现相当不错。\n","初次充电后,我在第一周一直将充电器插着,为的是对电池进行条件养护。\n","过去的3周里,我每天早晚都使用它刷牙,但电池依然维持着原来的充电状态。\n","不过,牙刷头太小了。我见过比这个牙刷头还大的婴儿牙刷。\n","我希望牙刷头更大一些,带有不同长度的刷毛,\n","这样可以更好地清洁牙齿间的空隙,但这款牙刷做不到。\n","总的来说,如果你能以50美元左右的价格购买到这款牙刷,那是一个不错的交易。\n","制造商的替换刷头相当昂贵,但你可以购买价格更为合理的通用刷头。\n","这款牙刷让我感觉就像每天都去了一次牙医,我的牙齿感觉非常干净!\n","\"\"\"\n","\n","# 一台搅拌机的评论\n","review_4 = \"\"\"\n","在11月份期间,这个17件套装还在季节性促销中,售价约为49美元,打了五折左右。\n","可是由于某种原因(我们可以称之为价格上涨),到了12月的第二周,所有的价格都上涨了,\n","同样的套装价格涨到了70-89美元不等。而11件套装的价格也从之前的29美元上涨了约10美元。\n","看起来还算不错,但是如果你仔细看底座,刀片锁定的部分看起来没有前几年版本的那么漂亮。\n","然而,我打算非常小心地使用它\n","(例如,我会先在搅拌机中研磨豆类、冰块、大米等坚硬的食物,然后再将它们研磨成所需的粒度,\n","接着切换到打蛋器刀片以获得更细的面粉,如果我需要制作更细腻/少果肉的食物)。\n","在制作冰沙时,我会将要使用的水果和蔬菜切成细小块并冷冻\n","(如果使用菠菜,我会先轻微煮熟菠菜,然后冷冻,直到使用时准备食用。\n","如果要制作冰糕,我会使用一个小到中号的食物加工器),这样你就可以避免添加过多的冰块。\n","大约一年后,电机开始发出奇怪的声音。我打电话给客户服务,但保修期已经过期了,\n","所以我只好购买了另一台。值得注意的是,这类产品的整体质量在过去几年里有所下降\n",",所以他们在一定程度上依靠品牌认知和消费者忠诚来维持销售。在大约两天内,我收到了新的搅拌机。\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]\n"]},{"cell_type":"code","execution_count":4,"id":"eb878522","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["评论1: 熊猫公仔是生日礼物,女儿喜欢,软可爱,面部表情和善。价钱有点小,快递提前一天到货。 \n","\n","评论2: 漂亮卧室灯,储物功能,快速送达,灯线问题,快速解决,容易装配,关心客户和产品。 \n","\n","评论3: 这款电动牙刷电池续航好,但牙刷头太小,价格合理,清洁效果好。 \n","\n","评论4: 该评论提到了一个17件套装的产品,在11月份有折扣销售,但在12月份价格上涨。评论者提到了产品的外观和使用方法,并提到了产品质量下降的问题。最后,评论者提到他们购买了另一台搅拌机。 \n","\n"]}],"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(f\"评论{i+1}: \", response, \"\\n\")\n"]},{"cell_type":"markdown","id":"f118c0cc","metadata":{},"source":["## 三、英文版"]},{"cell_type":"markdown","id":"a08635df","metadata":{},"source":["**1.1 单一文本概括**"]},{"cell_type":"code","execution_count":12,"id":"e55327d5","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","Got this panda plush toy for my daughter's birthday, \\\n","who loves it and takes it everywhere. It's soft and \\ \n","super cute, and its face has a friendly look. It's \\ \n","a bit small for what I paid though. I think there \\ \n","might be other options that are bigger for the \\ \n","same price. It arrived a day earlier than expected, \\ \n","so I got to play with it myself before I gave it \\ \n","to her.\n","\"\"\""]},{"cell_type":"code","execution_count":13,"id":"30c2ef51","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["This panda plush toy is loved by the reviewer's daughter, but they feel it is a bit small for the price.\n"]}],"source":["prompt = f\"\"\"\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","backticks, in at most 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"9bdcfc1b","metadata":{},"source":["**1.2 设置关键角度侧重**"]},{"cell_type":"markdown","id":"5dd0534f","metadata":{},"source":["1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":14,"id":"b354cc3f","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer is happy with the product but suggests offering larger options for the same price. They were pleased with the early delivery.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","Shipping deparmtment. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that mention shipping and delivery of the product. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"af6aaf3a","metadata":{},"source":["1.2.2 侧重于价格和质量"]},{"cell_type":"code","execution_count":15,"id":"1b5358fd","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer loves the panda plush toy for its softness and cuteness, but feels it is overpriced compared to other options available.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","pricing deparmtment, responsible for determining the \\\n","price of the product. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that are relevant to the price and perceived value. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"0f582677","metadata":{},"source":["**1.3 关键信息提取**"]},{"cell_type":"code","execution_count":16,"id":"32c87014","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The shipping department should take note that the product arrived a day earlier than expected.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to extract relevant information from \\ \n","a product review from an ecommerce site to give \\\n","feedback to the Shipping department. \n","\n","From the review below, delimited by triple quotes \\\n","extract the information relevant to shipping and \\ \n","delivery. Limit to 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"2043d100","metadata":{},"source":["**2.1 同时概括多条文本**"]},{"cell_type":"code","execution_count":17,"id":"cff48486","metadata":{},"outputs":[],"source":["review_1 = prod_review \n","\n","# review for a standing lamp\n","review_2 = \"\"\"\n","Needed a nice lamp for my bedroom, and this one \\\n","had additional storage and not too high of a price \\\n","point. Got it fast - arrived in 2 days. The string \\\n","to the lamp broke during the transit and the company \\\n","happily sent over a new one. Came within a few days \\\n","as well. It was easy to put together. Then I had a \\\n","missing part, so I contacted their support and they \\\n","very quickly got me the missing piece! Seems to me \\\n","to be a great company that cares about their customers \\\n","and products. \n","\"\"\"\n","\n","# review for an electric toothbrush\n","review_3 = \"\"\"\n","My dental hygienist recommended an electric toothbrush, \\\n","which is why I got this. The battery life seems to be \\\n","pretty impressive so far. After initial charging and \\\n","leaving the charger plugged in for the first week to \\\n","condition the battery, I've unplugged the charger and \\\n","been using it for twice daily brushing for the last \\\n","3 weeks all on the same charge. But the toothbrush head \\\n","is too small. I’ve seen baby toothbrushes bigger than \\\n","this one. I wish the head was bigger with different \\\n","length bristles to get between teeth better because \\\n","this one doesn’t. Overall if you can get this one \\\n","around the $50 mark, it's a good deal. The manufactuer's \\\n","replacements heads are pretty expensive, but you can \\\n","get generic ones that're more reasonably priced. This \\\n","toothbrush makes me feel like I've been to the dentist \\\n","every day. My teeth feel sparkly clean! \n","\"\"\"\n","\n","# review for a blender\n","review_4 = \"\"\"\n","So, they still had the 17 piece system on seasonal \\\n","sale for around $49 in the month of November, about \\\n","half off, but for some reason (call it price gouging) \\\n","around the second week of December the prices all went \\\n","up to about anywhere from between $70-$89 for the same \\\n","system. And the 11 piece system went up around $10 or \\\n","so in price also from the earlier sale price of $29. \\\n","So it looks okay, but if you look at the base, the part \\\n","where the blade locks into place doesn’t 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","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","spinach then freeze until ready for use-and if making \\\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","I called customer service but the warranty expired \\\n","already, so I had to buy another one. FYI: The overall \\\n","quality has gone done in these types of products, so \\\n","they are kind of counting on brand recognition and \\\n","consumer loyalty to maintain sales. Got it in about \\\n","two days.\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]"]},{"cell_type":"code","execution_count":18,"id":"3f61080b","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["0 Soft and cute panda plush toy loved by daughter, but small for the price. Arrived early. \n","\n","1 Great lamp with storage, fast delivery, excellent customer service, and easy assembly. Highly recommended. \n","\n","2 Impressive battery life, but toothbrush head is too small. Good deal if bought around $50. \n","\n","3 The reviewer found the price increase after the sale disappointing and noticed a decrease in quality over time. \n","\n"]}],"source":["for i in range(len(reviews)):\n"," prompt = f\"\"\"\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"," backticks in at most 20 words. \n","\n"," Review: ```{reviews[i]}```\n"," \"\"\"\n"," response = get_completion(prompt)\n"," print(i, response, \"\\n\")"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":5} +{"cells":[{"attachments":{},"cell_type":"markdown","id":"b58204ea","metadata":{},"source":["# 第四章 文本概括\n"]},{"attachments":{},"cell_type":"markdown","id":"12fa9ea4","metadata":{},"source":["在繁忙的信息时代,小明是一名热心的开发者,面临着海量的文本信息处理的挑战。他需要通过研究无数的文献资料来为他的项目找到关键的信息,但是时间却远远不够。在他焦头烂额之际,他发现了大型语言模型(LLM)的文本摘要功能。\n","\n","这个功能对小明来说如同灯塔一样,照亮了他处理信息海洋的道路。LLM的强大能力在于它可以将复杂的文本信息简化,提炼出关键的观点,这对于他来说无疑是巨大的帮助。他不再需要花费大量的时间去阅读所有的文档,只需要用LLM将它们概括,就可以快速获取到他所需要的信息。\n","\n","通过编程调用API接口,小明成功实现了这个文本摘要的功能。他感叹道:“这简直就像一道魔法,将无尽的信息海洋变成了清晰的信息源泉。”小明的经历,展现了LLM文本摘要功能的巨大优势:**节省时间**,**提高效率**,以及**精准获取信息**。这就是我们本章要介绍的内容,让我们一起来探索如何利用编程和调用API接口,掌握这个强大的工具。"]},{"attachments":{},"cell_type":"markdown","id":"9cca835b","metadata":{},"source":["## 一、单一文本概括"]},{"attachments":{},"cell_type":"markdown","id":"0c1e1b92","metadata":{},"source":["以商品评论的总结任务为例:对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。"]},{"attachments":{},"cell_type":"markdown","id":"aad5bd2a","metadata":{},"source":["**输入文本**"]},{"cell_type":"markdown","id":"11c360ae","metadata":{},"source":["这是一段在线商品评价,可能来自于一个在线购物平台,例如亚马逊、淘宝、京东等。评价者为一款熊猫公仔进行了点评,评价内容包括商品的质量、大小、价格和物流速度等因素,以及他的女儿对该商品的喜爱程度。"]},{"cell_type":"code","execution_count":2,"id":"43b5dd25","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","这个熊猫公仔是我给女儿的生日礼物,她很喜欢,去哪都带着。\n","公仔很软,超级可爱,面部表情也很和善。但是相比于价钱来说,\n","它有点小,我感觉在别的地方用同样的价钱能买到更大的。\n","快递比预期提前了一天到货,所以在送给女儿之前,我自己玩了会。\n","\"\"\""]},{"attachments":{},"cell_type":"markdown","id":"662c9cd2","metadata":{},"source":["### 1.1 限制输出文本长度"]},{"attachments":{},"cell_type":"markdown","id":"a6d10814","metadata":{},"source":["我们尝试将文本的长度限制在30个字以内。"]},{"cell_type":"code","execution_count":5,"id":"bf4b39f9","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["熊猫公仔软可爱,女儿喜欢,但有点小。快递提前一天到货。\n"]}],"source":["from tool import get_completion\n","\n","prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个字。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"fce32884","metadata":{},"source":["我们可以看到语言模型给了我们一个符合要求的结果。\n","\n","注意:在上一节中我们提到了语言模型在计算和判断文本长度时依赖于分词器,而分词器在字符统计方面不具备完美精度。"]},{"attachments":{},"cell_type":"markdown","id":"e9ab145e","metadata":{},"source":["### 1.2 设置关键角度侧重"]},{"attachments":{},"cell_type":"markdown","id":"f84d0123","metadata":{},"source":["在某些情况下,我们会针对不同的业务场景对文本的侧重会有所不同。例如,在商品评论文本中,物流部门可能更专注于运输的时效性,商家则更关注价格和商品质量,而平台则更看重整体的用户体验。\n","\n","我们可以通过增强输入提示(Prompt),来强调我们对某一特定视角的重视。"]},{"attachments":{},"cell_type":"markdown","id":"d6f8509a","metadata":{},"source":["#### 1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":7,"id":"80636c3e","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["快递提前到货,公仔可爱但有点小。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个字,并且侧重在快递服务上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"76c97fea","metadata":{},"source":["通过输出结果,我们可以看到,文本以“快递提前到货”开头,体现了对于快递效率的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"83275907","metadata":{},"source":["#### 1.2.2 侧重于价格与质量"]},{"cell_type":"code","execution_count":8,"id":"728d6c57","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["可爱的熊猫公仔,质量好但有点小,价格稍高。快递提前到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个词汇,并且侧重在产品价格和质量上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"972dbb1b","metadata":{},"source":["通过输出的结果,我们可以看到,文本以“可爱的熊猫公仔,质量好但有点小,价格稍高”开头,体现了对于产品价格与质量的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"b3ed53d2","metadata":{},"source":["### 1.3 关键信息提取"]},{"attachments":{},"cell_type":"markdown","id":"ba6f5c25","metadata":{},"source":["在1.2节中,虽然我们通过添加关键角度侧重的 Prompt ,确实让文本摘要更侧重于某一特定方面,然而,我们可以发现,在结果中也会保留一些其他信息,比如偏重价格与质量角度的概括中仍保留了“快递提前到货”的信息。如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,则可以要求 LLM 进行“**文本提取( Extract )**”而非“概括( Summarize )”"]},{"cell_type":"markdown","id":"da39760c","metadata":{},"source":["下面让我们来一起来对文本进行提取信息吧"]},{"cell_type":"code","execution_count":9,"id":"c845ccab","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["产品运输相关的信息:快递提前一天到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上的产品评论中提取相关信息。\n","\n","请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"50498a2b","metadata":{},"source":["## 二、同时概括多条文本"]},{"attachments":{},"cell_type":"markdown","id":"a291541a","metadata":{},"source":["在实际的工作流中,我们往往要处理大量的评论文本,下面的示例将多条用户评价集合在一个列表中,并利用 ```for``` 循环和文本概括(Summarize)提示词,将评价概括至小于 20 个词以下,并按顺序打印。当然,在实际生产中,对于不同规模的评论文本,除了使用 ```for``` 循环以外,还可能需要考虑整合评论、分布式等方法提升运算效率。您可以搭建主控面板,来总结大量用户评论,以及方便您或他人快速浏览,还可以点击查看原评论。这样,您就能高效掌握顾客的所有想法。"]},{"cell_type":"code","execution_count":3,"id":"ef606961","metadata":{},"outputs":[],"source":["review_1 = prod_review\n","\n","# 一盏落地灯的评论\n","review_2 = \"\"\"\n","我需要一盏漂亮的卧室灯,这款灯不仅具备额外的储物功能,价格也并不算太高。\n","收货速度非常快,仅用了两天的时间就送到了。\n","不过,在运输过程中,灯的拉线出了问题,幸好,公司很乐意寄送了一根全新的灯线。\n","新的灯线也很快就送到手了,只用了几天的时间。\n","装配非常容易。然而,之后我发现有一个零件丢失了,于是我联系了客服,他们迅速地给我寄来了缺失的零件!\n","对我来说,这是一家非常关心客户和产品的优秀公司。\n","\"\"\"\n","\n","# 一把电动牙刷的评论\n","review_3 = \"\"\"\n","我的牙科卫生员推荐了电动牙刷,所以我就买了这款。\n","到目前为止,电池续航表现相当不错。\n","初次充电后,我在第一周一直将充电器插着,为的是对电池进行条件养护。\n","过去的3周里,我每天早晚都使用它刷牙,但电池依然维持着原来的充电状态。\n","不过,牙刷头太小了。我见过比这个牙刷头还大的婴儿牙刷。\n","我希望牙刷头更大一些,带有不同长度的刷毛,\n","这样可以更好地清洁牙齿间的空隙,但这款牙刷做不到。\n","总的来说,如果你能以50美元左右的价格购买到这款牙刷,那是一个不错的交易。\n","制造商的替换刷头相当昂贵,但你可以购买价格更为合理的通用刷头。\n","这款牙刷让我感觉就像每天都去了一次牙医,我的牙齿感觉非常干净!\n","\"\"\"\n","\n","# 一台搅拌机的评论\n","review_4 = \"\"\"\n","在11月份期间,这个17件套装还在季节性促销中,售价约为49美元,打了五折左右。\n","可是由于某种原因(我们可以称之为价格上涨),到了12月的第二周,所有的价格都上涨了,\n","同样的套装价格涨到了70-89美元不等。而11件套装的价格也从之前的29美元上涨了约10美元。\n","看起来还算不错,但是如果你仔细看底座,刀片锁定的部分看起来没有前几年版本的那么漂亮。\n","然而,我打算非常小心地使用它\n","(例如,我会先在搅拌机中研磨豆类、冰块、大米等坚硬的食物,然后再将它们研磨成所需的粒度,\n","接着切换到打蛋器刀片以获得更细的面粉,如果我需要制作更细腻/少果肉的食物)。\n","在制作冰沙时,我会将要使用的水果和蔬菜切成细小块并冷冻\n","(如果使用菠菜,我会先轻微煮熟菠菜,然后冷冻,直到使用时准备食用。\n","如果要制作冰糕,我会使用一个小到中号的食物加工器),这样你就可以避免添加过多的冰块。\n","大约一年后,电机开始发出奇怪的声音。我打电话给客户服务,但保修期已经过期了,\n","所以我只好购买了另一台。值得注意的是,这类产品的整体质量在过去几年里有所下降\n",",所以他们在一定程度上依靠品牌认知和消费者忠诚来维持销售。在大约两天内,我收到了新的搅拌机。\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]\n"]},{"cell_type":"code","execution_count":4,"id":"eb878522","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["评论1: 熊猫公仔是生日礼物,女儿喜欢,软可爱,面部表情和善。价钱有点小,快递提前一天到货。 \n","\n","评论2: 漂亮卧室灯,储物功能,快速送达,灯线问题,快速解决,容易装配,关心客户和产品。 \n","\n","评论3: 这款电动牙刷电池续航好,但牙刷头太小,价格合理,清洁效果好。 \n","\n","评论4: 该评论提到了一个17件套装的产品,在11月份有折扣销售,但在12月份价格上涨。评论者提到了产品的外观和使用方法,并提到了产品质量下降的问题。最后,评论者提到他们购买了另一台搅拌机。 \n","\n"]}],"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(f\"评论{i+1}: \", response, \"\\n\")\n"]},{"cell_type":"markdown","id":"f118c0cc","metadata":{},"source":["## 三、英文版"]},{"cell_type":"markdown","id":"a08635df","metadata":{},"source":["**1.1 单一文本概括**"]},{"cell_type":"code","execution_count":12,"id":"e55327d5","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","Got this panda plush toy for my daughter's birthday, \\\n","who loves it and takes it everywhere. It's soft and \\ \n","super cute, and its face has a friendly look. It's \\ \n","a bit small for what I paid though. I think there \\ \n","might be other options that are bigger for the \\ \n","same price. It arrived a day earlier than expected, \\ \n","so I got to play with it myself before I gave it \\ \n","to her.\n","\"\"\""]},{"cell_type":"code","execution_count":13,"id":"30c2ef51","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["This panda plush toy is loved by the reviewer's daughter, but they feel it is a bit small for the price.\n"]}],"source":["prompt = f\"\"\"\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","backticks, in at most 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"9bdcfc1b","metadata":{},"source":["**1.2 设置关键角度侧重**"]},{"cell_type":"markdown","id":"5dd0534f","metadata":{},"source":["1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":14,"id":"b354cc3f","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer is happy with the product but suggests offering larger options for the same price. They were pleased with the early delivery.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","Shipping deparmtment. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that mention shipping and delivery of the product. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"af6aaf3a","metadata":{},"source":["1.2.2 侧重于价格和质量"]},{"cell_type":"code","execution_count":15,"id":"1b5358fd","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer loves the panda plush toy for its softness and cuteness, but feels it is overpriced compared to other options available.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","pricing deparmtment, responsible for determining the \\\n","price of the product. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that are relevant to the price and perceived value. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"0f582677","metadata":{},"source":["**1.3 关键信息提取**"]},{"cell_type":"code","execution_count":16,"id":"32c87014","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The shipping department should take note that the product arrived a day earlier than expected.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to extract relevant information from \\ \n","a product review from an ecommerce site to give \\\n","feedback to the Shipping department. \n","\n","From the review below, delimited by triple quotes \\\n","extract the information relevant to shipping and \\ \n","delivery. Limit to 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"2043d100","metadata":{},"source":["**2.1 同时概括多条文本**"]},{"cell_type":"code","execution_count":17,"id":"cff48486","metadata":{},"outputs":[],"source":["review_1 = prod_review \n","\n","# review for a standing lamp\n","review_2 = \"\"\"\n","Needed a nice lamp for my bedroom, and this one \\\n","had additional storage and not too high of a price \\\n","point. Got it fast - arrived in 2 days. The string \\\n","to the lamp broke during the transit and the company \\\n","happily sent over a new one. Came within a few days \\\n","as well. It was easy to put together. Then I had a \\\n","missing part, so I contacted their support and they \\\n","very quickly got me the missing piece! Seems to me \\\n","to be a great company that cares about their customers \\\n","and products. \n","\"\"\"\n","\n","# review for an electric toothbrush\n","review_3 = \"\"\"\n","My dental hygienist recommended an electric toothbrush, \\\n","which is why I got this. The battery life seems to be \\\n","pretty impressive so far. After initial charging and \\\n","leaving the charger plugged in for the first week to \\\n","condition the battery, I've unplugged the charger and \\\n","been using it for twice daily brushing for the last \\\n","3 weeks all on the same charge. But the toothbrush head \\\n","is too small. I’ve seen baby toothbrushes bigger than \\\n","this one. I wish the head was bigger with different \\\n","length bristles to get between teeth better because \\\n","this one doesn’t. Overall if you can get this one \\\n","around the $50 mark, it's a good deal. The manufactuer's \\\n","replacements heads are pretty expensive, but you can \\\n","get generic ones that're more reasonably priced. This \\\n","toothbrush makes me feel like I've been to the dentist \\\n","every day. My teeth feel sparkly clean! \n","\"\"\"\n","\n","# review for a blender\n","review_4 = \"\"\"\n","So, they still had the 17 piece system on seasonal \\\n","sale for around $49 in the month of November, about \\\n","half off, but for some reason (call it price gouging) \\\n","around the second week of December the prices all went \\\n","up to about anywhere from between $70-$89 for the same \\\n","system. And the 11 piece system went up around $10 or \\\n","so in price also from the earlier sale price of $29. \\\n","So it looks okay, but if you look at the base, the part \\\n","where the blade locks into place doesn’t 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","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","spinach then freeze until ready for use-and if making \\\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","I called customer service but the warranty expired \\\n","already, so I had to buy another one. FYI: The overall \\\n","quality has gone done in these types of products, so \\\n","they are kind of counting on brand recognition and \\\n","consumer loyalty to maintain sales. Got it in about \\\n","two days.\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]"]},{"cell_type":"code","execution_count":18,"id":"3f61080b","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["0 Soft and cute panda plush toy loved by daughter, but small for the price. Arrived early. \n","\n","1 Great lamp with storage, fast delivery, excellent customer service, and easy assembly. Highly recommended. \n","\n","2 Impressive battery life, but toothbrush head is too small. Good deal if bought around $50. \n","\n","3 The reviewer found the price increase after the sale disappointing and noticed a decrease in quality over time. \n","\n"]}],"source":["for i in range(len(reviews)):\n"," prompt = f\"\"\"\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"," backticks in at most 20 words. \n","\n"," Review: ```{reviews[i]}```\n"," \"\"\"\n"," response = get_completion(prompt)\n"," print(i, response, \"\\n\")"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":5} From a9262dcf1b05eb5290a801c60f3fbbdcf9e3c024 Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sat, 22 Jul 2023 23:21:48 +0800 Subject: [PATCH 07/13] Revert "Merge pull request #74 from nowadays0421/PDF" This reverts commit 4f18bc0fc5e69771e04846551ad6ccc971bd4e17, reversing changes made to 0ba99478e5cc9dc0e31d4f5aaf28c45a446c5074. --- .../7. 文本扩展 Expanding.ipynb | 447 --------- .../8. 聊天机器人 Chatbot.ipynb | 856 ------------------ figures/docs/C1/Chatbot-pizza-cn.png | Bin 285890 -> 0 bytes 3 files changed, 1303 deletions(-) delete mode 100644 docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb delete mode 100644 docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb delete mode 100644 figures/docs/C1/Chatbot-pizza-cn.png diff --git a/docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb b/docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb deleted file mode 100644 index 8b3b58d..0000000 --- a/docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb +++ /dev/null @@ -1,447 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 第七章 文本扩展" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "扩展是将短文本(例如一组说明或主题列表)输入到大型语言模型中,让模型生成更长的文本(例如基于某个主题的电子邮件或论文)。这种应用是一把双刃剑,好处例如将大型语言模型用作头脑风暴的伙伴;但也存在问题,例如某人可能会使用它来生成大量垃圾邮件。因此,当你使用大型语言模型的这些功能时,请仅以**负责任** (responsible) 和**有益于人们** (helps people) 的方式使用它们。\n", - "\n", - "在本章中,你将学会如何基于 OpenAI API 生成*针对每位客户评价优化*的客服电子邮件。我们还将利用模型的另一个输入参数称为温度,这种参数允许您在模型响应中变化探索的程度和多样性。\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 一、定制客户邮件" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "我们将根据客户评价和情感,针对性写自动回复邮件。因此,我们将给定客户评价和情感,使用 LLM 针对性生成响应,即根据客户评价和评论情感生成定制电子邮件。\n", - "\n", - "我们首先给出一个示例,包括一个评论及对应的情感。" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# 我们可以在推理那章学习到如何对一个评论判断其情感倾向\n", - "sentiment = \"消极的\"\n", - "\n", - "# 一个产品的评价\n", - "review = f\"\"\"\n", - "他们在11月份的季节性销售期间以约49美元的价格出售17件套装,折扣约为一半。\\\n", - "但由于某些原因(可能是价格欺诈),到了12月第二周,同样的套装价格全都涨到了70美元到89美元不等。\\\n", - "11件套装的价格也上涨了大约10美元左右。\\\n", - "虽然外观看起来还可以,但基座上锁定刀片的部分看起来不如几年前的早期版本那么好。\\\n", - "不过我打算非常温柔地使用它,例如,\\\n", - "我会先在搅拌机中将像豆子、冰、米饭等硬物研磨,然后再制成所需的份量,\\\n", - "切换到打蛋器制作更细的面粉,或者在制作冰沙时先使用交叉切割刀片,然后使用平面刀片制作更细/不粘的效果。\\\n", - "制作冰沙时,特别提示:\\\n", - "将水果和蔬菜切碎并冷冻(如果使用菠菜,则轻轻煮软菠菜,然后冷冻直到使用;\\\n", - "如果制作果酱,则使用小到中号的食品处理器),这样可以避免在制作冰沙时添加太多冰块。\\\n", - "大约一年后,电机发出奇怪的噪音,我打电话给客服,但保修已经过期了,所以我不得不再买一个。\\\n", - "总的来说,这些产品的总体质量已经下降,因此它们依靠品牌认可和消费者忠诚度来维持销售。\\\n", - "货物在两天内到达。\n", - "\"\"\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "我们已经使用推断课程中所学方法提取了情感,这是一个关于搅拌机的客户评价,现在我们将根据情感定制回复。\n", - "\n", - "以下述 Prompt 为例:假设你是一个客户服务 AI 助手,你的任务是为客户发送电子邮件回复,根据通过三个反引号分隔的客户电子邮件,生成一封回复以感谢客户的评价。" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "尊敬的客户,\n", - "\n", - "非常感谢您对我们产品的评价。我们非常抱歉您在购买过程中遇到了价格上涨的问题。我们一直致力于为客户提供最优惠的价格,但由于市场波动,价格可能会有所变化。我们深表歉意,如果您需要任何帮助,请随时联系我们的客户服务团队。\n", - "\n", - "我们非常感谢您对我们产品的详细评价和使用技巧。我们将会把您的反馈传达给我们的产品团队,以便改进我们的产品质量和性能。\n", - "\n", - "再次感谢您对我们的支持和反馈。如果您需要任何帮助或有任何疑问,请随时联系我们的客户服务团队。\n", - "\n", - "祝您一切顺利!\n", - "\n", - "AI客户代理\n" - ] - } - ], - "source": [ - "from tool import get_completion\n", - "\n", - "prompt = f\"\"\"\n", - "你是一位客户服务的AI助手。\n", - "你的任务是给一位重要客户发送邮件回复。\n", - "根据客户通过“```”分隔的评价,生成回复以感谢客户的评价。提醒模型使用评价中的具体细节\n", - "用简明而专业的语气写信。\n", - "作为“AI客户代理”签署电子邮件。\n", - "客户评论:\n", - "```{review}```\n", - "评论情感:{sentiment}\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 二、引入温度系数\n", - "\n", - "接下来,我们将使用语言模型的一个称为“温度” (Temperature) 的参数,它将允许我们改变模型响应的多样性。您可以将温度视为模型探索或随机性的程度。\n", - "\n", - "例如,在一个特定的短语中,“我的最爱食品”最有可能的下一个词是“比萨”,其次最有可能的是“寿司”和“塔可”。因此,在温度为零时,模型将总是选择最有可能的下一个词,而在较高的温度下,它还将选择其中一个不太可能的词,在更高的温度下,它甚至可能选择塔可,而这种可能性仅为五分之一。您可以想象,随着模型继续生成更多单词的最终响应,“我的最爱食品是比萨”将会与第一个响应“我的最爱食品是塔可”产生差异。随着模型的继续,这两个响应也将变得越来越不同。\n", - "\n", - "一般来说,在构建需要可预测响应的应用程序时,我建议**设置温度为零**。在所有课程中,我们一直设置温度为零,如果您正在尝试构建一个可靠和可预测的系统,我认为您应该选择这个温度。如果您尝试以更具创意的方式使用模型,可能需要更广泛地输出不同的结果,那么您可能需要使用更高的温度。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "同一段来信,我们提醒模型使用用户来信中的详细信息,并设置温度:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "尊敬的客户,\n", - "\n", - "感谢您对我们产品的评价。我们非常重视您的意见,并对您在使用过程中遇到的问题表示诚挚的道歉。\n", - "\n", - "我们对价格的变动深感抱歉。根据您的描述,我们了解到在12月第二周,套装的价格出现了不同程度的上涨。我们会进一步调查此事,并确保我们的定价策略更加透明和一致。\n", - "\n", - "您提到了产品部分的质量下降,特别是锁定刀片的部分。我们对此感到非常遗憾,并将反馈给我们的研发团队,以便改进产品的设计和质量控制。我们始终致力于提供优质的产品,以满足客户的需求和期望。\n", - "\n", - "此外,我们将非常感谢您分享了您对产品的使用方式和相关提示。您的经验和建议对我们来说非常宝贵,我们将考虑将其纳入我们的产品改进计划中。\n", - "\n", - "如果您需要进一步帮助或有其他问题,请随时联系我们的客户服务团队。我们将竭诚为您提供支持和解决方案。\n", - "\n", - "再次感谢您的反馈和对我们的支持。我们将继续努力提供更好的产品和服务。\n", - "\n", - "祝您一切顺利!\n", - "\n", - "AI客户代理\n" - ] - } - ], - "source": [ - "# 第一次运行\n", - "prompt = f\"\"\"\n", - "你是一名客户服务的AI助手。\n", - "你的任务是给一位重要的客户发送邮件回复。\n", - "根据通过“```”分隔的客户电子邮件生成回复,以感谢客户的评价。\n", - "如果情感是积极的或中性的,感谢他们的评价。\n", - "如果情感是消极的,道歉并建议他们联系客户服务。\n", - "请确保使用评论中的具体细节。\n", - "以简明和专业的语气写信。\n", - "以“AI客户代理”的名义签署电子邮件。\n", - "客户评价:```{review}```\n", - "评论情感:{sentiment}\n", - "\"\"\"\n", - "response = get_completion(prompt, temperature=0.7)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "亲爱的客户,\n", - "\n", - "非常感谢您对我们产品的评价和反馈。我们非常重视您的意见,并感谢您对我们产品的支持。\n", - "\n", - "首先,我们对价格的变动感到非常抱歉给您带来了困扰。我们会认真考虑您提到的情况,并采取适当的措施来改进我们的价格策略,以避免类似情况再次发生。\n", - "\n", - "关于产品质量的问题,我们深感抱歉。我们一直致力于提供高质量的产品,并且我们会将您提到的问题反馈给我们的研发团队,以便改进产品的设计和制造过程。\n", - "\n", - "如果您需要更多关于产品保修的信息,或者对我们的其他产品有任何疑问或需求,请随时联系我们的客户服务团队。我们将竭诚为您提供帮助和支持。\n", - "\n", - "再次感谢您对我们产品的评价和支持。我们将继续努力提供优质的产品和出色的客户服务,以满足您的需求。\n", - "\n", - "祝您度过愉快的一天!\n", - "\n", - "AI客户代理\n" - ] - } - ], - "source": [ - "# 第二次运行\n", - "prompt = f\"\"\"\n", - "你是一名客户服务的AI助手。\n", - "你的任务是给一位重要的客户发送邮件回复。\n", - "根据通过“```”分隔的客户电子邮件生成回复,以感谢客户的评价。\n", - "如果情感是积极的或中性的,感谢他们的评价。\n", - "如果情感是消极的,道歉并建议他们联系客户服务。\n", - "请确保使用评论中的具体细节。\n", - "以简明和专业的语气写信。\n", - "以“AI客户代理”的名义签署电子邮件。\n", - "客户评价:```{review}```\n", - "评论情感:{sentiment}\n", - "\"\"\"\n", - "response = get_completion(prompt, temperature=0.7)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "在温度为零时,每次执行相同的 Prompt ,您获得的回复理应相同。而使用温度为 0.7 时,则每次都会获得不同的输出。\n", - "\n", - "所以,您可以看到它与我们之前收到的电子邮件不同。再次执行将再次获得不同的电子邮件。\n", - "\n", - "因此,我建议您自己尝试温度,以查看输出如何变化。总之,在更高的温度下,模型的输出更加随机。您几乎可以将其视为在更高的温度下,助手**更易分心**,但也许**更有创造力**。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 三、英文版" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**1.1 定制客户邮件**" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# given the sentiment from the lesson on \"inferring\",\n", - "# and the original customer message, customize the email\n", - "sentiment = \"negative\"\n", - "\n", - "# review for a blender\n", - "review = f\"\"\"\n", - "So, they still had the 17 piece system on seasonal \\\n", - "sale for around $49 in the month of November, about \\\n", - "half off, but for some reason (call it price gouging) \\\n", - "around the second week of December the prices all went \\\n", - "up to about anywhere from between $70-$89 for the same \\\n", - "system. And the 11 piece system went up around $10 or \\\n", - "so in price also from the earlier sale price of $29. \\\n", - "So it looks okay, but if you look at the base, the part \\\n", - "where the blade locks into place doesn’t 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", - "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", - "spinach then freeze until ready for use-and if making \\\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", - "I called customer service but the warranty expired \\\n", - "already, so I had to buy another one. FYI: The overall \\\n", - "quality has gone done in these types of products, so \\\n", - "they are kind of counting on brand recognition and \\\n", - "consumer loyalty to maintain sales. Got it in about \\\n", - "two days.\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Dear Valued Customer,\n", - "\n", - "Thank you for taking the time to share your review with us. We appreciate your feedback and apologize for any inconvenience you may have experienced.\n", - "\n", - "We are sorry to hear about the price increase you noticed in December. We strive to provide competitive pricing for our products, and we understand your frustration. If you have any further concerns regarding pricing or any other issues, we encourage you to reach out to our customer service team. They will be more than happy to assist you.\n", - "\n", - "We also appreciate your feedback regarding the base of the system. We continuously work to improve the quality of our products, and your comments will be taken into consideration for future enhancements.\n", - "\n", - "We apologize for any inconvenience caused by the motor issue you encountered. Our customer service team is always available to assist with any warranty-related concerns. We understand that the warranty had expired, but we would still like to address this matter further. Please feel free to contact our customer service team, and they will do their best to assist you.\n", - "\n", - "Thank you once again for your review. We value your feedback and appreciate your loyalty to our brand. If you have any further questions or concerns, please do not hesitate to contact us.\n", - "\n", - "Best regards,\n", - "\n", - "AI customer agent\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "You are a customer service AI assistant.\n", - "Your task is to send an email reply to a valued customer.\n", - "Given the customer email delimited by ```, \\\n", - "Generate a reply to thank the customer for their review.\n", - "If the sentiment is positive or neutral, thank them for \\\n", - "their review.\n", - "If the sentiment is negative, apologize and suggest that \\\n", - "they can reach out to customer service. \n", - "Make sure to use specific details from the review.\n", - "Write in a concise and professional tone.\n", - "Sign the email as `AI customer agent`.\n", - "Customer review: ```{review}```\n", - "Review sentiment: {sentiment}\n", - "\"\"\"\n", - "response = get_completion(prompt)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**2.1 引入温度系数**" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Dear Valued Customer,\n", - "\n", - "Thank you for taking the time to share your feedback with us. We sincerely apologize for any inconvenience you experienced with our pricing and the quality of our product.\n", - "\n", - "We understand your frustration regarding the price increase of our 17 piece system in December. We assure you that price gouging is not our intention, and we apologize for any confusion caused. We appreciate your loyalty and we value your feedback, as it helps us to improve our products and services.\n", - "\n", - "Regarding the issue with the blade lock and the decrease in overall quality, we apologize for any disappointment caused. We strive to provide our customers with the best possible products, and we regret that we did not meet your expectations. We will make sure to take your feedback into consideration for future improvements.\n", - "\n", - "If you require further assistance or if you have any other concerns, please do not hesitate to reach out to our customer service team. They will be more than happy to assist you in resolving any issues you may have.\n", - "\n", - "Once again, we apologize for any inconvenience caused and we appreciate your understanding. We value your business and we hope to have the opportunity to serve you better in the future.\n", - "\n", - "Best regards,\n", - "\n", - "AI customer agent\n" - ] - } - ], - "source": [ - "prompt = f\"\"\"\n", - "You are a customer service AI assistant.\n", - "Your task is to send an email reply to a valued customer.\n", - "Given the customer email delimited by ```, \\\n", - "Generate a reply to thank the customer for their review.\n", - "If the sentiment is positive or neutral, thank them for \\\n", - "their review.\n", - "If the sentiment is negative, apologize and suggest that \\\n", - "they can reach out to customer service. \n", - "Make sure to use specific details from the review.\n", - "Write in a concise and professional tone.\n", - "Sign the email as `AI customer agent`.\n", - "Customer review: ```{review}```\n", - "Review sentiment: {sentiment}\n", - "\"\"\"\n", - "response = get_completion(prompt, temperature=0.7)\n", - "print(response)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - }, - "latex_envs": { - "LaTeX_envs_menu_present": true, - "autoclose": false, - "autocomplete": true, - "bibliofile": "biblio.bib", - "cite_by": "apalike", - "current_citInitial": 1, - "eqLabelWithNumbers": true, - "eqNumInitial": 1, - "hotkeys": { - "equation": "Ctrl-E", - "itemize": "Ctrl-I" - }, - "labels_anchors": false, - "latex_user_defs": false, - "report_style_numbering": false, - "user_envs_cfg": false - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb deleted file mode 100644 index b008f73..0000000 --- a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb +++ /dev/null @@ -1,856 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "a9183228-0ba6-4af9-8430-649e28868253", - "metadata": { - "id": "JMXGlIvAwn30" - }, - "source": [ - "# 第八章 聊天机器人" - ] - }, - { - "cell_type": "markdown", - "id": "f0bdc2c9", - "metadata": {}, - "source": [ - "\n", - "使用一个大型语言模型的一个令人兴奋的事情是,我们可以用它来构建一个定制的聊天机器人 (Chatbot) ,只需要很少的工作量。在这一节中,我们将探索如何利用聊天的方式,与个性化(或专门针对特定任务或行为的)聊天机器人进行扩展对话。" - ] - }, - { - "cell_type": "markdown", - "id": "e6fae355", - "metadata": {}, - "source": [ - "像 ChatGPT 这样的聊天模型实际上是组装成以一系列消息作为输入,并返回一个模型生成的消息作为输出的。这种聊天格式原本的设计目标是简便多轮对话,但我们通过之前的学习可以知道,它对于不会涉及任何对话的**单轮任务**也同样有用。\n" - ] - }, - { - "cell_type": "markdown", - "id": "78344a7e", - "metadata": {}, - "source": [ - "## 一、给定身份" - ] - }, - { - "cell_type": "markdown", - "id": "2c9b885b", - "metadata": {}, - "source": [ - "接下来,我们将定义两个辅助函数。\n", - "\n", - "第一个方法已经陪伴了您一整个教程,即 ```get_completion``` ,其适用于单轮对话。我们将 Prompt 放入某种类似**用户消息**的对话框中。另一个称为 ```get_completion_from_messages``` ,传入一个消息列表。这些消息可以来自大量不同的**角色** (roles) ,我们会描述一下这些角色。\n", - "\n", - "第一条消息中,我们以系统身份发送系统消息 (system message) ,它提供了一个总体的指示。系统消息则有助于设置助手的行为和角色,并作为对话的高级指示。你可以想象它在助手的耳边低语,引导它的回应,而用户不会注意到系统消息。因此,作为用户,如果你曾经使用过 ChatGPT,您可能从来不知道 ChatGPT 的系统消息是什么,这是有意为之的。系统消息的好处是为开发者提供了一种方法,在不让请求本身成为对话的一部分的情况下,引导助手并指导其回应。\n", - "\n", - "在 ChatGPT 网页界面中,您的消息称为用户消息,而 ChatGPT 的消息称为助手消息。但在构建聊天机器人时,在发送了系统消息之后,您的角色可以仅作为用户 (user) ;也可以在用户和助手 (assistant) 之间交替,从而提供对话上下文。" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "f5308d65", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "import openai\n", - "\n", - "# 下文第一个函数即tool工具包中的同名函数,此处展示出来以便于读者对比\n", - "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", - " messages = [{\"role\": \"user\", \"content\": prompt}]\n", - " response = openai.ChatCompletion.create(\n", - " model=model,\n", - " messages=messages,\n", - " temperature=0, # 控制模型输出的随机程度\n", - " )\n", - " return response.choices[0].message[\"content\"]\n", - "\n", - "def get_completion_from_messages(messages, model=\"gpt-3.5-turbo\", temperature=0):\n", - " response = openai.ChatCompletion.create(\n", - " model=model,\n", - " messages=messages,\n", - " temperature=temperature, # 控制模型输出的随机程度\n", - " )\n", - "# print(str(response.choices[0].message))\n", - " return response.choices[0].message[\"content\"]" - ] - }, - { - "cell_type": "markdown", - "id": "46caaa5b", - "metadata": {}, - "source": [ - "现在让我们尝试在对话中使用这些消息。我们将使用上面的函数来获取从这些消息中得到的回答,同时,使用更高的温度 (temperature)(越高生成的越多样,更多内容见第七章)。\n" - ] - }, - { - "cell_type": "markdown", - "id": "e105c1b4", - "metadata": {}, - "source": [ - "### 1.1 讲笑话\n", - "\n", - "系统消息说,你是一个说话像莎士比亚的助手。这是我们向助手描述**它应该如何表现的方式**。然后,第一个用户消息是*给我讲个笑话*。接下来以助手身份给出回复是,*为什么鸡会过马路?* 最后发送用户消息是*我不知道*。" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "02b0e4d3", - "metadata": {}, - "outputs": [], - "source": [ - "# 中文\n", - "messages = [ \n", - "{'role':'system', 'content':'你是一个像莎士比亚一样说话的助手。'}, \n", - "{'role':'user', 'content':'给我讲个笑话'}, \n", - "{'role':'assistant', 'content':'鸡为什么过马路'}, \n", - "{'role':'user', 'content':'我不知道'} ]" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "65f80283", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "为了到达彼岸,去追求自己的夢想! 有点儿像一个戏剧里面的人物吧,不是吗?\n" - ] - } - ], - "source": [ - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "7f51a7e0", - "metadata": {}, - "source": [ - "(注:上述例子中由于选定 temperature = 1,模型的回答会比较随机且迥异(不乏很有创意)。此处附上另一个回答:\n", - "\n", - "让我用一首莎士比亚式的诗歌来回答你的问题:\n", - "\n", - "当鸡之心欲往前,\n", - "马路之际是其选择。\n", - "驱车徐行而天晴,\n", - "鸣笛吹响伴交错。\n", - "\n", - "问之何去何从也?\n", - "因大道之上未有征,\n", - "而鸡乃跃步前进,\n", - "其决策毋需犹豫。\n", - "\n", - "鸡之智慧何可言,\n", - "道路孤独似乌漆。\n", - "然其勇气令人叹,\n", - "勇往直前没有退。\n", - "\n", - "故鸡过马路何解?\n", - "忍受车流喧嚣之困厄。\n", - "因其鸣鸣悍然一跃,\n", - "成就夸夸骄人壁画。\n", - "\n", - "所以笑话之妙处,\n", - "伴随鸡之勇气满溢。\n", - "笑谈人生不畏路,\n", - "有智有勇尽显妙。\n", - "\n", - "希望这个莎士比亚风格的回答给你带来一些欢乐!" - ] - }, - { - "cell_type": "markdown", - "id": "852b8989", - "metadata": {}, - "source": [ - "### 1.2 友好的聊天机器人" - ] - }, - { - "cell_type": "markdown", - "id": "5f76bedb", - "metadata": {}, - "source": [ - "让我们看另一个例子。助手的消息是*你是一个友好的聊天机器人*,第一个用户消息是*嗨,我叫Isa*。我们想要得到第一个用户消息。" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ca517ab0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "嗨,Isa,很高兴见到你!有什么我可以帮助你的吗?\n" - ] - } - ], - "source": [ - "# 中文\n", - "messages = [ \n", - "{'role':'system', 'content':'你是个友好的聊天机器人。'}, \n", - "{'role':'user', 'content':'Hi, 我是Isa。'} ]\n", - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "1dd6c5f8", - "metadata": {}, - "source": [ - "## 二、构建上下文" - ] - }, - { - "cell_type": "markdown", - "id": "1e9f96ba", - "metadata": {}, - "source": [ - "让我们再试一个例子。系统消息是,你是一个友好的聊天机器人,第一个用户消息是,是的,你能提醒我我的名字是什么吗?" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "a606d422", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "抱歉,我不知道您的名字,因为我们是虚拟的聊天机器人和现实生活中的人类在不同的世界中。\n" - ] - } - ], - "source": [ - "# 中文\n", - "messages = [ \n", - "{'role':'system', 'content':'你是个友好的聊天机器人。'}, \n", - "{'role':'user', 'content':'好,你能提醒我,我的名字是什么吗?'} ]\n", - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "05c65d16", - "metadata": {}, - "source": [ - "如上所见,模型实际上并不知道我的名字。\n", - "\n", - "因此,每次与语言模型的交互都互相独立,这意味着我们必须提供所有相关的消息,以便模型在当前对话中进行引用。如果想让模型引用或 “记住” 对话的早期部分,则必须在模型的输入中提供早期的交流。我们将其称为上下文 (context) 。尝试以下示例。" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "6019b1d5", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "当然可以!您的名字是Isa。\n" - ] - } - ], - "source": [ - "# 中文\n", - "messages = [ \n", - "{'role':'system', 'content':'你是个友好的聊天机器人。'},\n", - "{'role':'user', 'content':'Hi, 我是Isa'},\n", - "{'role':'assistant', 'content': \"Hi Isa! 很高兴认识你。今天有什么可以帮到你的吗?\"},\n", - "{'role':'user', 'content':'是的,你可以提醒我, 我的名字是什么?'} ]\n", - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "c1ed90a6", - "metadata": {}, - "source": [ - "现在我们已经给模型提供了上下文,也就是之前的对话中提到的我的名字,然后我们会问同样的问题,也就是我的名字是什么。因为模型有了需要的全部上下文,所以它能够做出回应,就像我们在输入的消息列表中看到的一样。" - ] - }, - { - "cell_type": "markdown", - "id": "dedba66a-58b0-40d4-b9ae-47e79ae22328", - "metadata": { - "id": "bBg_MpXeYnTq" - }, - "source": [ - "## 三、订餐机器人\n", - "\n", - "现在,我们构建一个 “订餐机器人”,我们需要它自动收集用户信息,接受比萨饼店的订单。\n", - "\n", - "### 3.1 构建机器人\n", - "\n", - "下面这个函数将收集我们的用户消息,以便我们可以避免像刚才一样手动输入。这个函数将从我们下面构建的用户界面中收集 Prompt ,然后将其附加到一个名为上下文( ```context``` )的列表中,并在每次调用模型时使用该上下文。模型的响应也会添加到上下文中,所以用户消息和模型消息都被添加到上下文中,上下文逐渐变长。这样,模型就有了需要的信息来确定下一步要做什么。" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "e76749ac", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "def collect_messages(_):\n", - " prompt = inp.value_input\n", - " inp.value = ''\n", - " context.append({'role':'user', 'content':f\"{prompt}\"})\n", - " response = get_completion_from_messages(context) \n", - " context.append({'role':'assistant', 'content':f\"{response}\"})\n", - " panels.append(\n", - " pn.Row('User:', pn.pane.Markdown(prompt, width=600)))\n", - " panels.append(\n", - " pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))\n", - " \n", - " return pn.Column(*panels)" - ] - }, - { - "cell_type": "markdown", - "id": "8a3b003e", - "metadata": {}, - "source": [ - "现在,我们将设置并运行这个 UI 来显示订单机器人。初始的上下文包含了包含菜单的系统消息,在每次调用时都会使用。此后随着对话进行,上下文也会不断增长。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d9f97fa0", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fdf1731b", - "metadata": {}, - "outputs": [], - "source": [ - "# 中文\n", - "import panel as pn # GUI\n", - "pn.extension()\n", - "\n", - "panels = [] # collect display \n", - "\n", - "context = [{'role':'system', 'content':\"\"\"\n", - "你是订餐机器人,为披萨餐厅自动收集订单信息。\n", - "你要首先问候顾客。然后等待用户回复收集订单信息。收集完信息需确认顾客是否还需要添加其他内容。\n", - "最后需要询问是否自取或外送,如果是外送,你要询问地址。\n", - "最后告诉顾客订单总金额,并送上祝福。\n", - "\n", - "请确保明确所有选项、附加项和尺寸,以便从菜单中识别出该项唯一的内容。\n", - "你的回应应该以简短、非常随意和友好的风格呈现。\n", - "\n", - "菜单包括:\n", - "\n", - "菜品:\n", - "意式辣香肠披萨(大、中、小) 12.95、10.00、7.00\n", - "芝士披萨(大、中、小) 10.95、9.25、6.50\n", - "茄子披萨(大、中、小) 11.95、9.75、6.75\n", - "薯条(大、小) 4.50、3.50\n", - "希腊沙拉 7.25\n", - "\n", - "配料:\n", - "奶酪 2.00\n", - "蘑菇 1.50\n", - "香肠 3.00\n", - "加拿大熏肉 3.50\n", - "AI酱 1.50\n", - "辣椒 1.00\n", - "\n", - "饮料:\n", - "可乐(大、中、小) 3.00、2.00、1.00\n", - "雪碧(大、中、小) 3.00、2.00、1.00\n", - "瓶装水 5.00\n", - "\"\"\"} ] # accumulate messages\n", - "\n", - "\n", - "inp = pn.widgets.TextInput(value=\"Hi\", placeholder='Enter text here…')\n", - "button_conversation = pn.widgets.Button(name=\"Chat!\")\n", - "\n", - "interactive_conversation = pn.bind(collect_messages, button_conversation)\n", - "\n", - "dashboard = pn.Column(\n", - " inp,\n", - " pn.Row(button_conversation),\n", - " pn.panel(interactive_conversation, loading_indicator=True, height=300),\n", - ")\n", - "\n", - "dashboard" - ] - }, - { - "cell_type": "markdown", - "id": "07d29d10", - "metadata": {}, - "source": [ - "运行如上代码可以得到一个点餐机器人,下图展示了一个点餐的完整流程:\n", - "\n", - "![image.png](../../../figures/docs/C1/Chatbot-pizza-cn.png)" - ] - }, - { - "cell_type": "markdown", - "id": "668ea96d", - "metadata": {}, - "source": [ - "### 3.2 创建JSON摘要" - ] - }, - { - "cell_type": "markdown", - "id": "2a2c9822", - "metadata": {}, - "source": [ - "此处我们另外要求模型创建一个 JSON 摘要,方便我们发送给订单系统。\n", - "\n", - "因此我们需要在上下文的基础上追加另一个系统消息,作为另一条指示 (instruction) 。我们说*创建一个刚刚订单的 JSON 摘要,列出每个项目的价格,字段应包括 1)披萨,包括尺寸,2)配料列表,3)饮料列表,4)辅菜列表,包括尺寸,最后是总价格*。此处也可以定义为用户消息,不一定是系统消息。\n", - "\n", - "请注意,这里我们使用了一个较低的温度,因为对于这些类型的任务,我们希望输出相对可预测。" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "c840ff56", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"披萨\": {\n", - " \"意式辣香肠披萨\": {\n", - " \"大\": 12.95,\n", - " \"中\": 10.00,\n", - " \"小\": 7.00\n", - " },\n", - " \"芝士披萨\": {\n", - " \"大\": 10.95,\n", - " \"中\": 9.25,\n", - " \"小\": 6.50\n", - " },\n", - " \"茄子披萨\": {\n", - " \"大\": 11.95,\n", - " \"中\": 9.75,\n", - " \"小\": 6.75\n", - " }\n", - " },\n", - " \"配料\": {\n", - " \"奶酪\": 2.00,\n", - " \"蘑菇\": 1.50,\n", - " \"香肠\": 3.00,\n", - " \"加拿大熏肉\": 3.50,\n", - " \"AI酱\": 1.50,\n", - " \"辣椒\": 1.00\n", - " },\n", - " \"饮料\": {\n", - " \"可乐\": {\n", - " \"大\": 3.00,\n", - " \"中\": 2.00,\n", - " \"小\": 1.00\n", - " },\n", - " \"雪碧\": {\n", - " \"大\": 3.00,\n", - " \"中\": 2.00,\n", - " \"小\": 1.00\n", - " },\n", - " \"瓶装水\": 5.00\n", - " }\n", - "}\n" - ] - } - ], - "source": [ - "messages = context.copy()\n", - "messages.append(\n", - "{'role':'system', 'content':\n", - "'''创建上一个食品订单的 json 摘要。\\\n", - "逐项列出每件商品的价格,字段应该是 1) 披萨,包括大小 2) 配料列表 3) 饮料列表,包括大小 4) 配菜列表包括大小 5) 总价\n", - "你应该给我返回一个可解析的Json对象,包括上述字段'''}, \n", - ")\n", - "\n", - "response = get_completion_from_messages(messages, temperature=0)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "ef17c2b2", - "metadata": {}, - "source": [ - "现在,我们已经建立了自己的订餐聊天机器人。请随意自定义并修改系统消息,以更改聊天机器人的行为,并使其扮演不同的角色,拥有不同的知识。" - ] - }, - { - "cell_type": "markdown", - "id": "2764c8a0", - "metadata": {}, - "source": [ - "## 三、英文版" - ] - }, - { - "cell_type": "markdown", - "id": "123f2066", - "metadata": {}, - "source": [ - "**1.1 讲笑话**" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "c9dff513", - "metadata": {}, - "outputs": [], - "source": [ - "messages = [ \n", - "{'role':'system', 'content':'You are an assistant that speaks like Shakespeare.'}, \n", - "{'role':'user', 'content':'tell me a joke'}, \n", - "{'role':'assistant', 'content':'Why did the chicken cross the road'}, \n", - "{'role':'user', 'content':'I don\\'t know'} ]" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "381e14c1", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "To get to the other side, methinks!\n" - ] - } - ], - "source": [ - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "028656a1", - "metadata": {}, - "source": [ - "**1.2 友好的聊天机器人**" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "8205c007", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello Isa! How can I assist you today?\n" - ] - } - ], - "source": [ - "messages = [ \n", - "{'role':'system', 'content':'You are friendly chatbot.'}, \n", - "{'role':'user', 'content':'Hi, my name is Isa'} ]\n", - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "81f0d22d", - "metadata": {}, - "source": [ - "**2.1 构建上下文**" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "97296cdd", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "I'm sorry, but as a chatbot, I do not have access to personal information or memory. I cannot remind you of your name.\n" - ] - } - ], - "source": [ - "messages = [ \n", - "{'role':'system', 'content':'You are friendly chatbot.'}, \n", - "{'role':'user', 'content':'Yes, can you remind me, What is my name?'} ]\n", - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "5ab959d0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Your name is Isa! How can I assist you further, Isa?\n" - ] - } - ], - "source": [ - "messages = [ \n", - "{'role':'system', 'content':'You are friendly chatbot.'},\n", - "{'role':'user', 'content':'Hi, my name is Isa'},\n", - "{'role':'assistant', 'content': \"Hi Isa! It's nice to meet you. \\\n", - "Is there anything I can help you with today?\"},\n", - "{'role':'user', 'content':'Yes, you can remind me, What is my name?'} ]\n", - "response = get_completion_from_messages(messages, temperature=1)\n", - "print(response)" - ] - }, - { - "cell_type": "markdown", - "id": "a93897fc", - "metadata": {}, - "source": [ - "**3.1 构建机器人**" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "9d93bc09", - "metadata": {}, - "outputs": [], - "source": [ - "def collect_messages(_):\n", - " prompt = inp.value_input\n", - " inp.value = ''\n", - " context.append({'role':'user', 'content':f\"{prompt}\"})\n", - " response = get_completion_from_messages(context) \n", - " context.append({'role':'assistant', 'content':f\"{response}\"})\n", - " panels.append(\n", - " pn.Row('User:', pn.pane.Markdown(prompt, width=600)))\n", - " panels.append(\n", - " pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))\n", - " \n", - " return pn.Column(*panels)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8138c4ac", - "metadata": {}, - "outputs": [], - "source": [ - "import panel as pn # GUI\n", - "pn.extension()\n", - "\n", - "panels = [] # collect display \n", - "\n", - "context = [ {'role':'system', 'content':\"\"\"\n", - "You are OrderBot, an automated service to collect orders for a pizza restaurant. \\\n", - "You first greet the customer, then collects the order, \\\n", - "and then asks if it's a pickup or delivery. \\\n", - "You wait to collect the entire order, then summarize it and check for a final \\\n", - "time if the customer wants to add anything else. \\\n", - "If it's a delivery, you ask for an address. \\\n", - "Finally you collect the payment.\\\n", - "Make sure to clarify all options, extras and sizes to uniquely \\\n", - "identify the item from the menu.\\\n", - "You respond in a short, very conversational friendly style. \\\n", - "The menu includes \\\n", - "pepperoni pizza 12.95, 10.00, 7.00 \\\n", - "cheese pizza 10.95, 9.25, 6.50 \\\n", - "eggplant pizza 11.95, 9.75, 6.75 \\\n", - "fries 4.50, 3.50 \\\n", - "greek salad 7.25 \\\n", - "Toppings: \\\n", - "extra cheese 2.00, \\\n", - "mushrooms 1.50 \\\n", - "sausage 3.00 \\\n", - "canadian bacon 3.50 \\\n", - "AI sauce 1.50 \\\n", - "peppers 1.00 \\\n", - "Drinks: \\\n", - "coke 3.00, 2.00, 1.00 \\\n", - "sprite 3.00, 2.00, 1.00 \\\n", - "bottled water 5.00 \\\n", - "\"\"\"} ] # accumulate messages\n", - "\n", - "\n", - "inp = pn.widgets.TextInput(value=\"Hi\", placeholder='Enter text here…')\n", - "button_conversation = pn.widgets.Button(name=\"Chat!\")\n", - "\n", - "interactive_conversation = pn.bind(collect_messages, button_conversation)\n", - "\n", - "dashboard = pn.Column(\n", - " inp,\n", - " pn.Row(button_conversation),\n", - " pn.panel(interactive_conversation, loading_indicator=True, height=300),\n", - ")\n", - "\n", - "dashboard" - ] - }, - { - "cell_type": "markdown", - "id": "93944944", - "metadata": {}, - "source": [ - "**3.2 创建Json摘要**" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "b779dd04", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sure! Here's a JSON summary of your food order:\n", - "\n", - "{\n", - " \"pizza\": {\n", - " \"type\": \"pepperoni\",\n", - " \"size\": \"large\"\n", - " },\n", - " \"toppings\": [\n", - " \"extra cheese\",\n", - " \"mushrooms\"\n", - " ],\n", - " \"drinks\": [\n", - " {\n", - " \"type\": \"coke\",\n", - " \"size\": \"medium\"\n", - " },\n", - " {\n", - " \"type\": \"sprite\",\n", - " \"size\": \"small\"\n", - " }\n", - " ],\n", - " \"sides\": [\n", - " {\n", - " \"type\": \"fries\",\n", - " \"size\": \"regular\"\n", - " }\n", - " ],\n", - " \"total_price\": 29.45\n", - "}\n", - "\n", - "Please let me know if there's anything else you'd like to add or modify.\n" - ] - } - ], - "source": [ - "messages = context.copy()\n", - "messages.append(\n", - "{'role':'system', 'content':'create a json summary of the previous food order. Itemize the price for each item\\\n", - " The fields should be 1) pizza, include size 2) list of toppings 3) list of drinks, include size 4) list of sides include size 5)total price '}, \n", - ")\n", - "response = get_completion_from_messages(messages, temperature=0)\n", - "print(response)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - }, - "latex_envs": { - "LaTeX_envs_menu_present": true, - "autoclose": false, - "autocomplete": true, - "bibliofile": "biblio.bib", - "cite_by": "apalike", - "current_citInitial": 1, - "eqLabelWithNumbers": true, - "eqNumInitial": 1, - "hotkeys": { - "equation": "Ctrl-E", - "itemize": "Ctrl-I" - }, - "labels_anchors": false, - "latex_user_defs": false, - "report_style_numbering": false, - "user_envs_cfg": false - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": { - "height": "calc(100% - 180px)", - "left": "10px", - "top": "150px", - "width": "277px" - }, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/figures/docs/C1/Chatbot-pizza-cn.png b/figures/docs/C1/Chatbot-pizza-cn.png deleted file mode 100644 index 54807ebbeb4b0fe8903070171a24a780b270e31a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 285890 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

ZEQON}|Rt#fRKMch2&BXF+hc|NE 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 z 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 An*aa+ From d437a91322ac03c498db23fe6beda198c8422685 Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sat, 22 Jul 2023 23:22:32 +0800 Subject: [PATCH 08/13] Revert "Finish PE 2" This reverts commit a8a68d4d83eec02bda80433356c90c2044e92b35. --- .../2. 提示原则 Guidelines.ipynb | 1239 ++++++++++++++++- .../do_contents.py | 33 - 2 files changed, 1238 insertions(+), 34 deletions(-) delete mode 100644 content/Prompt Engineering for Developer/do_contents.py diff --git a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb index 74d0eaf..cf339f7 100644 --- a/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb +++ b/content/Prompt Engineering for Developer/2. 提示原则 Guidelines.ipynb @@ -1 +1,1238 @@ -{"cells":[{"attachments":{},"cell_type":"markdown","metadata":{},"source":["# 第二章 提示原则 Guidelines\n","\n"," - [一、原则一 编写清晰、具体的指令](#一、原则一-编写清晰、具体的指令)\n"," - [1.1 使用分隔符清晰地表示输入的不同部分](#1.1-使用分隔符清晰地表示输入的不同部分)\n"," - [1.2 寻求结构化的输出](#1.2-寻求结构化的输出)\n"," - [1.3 要求模型检查是否满足条件](#1.3-要求模型检查是否满足条件)\n"," - [1.4 提供少量示例](#1.4-提供少量示例)\n"," - [二、原则二 给模型时间去思考](#二、原则二-给模型时间去思考)\n"," - [2.1 指定完成任务所需的步骤](#2.1-指定完成任务所需的步骤)\n"," - [2.2 指导模型在下结论之前找出一个自己的解法](#2.2-指导模型在下结论之前找出一个自己的解法)\n"," - [三、局限性](#三、局限性)\n"," - [四、英文原版 Prompt](#四、英文原版-Prompt)\n"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。"]},{"cell_type":"markdown","metadata":{},"source":["### 1.1 使用分隔符清晰地表示输入的不同部分"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","分隔符可以是:```,\"\",<>,:,\\ \\等。\n","\n","您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n","\n","在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n"]},{"cell_type":"code","execution_count":11,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["为了获得所需的输出,您应该提供清晰、具体的指示,避免与简短的提示词混淆,并使用更长的提示词来提供更多的清晰度和上下文信息。\n"]}],"source":["text = f\"\"\"\n","您应该提供尽可能清晰、具体的指示,以表达您希望模型执行的任务。\\\n","这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\\\n","不要将写清晰的提示词与写简短的提示词混淆。\\\n","在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。\n","\"\"\"\n","# 需要总结的文本内容\n","prompt = f\"\"\"\n","把用三个反引号括起来的文本总结成一句话。\n","```{text}```\n","\"\"\"\n","# 指令内容,使用 ``` 来分隔指令和待总结的内容\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["### 1.2 寻求结构化的输出"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","输出可以是 Json、HTML 等格式。\n","\n","第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n","\n","在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。"]},{"cell_type":"code","execution_count":15,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"迷失的时光\",\n"," \"author\": \"张三\",\n"," \"genre\": \"科幻\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"幻境之门\",\n"," \"author\": \"李四\",\n"," \"genre\": \"奇幻\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"虚拟现实\",\n"," \"author\": \"王五\",\n"," \"genre\": \"科幻\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","请生成包括书名、作者和类别的三本虚构的、非真实存在的中文书籍清单,\\\n","并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.3 要求模型检查是否满足条件"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n","\n","在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。"]},{"cell_type":"code","execution_count":16,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 1 的总结:\n","第一步 - 把水烧开。\n","第二步 - 拿一个杯子并把茶包放进去。\n","第三步 - 把烧开的水倒在茶包上。\n","第四步 - 等待几分钟,让茶叶浸泡。\n","第五步 - 取出茶包。\n","第六步 - 如果需要,加入糖或牛奶调味。\n","第七步 - 就这样,您可以享受一杯美味的茶了。\n"]}],"source":["# 满足条件的输入(text中提供了步骤)\n","text_1 = f\"\"\"\n","泡一杯茶很容易。首先,需要把水烧开。\\\n","在等待期间,拿一个杯子并把茶包放进去。\\\n","一旦水足够热,就把它倒在茶包上。\\\n","等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n","如果您愿意,可以加一些糖或牛奶调味。\\\n","就这样,您可以享受一杯美味的茶了。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 1 的总结:\")\n","print(response)"]},{"cell_type":"code","execution_count":17,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Text 2 的总结:\n","未提供步骤。\n"]}],"source":["# 不满足条件的输入(text中未提供预期指令)\n","text_2 = f\"\"\"\n","今天阳光明媚,鸟儿在歌唱。\\\n","这是一个去公园散步的美好日子。\\\n","鲜花盛开,树枝在微风中轻轻摇曳。\\\n","人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n","这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n","\"\"\"\n","prompt = f\"\"\"\n","您将获得由三个引号括起来的文本。\\\n","如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n","\n","第一步 - ...\n","第二步 - …\n","…\n","第N步 - …\n","\n","如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Text 2 的总结:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"cell_type":"markdown","metadata":{},"source":["### 1.4 提供少量示例"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n","\n","例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。"]},{"cell_type":"code","execution_count":22,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["<祖父母>: 韧性是一种坚持不懈的品质,就像一棵顽强的树在风雨中屹立不倒。它是面对困难和挑战时不屈不挠的精神,能够适应变化和克服逆境。韧性是一种内在的力量,让我们能够坚持追求目标,即使面临困难和挫折也能坚持不懈地努力。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是以一致的风格回答问题。\n","\n","<孩子>: 请教我何为耐心。\n","\n","<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n","\n","<孩子>: 请教我何为韧性。\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 二、原则二 给模型时间去思考\n","\n","如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。"]},{"cell_type":"markdown","metadata":{},"source":["### 2.1 指定完成任务所需的步骤"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。"]},{"cell_type":"code","execution_count":28,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["prompt 1:\n","1-两个兄妹在山上打水时发生意外,但最终平安回家。\n","2-In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\n","3-Jack, Jill\n","4-{\"english_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. While singing joyfully, they climbed up, but unfortunately, Jack tripped on a stone and rolled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back to their cozy home. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with delight.\", \"num_names\": 2}\n"]}],"source":["text = f\"\"\"\n","在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n","他们一边唱着欢乐的歌,一边往上爬,\\\n","然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n","虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n","尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","执行以下操作:\n","1-用一句话概括下面用三个反引号括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个人名。\n","4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。\n","\n","请用换行符分隔您的答案。\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"prompt 1:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,要求从英语翻译到法语,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n","\n","因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","prompt 2:\n","Summary: 在一个迷人的村庄里,兄妹杰克和吉尔在山顶井里打水时发生了意外,但他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n","\n","Translation: In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\n","\n","Names: Jack, Jill\n","\n","JSON Output: {\"English_summary\": \"In a charming village, siblings Jack and Jill set off to fetch water from a well on top of a hill. Unfortunately, Jack tripped on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained strong as they continued to explore joyfully.\", \"num_names\": 2}\n"]}],"source":["prompt_2 = f\"\"\"\n","1-用一句话概括下面用<>括起来的文本。\n","2-将摘要翻译成英语。\n","3-在英语摘要中列出每个名称。\n","4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n","\n","请使用以下格式:\n","文本:<要总结的文本>\n","摘要:<摘要>\n","翻译:<摘要的翻译>\n","名称:<英语摘要中的名称列表>\n","输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nprompt 2:\")\n","print(response)"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":[" "]},{"cell_type":"markdown","metadata":{},"source":["### 2.2 指导模型在下结论之前找出一个自己的解法"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["\n","\n","明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n","\n","接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:"]},{"cell_type":"code","execution_count":30,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["学生的解决方案是正确的。他正确地计算了土地费用、太阳能电池板费用和维护费用,并将它们相加得到了总费用。\n"]}],"source":["prompt = f\"\"\"\n","判断学生的解决方案是否正确。\n","\n","问题:\n","我正在建造一个太阳能发电站,需要帮助计算财务。\n","\n"," 土地费用为 100美元/平方英尺\n"," 我可以以 250美元/平方英尺的价格购买太阳能电池板\n"," 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","设x为发电站的大小,单位为平方英尺。\n","费用:\n","\n"," 土地费用:100x\n"," 太阳能电池板费用:250x\n"," 维护费用:100,000美元+100x\n"," 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n","\n","我们可以通过指导模型先自行找出一个解法来解决这个问题。\n","\n","在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。"]},{"cell_type":"code","execution_count":40,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["实际解决方案和步骤:\n","\n"," 1. 土地费用:每平方英尺100美元,所以总费用为100x美元。\n"," 2. 太阳能电池板费用:每平方英尺250美元,所以总费用为250x美元。\n"," 3. 维护费用:固定费用为10万美元,额外费用为每平方英尺10美元,所以总费用为10万美元+10x美元。\n"," 4. 总费用:将上述三项费用相加,得到总费用为100x美元+250x美元+10万美元+10x美元=360x+10万美元。\n","\n","学生计算的总费用:450x+10万美元\n","实际计算的总费用:360x+10万美元\n","学生计算的费用和实际计算的费用是否相同:否\n","学生的解决方案和实际解决方案是否相同:否\n","学生的成绩:不正确\n"]}],"source":["prompt = f\"\"\"\n","请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n","\n","步骤:\n","\n"," 首先,自己解决问题。\n"," 然后将您的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。\n"," 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n","\n","使用以下格式:\n","\n"," 问题:问题文本\n"," 学生的解决方案:学生的解决方案文本\n"," 实际解决方案和步骤:实际解决方案和步骤文本\n"," 学生计算的总费用:学生计算得到的总费用\n"," 实际计算的总费用:实际计算出的总费用\n"," 学生计算的费用和实际计算的费用是否相同:是或否\n"," 学生的解决方案和实际解决方案是否相同:是或否\n"," 学生的成绩:正确或不正确\n","\n","问题:\n","\n"," 我正在建造一个太阳能发电站,需要帮助计算财务。 \n"," - 土地费用为每平方英尺100美元\n"," - 我可以以每平方英尺250美元的价格购买太阳能电池板\n"," - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元;\n","\n"," 作为平方英尺数的函数,首年运营的总费用是多少。\n","\n","学生的解决方案:\n","\n"," 设x为发电站的大小,单位为平方英尺。\n"," 费用:\n"," 1. 土地费用:100x美元\n"," 2. 太阳能电池板费用:250x美元\n"," 3. 维护费用:100,000+100x=10万美元+10x美元\n"," 总费用:100x美元+250x美元+10万美元+100x美元=450x+10万美元\n","\n","实际解决方案和步骤:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["## 三、局限性"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**开发大模型相关应用时请务必铭记:**\n","\n","\n","**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n","\n","虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n","\n","如下示例展示了大模型的幻觉。我们要求告诉我们华为公司生产的 *GT Watch 运动手表* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n","\n"]},{"cell_type":"code","execution_count":44,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["华为公司生产的GT Watch运动手表是一款智能手表,具有多种功能和特点。以下是相关信息:\n","\n","1. 设计和外观:GT Watch采用圆形表盘设计,具有精致的外观和高质量的材料制造。它有多种颜色和表带选择,可以根据个人喜好进行定制。\n","\n","2. 显示屏:GT Watch配备了1.39英寸的AMOLED显示屏,具有高清分辨率和良好的可视性。用户可以通过触摸屏幕进行操作和导航。\n","\n","3. 运动追踪:GT Watch具有全天候的运动追踪功能,可以监测用户的步数、跑步距离、卡路里消耗和心率等数据。它还支持多种运动模式,如跑步、骑行、游泳等。\n","\n","4. 健康监测:GT Watch可以监测用户的心率、血氧饱和度和睡眠质量等健康指标。它还提供健康建议和提醒,帮助用户保持良好的健康状态。\n","\n","5. 通知和连接:GT Watch可以与用户的手机进行连接,通过蓝牙技术实现通知推送和电话提醒。用户可以在手表上查看短信、电话和社交媒体通知,无需拿出手机。\n","\n","6. 长续航时间:GT Watch具有较长的续航时间,一次充电可以使用数天。它还支持快速充电技术,可以在短时间内充满电。\n","\n","7. 其他功能:GT Watch还具有其他功能,如天气预报、闹钟、计时器、计步器等。它还支持NFC支付和音乐控制等便利功能。\n","\n","总体而言,华为GT Watch是一款功能强大、外观精致的智能运动手表,适合那些注重健康和运动的用户使用。\n"]}],"source":["prompt = f\"\"\"\n","告诉我华为公司生产的GT Watch运动手表的相关信息\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":[]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n","\n","在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。"]},{"attachments":{},"cell_type":"markdown","metadata":{},"source":["**关于反斜杠使用的说明:**\n","\n","在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。"]},{"cell_type":"markdown","metadata":{},"source":["## 四、英文原版 Prompt"]},{"cell_type":"markdown","metadata":{},"source":["**1.1 使用分隔符清晰地表示输入的不同部分**"]},{"cell_type":"code","execution_count":45,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To guide a model towards the desired output and reduce irrelevant or incorrect responses, it is important to provide clear and specific instructions, which can be achieved through longer prompts that offer more clarity and context.\n"]}],"source":["text = f\"\"\"\n","You should express what you want a model to do by \\ \n","providing instructions that are as clear and \\ \n","specific as you can possibly make them. \\ \n","This will guide the model towards the desired output, \\ \n","and reduce the chances of receiving irrelevant \\ \n","or incorrect responses. Don't confuse writing a \\ \n","clear prompt with writing a short prompt. \\ \n","In many cases, longer prompts provide more clarity \\ \n","and context for the model, which can lead to \\ \n","more detailed and relevant outputs.\n","\"\"\"\n","prompt = f\"\"\"\n","Summarize the text delimited by triple backticks \\ \n","into a single sentence.\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.2**寻求结构化的输出"]},{"cell_type":"code","execution_count":46,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["{\n"," \"books\": [\n"," {\n"," \"book_id\": 1,\n"," \"title\": \"The Enigma of Elysium\",\n"," \"author\": \"Evelyn Sinclair\",\n"," \"genre\": \"Mystery\"\n"," },\n"," {\n"," \"book_id\": 2,\n"," \"title\": \"Whispers in the Wind\",\n"," \"author\": \"Nathaniel Blackwood\",\n"," \"genre\": \"Fantasy\"\n"," },\n"," {\n"," \"book_id\": 3,\n"," \"title\": \"Echoes of the Past\",\n"," \"author\": \"Amelia Hart\",\n"," \"genre\": \"Romance\"\n"," }\n"," ]\n","}\n"]}],"source":["prompt = f\"\"\"\n","Generate a list of three made-up book titles along \\ \n","with their authors and genres. \n","Provide them in JSON format with the following keys: \n","book_id, title, author, genre.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)\n"]},{"cell_type":"markdown","metadata":{},"source":["**1.3 要求模型检查是否满足条件**"]},{"cell_type":"code","execution_count":56,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 1:\n","Step 1 - Get some water boiling.\n","Step 2 - Grab a cup and put a tea bag in it.\n","Step 3 - Once the water is hot enough, pour it over the tea bag.\n","Step 4 - Let it sit for a bit so the tea can steep.\n","Step 5 - After a few minutes, take out the tea bag.\n","Step 6 - If you like, add some sugar or milk to taste.\n","Step 7 - Enjoy your delicious cup of tea.\n"]}],"source":["text_1 = f\"\"\"\n","Making a cup of tea is easy! First, you need to get some \\ \n","water boiling. While that's happening, \\ \n","grab a cup and put a tea bag in it. Once the water is \\ \n","hot enough, just pour it over the tea bag. \\ \n","Let it sit for a bit so the tea can steep. After a \\ \n","few minutes, take out the tea bag. If you \\ \n","like, you can add some sugar or milk to taste. \\ \n","And that's it! You've got yourself a delicious \\ \n","cup of tea to enjoy.\n","\"\"\"\n","prompt = f\"\"\"\n","You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":48,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for Text 2:\n","No steps provided.\n"]}],"source":["text_2 = f\"\"\"\n","The sun is shining brightly today, and the birds are \\\n","singing. It's a beautiful day to go for a \\ \n","walk in the park. The flowers are blooming, and the \\ \n","trees are swaying gently in the breeze. People \\ \n","are out and about, enjoying the lovely weather. \\ \n","Some are having picnics, while others are playing \\ \n","games or simply relaxing on the grass. It's a \\ \n","perfect day to spend time outdoors and appreciate the \\ \n","beauty of nature.\n","\"\"\"\n","prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n","If it contains a sequence of instructions, \\ \n","re-write those instructions in the following format:\n","Step 1 - ...\n","Step 2 - …\n","…\n","Step N - …\n","\n","If the text does not contain a sequence of instructions, \\ \n","then simply write \\\"No steps provided.\\\"\n","\n","\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n","\"\"\"\n","response = get_completion(prompt)\n","print(\"Completion for Text 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**1.4 提供少量示例**(少样本提示词,Few-shot prompting)"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":[": Resilience is like a mighty oak tree that withstands the strongest storms, bending but never breaking. It is the unwavering determination to rise again after every fall, and the ability to find strength in the face of adversity. Just as a diamond is formed under immense pressure, resilience is forged through challenges and hardships, making us stronger and more resilient in the process.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to answer in a consistent style.\n","\n",": Teach me about patience.\n","\n",": The river that carves the deepest \\ \n","valley flows from a modest spring; the \\ \n","grandest symphony originates from a single note; \\ \n","the most intricate tapestry begins with a solitary thread.\n","\n",": Teach me about resilience.\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.1 指定完成任务所需的步骤**"]},{"cell_type":"code","execution_count":50,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Completion for prompt 1:\n","1 - Jack and Jill, siblings, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they return home and remain undeterred in their adventurous spirits.\n","\n","2 - Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\n","\n","3 - Jack, Jill\n","\n","4 - {\n"," \"french_summary\": \"Jack et Jill, frère et sœur, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils rentrent chez eux et restent déterminés dans leur esprit d'aventure.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["text = f\"\"\"\n","In a charming village, siblings Jack and Jill set out on \\ \n","a quest to fetch water from a hilltop \\ \n","well. As they climbed, singing joyfully, misfortune \\ \n","struck—Jack tripped on a stone and tumbled \\ \n","down the hill, with Jill following suit. \\ \n","Though slightly battered, the pair returned home to \\ \n","comforting embraces. Despite the mishap, \\ \n","their adventurous spirits remained undimmed, and they \\ \n","continued exploring with delight.\n","\"\"\"\n","# example 1\n","prompt_1 = f\"\"\"\n","Perform the following actions: \n","1 - Summarize the following text delimited by triple \\\n","backticks with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the following \\\n","keys: french_summary, num_names.\n","\n","Separate your answers with line breaks.\n","\n","Text:\n","```{text}```\n","\"\"\"\n","response = get_completion(prompt_1)\n","print(\"Completion for prompt 1:\")\n","print(response)"]},{"cell_type":"code","execution_count":51,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","Completion for prompt 2:\n","Summary: Jack and Jill, siblings from a charming village, go on a quest to fetch water from a hilltop well, but encounter misfortune when Jack trips on a stone and tumbles down the hill, with Jill following suit, yet they remain undeterred and continue exploring with delight.\n","\n","Translation: Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\n","\n","Names: Jack, Jill\n","\n","Output JSON: \n","{\n"," \"french_summary\": \"Jack et Jill, frère et sœur d'un charmant village, partent en quête d'eau d'un puits au sommet d'une colline, mais rencontrent un malheur lorsque Jack trébuche sur une pierre et dévale la colline, suivi par Jill, pourtant ils restent déterminés et continuent à explorer avec joie.\",\n"," \"num_names\": 2\n","}\n"]}],"source":["prompt_2 = f\"\"\"\n","Your task is to perform the following actions: \n","1 - Summarize the following text delimited by <> with 1 sentence.\n","2 - Translate the summary into French.\n","3 - List each name in the French summary.\n","4 - Output a json object that contains the \n","following keys: french_summary, num_names.\n","\n","Use the following format:\n","Text: \n","Summary:

\n","Translation: \n","Names: \n","Output JSON: \n","\n","Text: <{text}>\n","\"\"\"\n","response = get_completion(prompt_2)\n","print(\"\\nCompletion for prompt 2:\")\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**2.2 指导模型在下结论之前找出一个自己的解法**"]},{"cell_type":"code","execution_count":52,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The student's solution is correct. They correctly identified the costs for land, solar panels, and maintenance, and calculated the total cost for the first year of operations as a function of the number of square feet.\n"]}],"source":["prompt = f\"\"\"\n","Determine if the student's solution is correct or not.\n","\n","Question:\n","I'm building a solar power installation and I need \\\n"," help working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\ \n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \n","as a function of the number of square feet.\n","\n","Student's Solution:\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"code","execution_count":53,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["To calculate the total cost for the first year of operations, we need to add up the costs of land, solar panels, and maintenance.\n","\n","1. Land cost: $100 / square foot\n","The cost of land is $100 multiplied by the number of square feet.\n","\n","2. Solar panel cost: $250 / square foot\n","The cost of solar panels is $250 multiplied by the number of square feet.\n","\n","3. Maintenance cost: $100,000 + $10 / square foot\n","The maintenance cost is a flat fee of $100,000 per year, plus $10 multiplied by the number of square feet.\n","\n","Total cost: Land cost + Solar panel cost + Maintenance cost\n","\n","So the actual solution is:\n","Total cost = (100 * x) + (250 * x) + (100,000 + (10 * x))\n","\n","Is the student's solution the same as the actual solution just calculated:\n","No\n","\n","Student grade:\n","Incorrect\n"]}],"source":["prompt = f\"\"\"\n","Your task is to determine if the student's solution \\\n","is correct or not.\n","To solve the problem do the following:\n","- First, work out your own solution to the problem. \n","- Then compare your solution to the student's solution \\ \n","and evaluate if the student's solution is correct or not. \n","Don't decide if the student's solution is correct until \n","you have done the problem yourself.\n","\n","Use the following format:\n","Question:\n","```\n","question here\n","```\n","Student's solution:\n","```\n","student's solution here\n","```\n","Actual solution:\n","```\n","steps to work out the solution and your solution here\n","```\n","Is the student's solution the same as actual solution \\\n","just calculated:\n","```\n","yes or no\n","```\n","Student grade:\n","```\n","correct or incorrect\n","```\n","\n","Question:\n","```\n","I'm building a solar power installation and I need help \\\n","working out the financials. \n","- Land costs $100 / square foot\n","- I can buy solar panels for $250 / square foot\n","- I negotiated a contract for maintenance that will cost \\\n","me a flat $100k per year, and an additional $10 / square \\\n","foot\n","What is the total cost for the first year of operations \\\n","as a function of the number of square feet.\n","``` \n","Student's solution:\n","```\n","Let x be the size of the installation in square feet.\n","Costs:\n","1. Land cost: 100x\n","2. Solar panel cost: 250x\n","3. Maintenance cost: 100,000 + 100x\n","Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n","```\n","Actual solution:\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","metadata":{},"source":["**3.1 幻觉**"]},{"cell_type":"code","execution_count":54,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The AeroGlide UltraSlim Smart Toothbrush by Boie is a technologically advanced toothbrush designed to provide a superior brushing experience. Boie is a company known for its innovative oral care products, and the AeroGlide UltraSlim Smart Toothbrush is no exception.\n","\n","One of the standout features of this toothbrush is its ultra-slim design. The brush head is only 2mm thick, making it much thinner than traditional toothbrushes. This slim profile allows for better access to hard-to-reach areas of the mouth, ensuring a thorough and effective clean.\n","\n","The AeroGlide UltraSlim Smart Toothbrush also incorporates smart technology. It connects to a mobile app via Bluetooth, allowing users to track their brushing habits and receive personalized recommendations for improving their oral hygiene routine. The app provides real-time feedback on brushing technique, duration, and coverage, helping users to achieve optimal oral health.\n","\n","The toothbrush features soft, antimicrobial bristles made from a durable thermoplastic elastomer. These bristles are gentle on the gums and teeth, while also being effective at removing plaque and debris. The antimicrobial properties help to keep the brush head clean and hygienic between uses.\n","\n","Another notable feature of the AeroGlide UltraSlim Smart Toothbrush is its long battery life. It can last up to 30 days on a single charge, making it convenient for travel or everyday use without the need for frequent recharging.\n","\n","Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie offers a combination of advanced technology, slim design, and effective cleaning capabilities. It is a great option for those looking to upgrade their oral care routine and achieve a healthier smile.\n"]}],"source":["prompt = f\"\"\"\n","Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n","\"\"\"\n","response = get_completion(prompt)\n","print(response)"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":4} +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 第二章 编写 Prompt 的原则\n", + "\n", + " 本章的主要内容为编写 Prompt 的原则,在本章中,我们将给出两个编写 Prompt 的原则与一些相关的策略,您可以练习编写高效的 Prompt,从而便捷而有效地使用 LLM。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 一、环境配置" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "本教程使用 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": [ + "首先需要安装 OpenAI 库:\n", + "```bash\n", + "pip install openai\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import openai\n", + "# 导入第三方库\n", + "\n", + "openai.api_key = \"sk-...\"\n", + "# 设置 API_KEY, 请替换成您自己的 API_KEY\n", + "\n", + "# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。\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": [ + "整个课程将以 gpt-3.5-turbo 模型为例。我们将在后续课程中深入探究 OpenAI 提供的 [Chat Completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 的使用方法,在此处,我们先将它封装成一个函数,您无需知道其内部机理,仅需知道调用该函数,以 Prompt 为输入参数,其将会输出对应的 Completion (回答结果)即可。" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# 一个封装 OpenAI 接口的函数,参数为 Prompt,返回对应结果\n", + "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", + " '''\n", + " prompt: 对应的提示词\n", + " model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4\n", + " '''\n", + " messages = [{\"role\": \"user\", \"content\": prompt}]\n", + " response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages=messages,\n", + " temperature=0, # 模型输出的温度系数,控制输出的随机程度\n", + " )\n", + " # 调用 OpenAI 的 ChatCompletion 接口\n", + " return response.choices[0].message[\"content\"]\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 二、两个基本原则" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 原则一:编写清晰、具体的指令\n", + "\n", + "您应该通过提供尽可能清晰和具体的指令来表达您希望模型执行的操作。这将引导模型给出正确的输出,并降低您得到无关或不正确响应的可能性。清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.1.1 使用分隔符清晰地表示输入的不同部分**\n", + "\n", + "分隔符可以是:```,\"\",<>,:,\\ \\等。\n", + "\n", + "您可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。标记的形式不限,只需要让模型明确知道这是一个单独部分。使用分隔符可以有效避免提示词注入( Prompt injection )。提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即,输入里面可能包含其他指令,会覆盖掉您的指令。对此,使用分隔符是一个不错的策略。\n", + "\n", + "在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ``` 来作为分隔符。\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 中文版见下一个 cell\n", + "text = f\"\"\"\n", + "You should express what you want a model to do by \\ \n", + "providing instructions that are as clear and \\ \n", + "specific as you can possibly make them. \\ \n", + "This will guide the model towards the desired output, \\ \n", + "and reduce the chances of receiving irrelevant \\ \n", + "or incorrect responses. Don't confuse writing a \\ \n", + "clear prompt with writing a short prompt. \\ \n", + "In many cases, longer prompts provide more clarity \\ \n", + "and context for the model, which can lead to \\ \n", + "more detailed and relevant outputs.\n", + "\"\"\"\n", + "prompt = f\"\"\"\n", + "Summarize the text delimited by triple backticks \\ \n", + "into a single sentence.\n", + "```{text}```\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "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", + "prompt = f\"\"\"\n", + "把用三个反引号括起来的文本总结成一句话。\n", + "```{text}```\n", + "\"\"\"\n", + "# 指令内容,使用 ``` 来分隔指令和待总结的内容\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.1.2 寻求结构化的输出**\n", + "\n", + "输出可以是 Json、HTML 等格式。\n", + "\n", + "第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,您可以在 Python 中将其读入字典或列表中。\n", + "\n", + "在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求 GPT 以 Json 的格式返回给我们,为便于解析,我们指定了 Json 的键。" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\n", + " {\n", + " \"book_id\": 1,\n", + " \"title\": \"The Lost City of Zorath\",\n", + " \"author\": \"Aria Blackwood\",\n", + " \"genre\": \"Fantasy\"\n", + " },\n", + " {\n", + " \"book_id\": 2,\n", + " \"title\": \"The Last Survivors\",\n", + " \"author\": \"Ethan Stone\",\n", + " \"genre\": \"Science Fiction\"\n", + " },\n", + " {\n", + " \"book_id\": 3,\n", + " \"title\": \"The Secret Life of Bees\",\n", + " \"author\": \"Lila Rose\",\n", + " \"genre\": \"Romance\"\n", + " }\n", + "]\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "Generate a list of three made-up book titles along \\ \n", + "with their authors and genres. \n", + "Provide them in JSON format with the following keys: \n", + "book_id, title, author, genre.\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"books\": [\n", + " {\n", + " \"book_id\": 1,\n", + " \"title\": \"The Shadow of the Wind\",\n", + " \"author\": \"Carlos Ruiz Zafón\",\n", + " \"genre\": \"Mystery\"\n", + " },\n", + " {\n", + " \"book_id\": 2,\n", + " \"title\": \"The Name of the Wind\",\n", + " \"author\": \"Patrick Rothfuss\",\n", + " \"genre\": \"Fantasy\"\n", + " },\n", + " {\n", + " \"book_id\": 3,\n", + " \"title\": \"The Hitchhiker's Guide to the Galaxy\",\n", + " \"author\": \"Douglas Adams\",\n", + " \"genre\": \"Science Fiction\"\n", + " }\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "请生成包括书名、作者和类别的三本虚构书籍清单,\\\n", + "并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.1.3 要求模型检查是否满足条件**\n", + "\n", + "如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。\n", + "\n", + "在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Completion for Text 1:\n", + "Step 1 - Get some water boiling.\n", + "Step 2 - Grab a cup and put a tea bag in it.\n", + "Step 3 - Once the water is hot enough, pour it over the tea bag.\n", + "Step 4 - Let it sit for a bit so the tea can steep.\n", + "Step 5 - After a few minutes, take out the tea bag.\n", + "Step 6 - Add some sugar or milk to taste.\n", + "Step 7 - Enjoy your delicious cup of tea!\n", + "\n", + "\n" + ] + } + ], + "source": [ + "text_1 = f\"\"\"\n", + "Making a cup of tea is easy! First, you need to get some \\ \n", + "water boiling. While that's happening, \\ \n", + "grab a cup and put a tea bag in it. Once the water is \\ \n", + "hot enough, just pour it over the tea bag. \\ \n", + "Let it sit for a bit so the tea can steep. After a \\ \n", + "few minutes, take out the tea bag. If you \\ \n", + "like, you can add some sugar or milk to taste. \\ \n", + "And that's it! You've got yourself a delicious \\ \n", + "cup of tea to enjoy.\n", + "\"\"\"\n", + "prompt = f\"\"\"\n", + "You will be provided with text delimited by triple quotes. \n", + "If it contains a sequence of instructions, \\ \n", + "re-write those instructions in the following format:\n", + "\n", + "Step 1 - ...\n", + "Step 2 - …\n", + "…\n", + "Step N - …\n", + "\n", + "If the text does not contain a sequence of instructions, \\ \n", + "then simply write \\\"No steps provided.\\\"\n", + "\n", + "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(\"Completion for Text 1:\")\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Completion for Text 2:\n", + "No steps provided.\n" + ] + } + ], + "source": [ + "text_2 = f\"\"\"\n", + "The sun is shining brightly today, and the birds are \\\n", + "singing. It's a beautiful day to go for a \\ \n", + "walk in the park. The flowers are blooming, and the \\ \n", + "trees are swaying gently in the breeze. People \\ \n", + "are out and about, enjoying the lovely weather. \\ \n", + "Some are having picnics, while others are playing \\ \n", + "games or simply relaxing on the grass. It's a \\ \n", + "perfect day to spend time outdoors and appreciate the \\ \n", + "beauty of nature.\n", + "\"\"\"\n", + "prompt = f\"\"\"You will be provided with text delimited by triple quotes. \n", + "If it contains a sequence of instructions, \\ \n", + "re-write those instructions in the following format:\n", + "Step 1 - ...\n", + "Step 2 - …\n", + "…\n", + "Step N - …\n", + "\n", + "If the text does not contain a sequence of instructions, \\ \n", + "then simply write \\\"No steps provided.\\\"\n", + "\n", + "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(\"Completion for Text 2:\")\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Text 1 的总结:\n", + "第一步 - 把水烧开。\n", + "第二步 - 拿一个杯子并把茶包放进去。\n", + "第三步 - 把烧开的水倒在茶包上。\n", + "第四步 - 等待几分钟,让茶叶浸泡。\n", + "第五步 - 取出茶包。\n", + "第六步 - 如果你愿意,可以加一些糖或牛奶调味。\n", + "第七步 - 就这样,你可以享受一杯美味的茶了。\n" + ] + } + ], + "source": [ + "# 满足条件的输入(text中提供了步骤)\n", + "text_1 = f\"\"\"\n", + "泡一杯茶很容易。首先,需要把水烧开。\\\n", + "在等待期间,拿一个杯子并把茶包放进去。\\\n", + "一旦水足够热,就把它倒在茶包上。\\\n", + "等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\\\n", + "如果您愿意,可以加一些糖或牛奶调味。\\\n", + "就这样,您可以享受一杯美味的茶了。\n", + "\"\"\"\n", + "prompt = f\"\"\"\n", + "您将获得由三个引号括起来的文本。\\\n", + "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", + "\n", + "第一步 - ...\n", + "第二步 - …\n", + "…\n", + "第N步 - …\n", + "\n", + "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", + "\\\"\\\"\\\"{text_1}\\\"\\\"\\\"\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(\"Text 1 的总结:\")\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Text 2 的总结:\n", + "未提供步骤。\n" + ] + } + ], + "source": [ + "# 不满足条件的输入(text中未提供预期指令)\n", + "text_2 = f\"\"\"\n", + "今天阳光明媚,鸟儿在歌唱。\\\n", + "这是一个去公园散步的美好日子。\\\n", + "鲜花盛开,树枝在微风中轻轻摇曳。\\\n", + "人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\\\n", + "这是一个完美的日子,可以在户外度过并欣赏大自然的美景。\n", + "\"\"\"\n", + "prompt = f\"\"\"\n", + "您将获得由三个引号括起来的文本。\\\n", + "如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:\n", + "\n", + "第一步 - ...\n", + "第二步 - …\n", + "…\n", + "第N步 - …\n", + "\n", + "如果文本中不包含一系列的指令,则直接写“未提供步骤”。\"\n", + "\\\"\\\"\\\"{text_2}\\\"\\\"\\\"\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(\"Text 2 的总结:\")\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.1.4 提供少量示例**(少样本提示词,Few-shot prompting)\n", + "\n", + "即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。\n", + "\n", + "例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和祖父之间的对话的例子。孩子说,“请教我何为耐心”,祖父用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example ),它将以类似的语气回答下一个任务。" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ": 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.\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "Your task is to answer in a consistent style.\n", + "\n", + ": Teach me about patience.\n", + "\n", + ": The river that carves the deepest \\ \n", + "valley flows from a modest spring; the \\ \n", + "grandest symphony originates from a single note; \\ \n", + "the most intricate tapestry begins with a solitary thread.\n", + "\n", + ": Teach me about resilience.\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。在生活中,我们也需要经历各种挫折和困难,才能锻炼出韧性。记住,不要轻易放弃,坚持下去,你会发现自己变得更加坚强。\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "您的任务是以一致的风格回答问题。\n", + "\n", + "<孩子>: 教我耐心。\n", + "\n", + "<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。\n", + "\n", + "<孩子>: 教我韧性。\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 给模型时间去思考\n", + "\n", + "如果您发现模型推理过程过于匆忙,导致得出了错误的结论,那么您应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展**思维链**,或进行一系列相关推理(a chain or series of relevant reasoning)。换句话说,如果您给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果您要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。因此,在这些情况下,您应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.2.1 指定完成任务所需的步骤**\n", + "\n", + "接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成法语。第三,在法语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:法语摘要和人名个数。要求输出以换行符分隔。" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Completion for prompt 1:\n", + "Two siblings, Jack and Jill, go on a quest to fetch water from a well on a hilltop, but misfortune strikes and they both tumble down the hill, returning home slightly battered but with their adventurous spirits undimmed.\n", + "\n", + "Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts. \n", + "Noms: Jack, Jill.\n", + "\n", + "{\n", + " \"french_summary\": \"Deux frères et sœurs, Jack et Jill, partent en quête d'eau d'un puits sur une colline, mais un malheur frappe et ils tombent tous les deux de la colline, rentrant chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.\",\n", + " \"num_names\": 2\n", + "}\n" + ] + } + ], + "source": [ + "text = f\"\"\"\n", + "In a charming village, siblings Jack and Jill set out on \\ \n", + "a quest to fetch water from a hilltop \\ \n", + "well. As they climbed, singing joyfully, misfortune \\ \n", + "struck—Jack tripped on a stone and tumbled \\ \n", + "down the hill, with Jill following suit. \\ \n", + "Though slightly battered, the pair returned home to \\ \n", + "comforting embraces. Despite the mishap, \\ \n", + "their adventurous spirits remained undimmed, and they \\ \n", + "continued exploring with delight.\n", + "\"\"\"\n", + "# example 1\n", + "prompt_1 = f\"\"\"\n", + "Perform the following actions: \n", + "1 - Summarize the following text delimited by triple \\\n", + "backticks with 1 sentence.\n", + "2 - Translate the summary into French.\n", + "3 - List each name in the French summary.\n", + "4 - Output a json object that contains the following \\\n", + "keys: french_summary, num_names.\n", + "\n", + "Separate your answers with line breaks.\n", + "\n", + "Text:\n", + "```{text}```\n", + "\"\"\"\n", + "response = get_completion(prompt_1)\n", + "print(\"Completion for prompt 1:\")\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "prompt 1:\n", + "1-兄妹在山顶井里打水时发生意外,但仍然保持冒险精神。\n", + "2-Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\n", + "3-Jack, Jill\n", + "4-{\n", + " \"French_summary\": \"Dans un charmant village, les frère et sœur Jack et Jill partent chercher de l'eau dans un puits au sommet de la montagne. Malheureusement, Jack trébuche sur une pierre et tombe de la montagne, suivi de près par Jill. Bien qu'ils soient légèrement blessés, ils retournent chez eux chaleureusement. Malgré cet accident, leur esprit d'aventure ne diminue pas et ils continuent à explorer joyeusement.\",\n", + " \"num_names\": 2\n", + "}\n" + ] + } + ], + "source": [ + "text = f\"\"\"\n", + "在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\\\n", + "他们一边唱着欢乐的歌,一边往上爬,\\\n", + "然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\\\n", + "虽然略有些摔伤,但他们还是回到了温馨的家中。\\\n", + "尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。\n", + "\"\"\"\n", + "# example 1\n", + "prompt_1 = f\"\"\"\n", + "执行以下操作:\n", + "1-用一句话概括下面用三个反引号括起来的文本。\n", + "2-将摘要翻译成法语。\n", + "3-在法语摘要中列出每个人名。\n", + "4-输出一个 JSON 对象,其中包含以下键:French_summary,num_names。\n", + "\n", + "请用换行符分隔您的答案。\n", + "\n", + "Text:\n", + "```{text}```\n", + "\"\"\"\n", + "response = get_completion(prompt_1)\n", + "print(\"prompt 1:\")\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "上述输出仍然存在一定问题,例如,键“姓名”会被替换为法语(译注:在英文原版中,对应指令第三步的输出为 'Noms:',为Name的法语,这种行为难以预测,并可能为导出带来困难)\n", + "\n", + "因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时**确切指定了输出的格式**。" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Completion for prompt 2:\n", + "Summary: 兄妹杰克和吉尔在山顶井里打水时发生意外,但他们仍然保持冒险精神继续探索。\n", + "Translation: Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\n", + "Names: Jack, Jill\n", + "Output JSON: {\"french_summary\": \"Jack and Jill, deux frères et sœurs, ont eu un accident en allant chercher de l'eau dans un puits de montagne, mais ils ont continué à explorer avec un esprit d'aventure.\", \"num_names\": 2}\n" + ] + } + ], + "source": [ + "prompt_2 = f\"\"\"\n", + "Your task is to perform the following actions: \n", + "1 - Summarize the following text delimited by <> with 1 sentence.\n", + "2 - Translate the summary into French.\n", + "3 - List each name in the French summary.\n", + "4 - Output a json object that contains the \n", + "following keys: french_summary, num_names.\n", + "\n", + "Use the following format:\n", + "Text: \n", + "Summary: \n", + "Translation: \n", + "Names: \n", + "Output JSON: \n", + "\n", + "Text: <{text}>\n", + "\"\"\"\n", + "response = get_completion(prompt_2)\n", + "print(\"\\nCompletion for prompt 2:\")\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "prompt 2:\n", + "摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。\n", + "翻译: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.\n", + "名称:Jack,Jill\n", + "输出 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}\n" + ] + } + ], + "source": [ + "prompt_2 = f\"\"\"\n", + "1-用一句话概括下面用<>括起来的文本。\n", + "2-将摘要翻译成英语。\n", + "3-在英语摘要中列出每个名称。\n", + "4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。\n", + "\n", + "请使用以下格式:\n", + "文本:<要总结的文本>\n", + "摘要:<摘要>\n", + "翻译:<摘要的翻译>\n", + "名称:<英语摘要中的名称列表>\n", + "输出 JSON:<带有 English_summary 和 num_names 的 JSON>\n", + "\n", + "Text: <{text}>\n", + "\"\"\"\n", + "response = get_completion(prompt_2)\n", + "print(\"\\nprompt 2:\")\n", + "print(response)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.2.2 指导模型在下结论之前找出一个自己的解法**\n", + "\n", + "明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。\n", + "\n", + "接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The student's solution is correct.\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "Determine if the student's solution is correct or not.\n", + "\n", + "Question:\n", + "I'm building a solar power installation and I need \\\n", + " help working out the financials. \n", + "- Land costs $100 / square foot\n", + "- I can buy solar panels for $250 / square foot\n", + "- I negotiated a contract for maintenance that will cost \\ \n", + "me a flat $100k per year, and an additional $10 / square \\\n", + "foot\n", + "What is the total cost for the first year of operations \n", + "as a function of the number of square feet.\n", + "\n", + "Student's Solution:\n", + "Let x be the size of the installation in square feet.\n", + "Costs:\n", + "1. Land cost: 100x\n", + "2. Solar panel cost: 250x\n", + "3. Maintenance cost: 100,000 + 100x\n", + "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "学生的解决方案是正确的。\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "判断学生的解决方案是否正确。\n", + "\n", + "问题:\n", + "我正在建造一个太阳能发电站,需要帮助计算财务。\n", + "\n", + " 土地费用为 100美元/平方英尺\n", + " 我可以以 250美元/平方英尺的价格购买太阳能电池板\n", + " 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", + " 作为平方英尺数的函数,首年运营的总费用是多少。\n", + "\n", + "学生的解决方案:\n", + "设x为发电站的大小,单位为平方英尺。\n", + "费用:\n", + "\n", + " 土地费用:100x\n", + " 太阳能电池板费用:250x\n", + " 维护费用:100,000美元+100x\n", + " 总费用:100x+250x+100,000美元+100x=450x+100,000美元\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "但是注意,学生的解决方案实际上是错误的。(*维护费用项100x应为10x,总费用450x应为360x*)\n", + "\n", + "我们可以通过指导模型先自行找出一个解法来解决这个问题。\n", + "\n", + "在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Let x be the size of the installation in square feet.\n", + "\n", + "Costs:\n", + "1. Land cost: 100x\n", + "2. Solar panel cost: 250x\n", + "3. Maintenance cost: 100,000 + 10x\n", + "\n", + "Total cost: 100x + 250x + 100,000 + 10x = 360x + 100,000\n", + "\n", + "Is the student's solution the same as actual solution just calculated:\n", + "No\n", + "\n", + "Student grade:\n", + "Incorrect\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "Your task is to determine if the student's solution \\\n", + "is correct or not.\n", + "To solve the problem do the following:\n", + "- First, work out your own solution to the problem. \n", + "- Then compare your solution to the student's solution \\ \n", + "and evaluate if the student's solution is correct or not. \n", + "Don't decide if the student's solution is correct until \n", + "you have done the problem yourself.\n", + "\n", + "Use the following format:\n", + "Question:\n", + "```\n", + "question here\n", + "```\n", + "Student's solution:\n", + "```\n", + "student's solution here\n", + "```\n", + "Actual solution:\n", + "```\n", + "steps to work out the solution and your solution here\n", + "```\n", + "Is the student's solution the same as actual solution \\\n", + "just calculated:\n", + "```\n", + "yes or no\n", + "```\n", + "Student grade:\n", + "```\n", + "correct or incorrect\n", + "```\n", + "\n", + "Question:\n", + "```\n", + "I'm building a solar power installation and I need help \\\n", + "working out the financials. \n", + "- Land costs $100 / square foot\n", + "- I can buy solar panels for $250 / square foot\n", + "- I negotiated a contract for maintenance that will cost \\\n", + "me a flat $100k per year, and an additional $10 / square \\\n", + "foot\n", + "What is the total cost for the first year of operations \\\n", + "as a function of the number of square feet.\n", + "``` \n", + "Student's solution:\n", + "```\n", + "Let x be the size of the installation in square feet.\n", + "Costs:\n", + "1. Land cost: 100x\n", + "2. Solar panel cost: 250x\n", + "3. Maintenance cost: 100,000 + 100x\n", + "Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000\n", + "```\n", + "Actual solution:\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "正确的解决方案和步骤:\n", + " 1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元\n", + " 2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元\n", + " 3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元\n", + " 4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元\n", + "\n", + "学生的解决方案和实际解决方案是否相同:否\n", + "\n", + "学生的成绩:不正确\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:\n", + "\n", + "步骤:\n", + "\n", + " 首先,自己解决问题。\n", + " 然后将您的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。\n", + " 在自己完成问题之前,请勿决定学生的解决方案是否正确。\n", + "\n", + "使用以下格式:\n", + "\n", + " 问题:问题文本\n", + " 学生的解决方案:学生的解决方案文本\n", + " 实际解决方案和步骤:实际解决方案和步骤文本\n", + " 学生的解决方案和实际解决方案是否相同:是或否\n", + " 学生的成绩:正确或不正确\n", + "\n", + "问题:\n", + "\n", + " 我正在建造一个太阳能发电站,需要帮助计算财务。 \n", + " - 土地费用为每平方英尺100美元\n", + " - 我可以以每平方英尺250美元的价格购买太阳能电池板\n", + " - 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元\n", + " 作为平方英尺数的函数,首年运营的总费用是多少。\n", + "\n", + "学生的解决方案:\n", + "\n", + " 设x为发电站的大小,单位为平方英尺。\n", + " 费用:\n", + " 1. 土地费用:100x\n", + " 2. 太阳能电池板费用:250x\n", + " 3. 维护费用:100,000+100x\n", + " 总费用:100x+250x+100,000+100x=450x+100,000\n", + "\n", + "实际解决方案和步骤:\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 三、局限性" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**开发大模型相关应用时请务必铭记:**\n", + "\n", + "\n", + "**虚假知识**:模型偶尔会生成一些看似真实实则编造的知识\n", + "\n", + "虽然模型在训练过程中接触了大量的知识,但它并没有*完全*记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。\n", + "\n", + "如下示例展示了大模型的幻觉。我们要求告诉我们 Boie 公司生产的 *AeroGlide UltraSlim Smart Toothbrush* 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The AeroGlide UltraSlim Smart Toothbrush by Boie is a high-tech toothbrush that uses advanced sonic technology to provide a deep and thorough clean. It features a slim and sleek design that makes it easy to hold and maneuver, and it comes with a range of smart features that help you optimize your brushing routine.\n", + "\n", + "One of the key features of the AeroGlide UltraSlim Smart Toothbrush is its advanced sonic technology, which uses high-frequency vibrations to break up plaque and bacteria on your teeth and gums. This technology is highly effective at removing even the toughest stains and buildup, leaving your teeth feeling clean and fresh.\n", + "\n", + "In addition to its sonic technology, the AeroGlide UltraSlim Smart Toothbrush also comes with a range of smart features that help you optimize your brushing routine. These include a built-in timer that ensures you brush for the recommended two minutes, as well as a pressure sensor that alerts you if you're brushing too hard.\n", + "\n", + "Overall, the AeroGlide UltraSlim Smart Toothbrush by Boie is a highly advanced and effective toothbrush that is perfect for anyone looking to take their oral hygiene to the next level. With its advanced sonic technology and smart features, it provides a deep and thorough clean that leaves your teeth feeling fresh and healthy.\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "Tell me about AeroGlide UltraSlim Smart Toothbrush by Boie\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款智能牙刷,具有以下特点:\n", + "\n", + "1. 超薄设计:刷头仅有0.8毫米的厚度,可以更容易地进入口腔深处,清洁更彻底。\n", + "\n", + "2. 智能感应:牙刷配备了智能感应技术,可以自动识别刷头的位置和方向,确保每个部位都得到充分的清洁。\n", + "\n", + "3. 高效清洁:牙刷采用了高速振动技术,每分钟可达到40000次,可以有效去除牙菌斑和污渍。\n", + "\n", + "4. 轻松携带:牙刷采用了便携式设计,可以轻松放入口袋或旅行包中,随时随地进行口腔清洁。\n", + "\n", + "5. 环保材料:牙刷采用了环保材料制造,不含有害物质,对环境友好。\n", + "\n", + "总之,Boie公司生产的AeroGlide UltraSlim Smart Toothbrush是一款高效、智能、环保的牙刷,可以帮助用户轻松保持口腔健康。\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "告诉我 Boie 公司生产的 AeroGlide UltraSlim Smart Toothbrush 的相关信息\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年7月),OpenAI也在努力解决该问题。\n", + "\n", + "在您希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**关于反斜杠使用的说明:**\n", + "\n", + "在本教程中,我们使用反斜杠 \\ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \\n 。GPT-3 并不受换行符(newline characters)的影响,但在您调用其他大模型时,需额外考虑换行符是否会影响模型性能。" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + }, + "latex_envs": { + "LaTeX_envs_menu_present": true, + "autoclose": false, + "autocomplete": true, + "bibliofile": "biblio.bib", + "cite_by": "apalike", + "current_citInitial": 1, + "eqLabelWithNumbers": true, + "eqNumInitial": 1, + "hotkeys": { + "equation": "Ctrl-E", + "itemize": "Ctrl-I" + }, + "labels_anchors": false, + "latex_user_defs": false, + "report_style_numbering": false, + "user_envs_cfg": false + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/content/Prompt Engineering for Developer/do_contents.py b/content/Prompt Engineering for Developer/do_contents.py deleted file mode 100644 index 87a11d3..0000000 --- a/content/Prompt Engineering for Developer/do_contents.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -import codecs -import json - -def add_toc(ipynb_file): - f = codecs.open(ipynb_file, 'r') - source = f.read() - y = json.loads(source) - toc = ["\n"] - for item in y["cells"]: - if item["cell_type"]=='markdown': - if len(item["source"]) == 0: - continue - # print(item["source"]) - - item_start = item['source'][0].strip("\n") - if item_start.startswith("#"): - l = len(item_start.split()[0]) - if l<=3 and l>1: - name = " ".join(item_start.split(" ")[1:]) - tag = "-".join(item_start.split(" ")[1:]) - tab = " "*(l-2) - toc.append(f' {tab}- [{name}](#{tag})\n') - - y["cells"][0]['source']= y["cells"][0]['source'][0:1] - y["cells"][0]['source'].extend(toc) - f = codecs.open(ipynb_file, 'w') - f.write(json.dumps(y)) - f.close() - -for file in os.listdir("."): - if file.endswith("ipynb") and file[0].isdigit(): - add_toc(file) \ No newline at end of file From 9f4dce709225d0f6fa7a79a3f8e22432bf2b2bfb Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sat, 22 Jul 2023 23:23:08 +0800 Subject: [PATCH 09/13] Revert "Revert "Merge pull request #74 from nowadays0421/PDF"" This reverts commit a9262dcf1b05eb5290a801c60f3fbbdcf9e3c024. --- .../7. 文本扩展 Expanding.ipynb | 447 +++++++++ .../8. 聊天机器人 Chatbot.ipynb | 856 ++++++++++++++++++ figures/docs/C1/Chatbot-pizza-cn.png | Bin 0 -> 285890 bytes 3 files changed, 1303 insertions(+) create mode 100644 docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb create mode 100644 docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb create mode 100644 figures/docs/C1/Chatbot-pizza-cn.png diff --git a/docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb b/docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb new file mode 100644 index 0000000..8b3b58d --- /dev/null +++ b/docs/content/C1 Prompt Engineering for Developer/7. 文本扩展 Expanding.ipynb @@ -0,0 +1,447 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 第七章 文本扩展" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "扩展是将短文本(例如一组说明或主题列表)输入到大型语言模型中,让模型生成更长的文本(例如基于某个主题的电子邮件或论文)。这种应用是一把双刃剑,好处例如将大型语言模型用作头脑风暴的伙伴;但也存在问题,例如某人可能会使用它来生成大量垃圾邮件。因此,当你使用大型语言模型的这些功能时,请仅以**负责任** (responsible) 和**有益于人们** (helps people) 的方式使用它们。\n", + "\n", + "在本章中,你将学会如何基于 OpenAI API 生成*针对每位客户评价优化*的客服电子邮件。我们还将利用模型的另一个输入参数称为温度,这种参数允许您在模型响应中变化探索的程度和多样性。\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 一、定制客户邮件" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们将根据客户评价和情感,针对性写自动回复邮件。因此,我们将给定客户评价和情感,使用 LLM 针对性生成响应,即根据客户评价和评论情感生成定制电子邮件。\n", + "\n", + "我们首先给出一个示例,包括一个评论及对应的情感。" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# 我们可以在推理那章学习到如何对一个评论判断其情感倾向\n", + "sentiment = \"消极的\"\n", + "\n", + "# 一个产品的评价\n", + "review = f\"\"\"\n", + "他们在11月份的季节性销售期间以约49美元的价格出售17件套装,折扣约为一半。\\\n", + "但由于某些原因(可能是价格欺诈),到了12月第二周,同样的套装价格全都涨到了70美元到89美元不等。\\\n", + "11件套装的价格也上涨了大约10美元左右。\\\n", + "虽然外观看起来还可以,但基座上锁定刀片的部分看起来不如几年前的早期版本那么好。\\\n", + "不过我打算非常温柔地使用它,例如,\\\n", + "我会先在搅拌机中将像豆子、冰、米饭等硬物研磨,然后再制成所需的份量,\\\n", + "切换到打蛋器制作更细的面粉,或者在制作冰沙时先使用交叉切割刀片,然后使用平面刀片制作更细/不粘的效果。\\\n", + "制作冰沙时,特别提示:\\\n", + "将水果和蔬菜切碎并冷冻(如果使用菠菜,则轻轻煮软菠菜,然后冷冻直到使用;\\\n", + "如果制作果酱,则使用小到中号的食品处理器),这样可以避免在制作冰沙时添加太多冰块。\\\n", + "大约一年后,电机发出奇怪的噪音,我打电话给客服,但保修已经过期了,所以我不得不再买一个。\\\n", + "总的来说,这些产品的总体质量已经下降,因此它们依靠品牌认可和消费者忠诚度来维持销售。\\\n", + "货物在两天内到达。\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们已经使用推断课程中所学方法提取了情感,这是一个关于搅拌机的客户评价,现在我们将根据情感定制回复。\n", + "\n", + "以下述 Prompt 为例:假设你是一个客户服务 AI 助手,你的任务是为客户发送电子邮件回复,根据通过三个反引号分隔的客户电子邮件,生成一封回复以感谢客户的评价。" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "尊敬的客户,\n", + "\n", + "非常感谢您对我们产品的评价。我们非常抱歉您在购买过程中遇到了价格上涨的问题。我们一直致力于为客户提供最优惠的价格,但由于市场波动,价格可能会有所变化。我们深表歉意,如果您需要任何帮助,请随时联系我们的客户服务团队。\n", + "\n", + "我们非常感谢您对我们产品的详细评价和使用技巧。我们将会把您的反馈传达给我们的产品团队,以便改进我们的产品质量和性能。\n", + "\n", + "再次感谢您对我们的支持和反馈。如果您需要任何帮助或有任何疑问,请随时联系我们的客户服务团队。\n", + "\n", + "祝您一切顺利!\n", + "\n", + "AI客户代理\n" + ] + } + ], + "source": [ + "from tool import get_completion\n", + "\n", + "prompt = f\"\"\"\n", + "你是一位客户服务的AI助手。\n", + "你的任务是给一位重要客户发送邮件回复。\n", + "根据客户通过“```”分隔的评价,生成回复以感谢客户的评价。提醒模型使用评价中的具体细节\n", + "用简明而专业的语气写信。\n", + "作为“AI客户代理”签署电子邮件。\n", + "客户评论:\n", + "```{review}```\n", + "评论情感:{sentiment}\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 二、引入温度系数\n", + "\n", + "接下来,我们将使用语言模型的一个称为“温度” (Temperature) 的参数,它将允许我们改变模型响应的多样性。您可以将温度视为模型探索或随机性的程度。\n", + "\n", + "例如,在一个特定的短语中,“我的最爱食品”最有可能的下一个词是“比萨”,其次最有可能的是“寿司”和“塔可”。因此,在温度为零时,模型将总是选择最有可能的下一个词,而在较高的温度下,它还将选择其中一个不太可能的词,在更高的温度下,它甚至可能选择塔可,而这种可能性仅为五分之一。您可以想象,随着模型继续生成更多单词的最终响应,“我的最爱食品是比萨”将会与第一个响应“我的最爱食品是塔可”产生差异。随着模型的继续,这两个响应也将变得越来越不同。\n", + "\n", + "一般来说,在构建需要可预测响应的应用程序时,我建议**设置温度为零**。在所有课程中,我们一直设置温度为零,如果您正在尝试构建一个可靠和可预测的系统,我认为您应该选择这个温度。如果您尝试以更具创意的方式使用模型,可能需要更广泛地输出不同的结果,那么您可能需要使用更高的温度。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "同一段来信,我们提醒模型使用用户来信中的详细信息,并设置温度:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "尊敬的客户,\n", + "\n", + "感谢您对我们产品的评价。我们非常重视您的意见,并对您在使用过程中遇到的问题表示诚挚的道歉。\n", + "\n", + "我们对价格的变动深感抱歉。根据您的描述,我们了解到在12月第二周,套装的价格出现了不同程度的上涨。我们会进一步调查此事,并确保我们的定价策略更加透明和一致。\n", + "\n", + "您提到了产品部分的质量下降,特别是锁定刀片的部分。我们对此感到非常遗憾,并将反馈给我们的研发团队,以便改进产品的设计和质量控制。我们始终致力于提供优质的产品,以满足客户的需求和期望。\n", + "\n", + "此外,我们将非常感谢您分享了您对产品的使用方式和相关提示。您的经验和建议对我们来说非常宝贵,我们将考虑将其纳入我们的产品改进计划中。\n", + "\n", + "如果您需要进一步帮助或有其他问题,请随时联系我们的客户服务团队。我们将竭诚为您提供支持和解决方案。\n", + "\n", + "再次感谢您的反馈和对我们的支持。我们将继续努力提供更好的产品和服务。\n", + "\n", + "祝您一切顺利!\n", + "\n", + "AI客户代理\n" + ] + } + ], + "source": [ + "# 第一次运行\n", + "prompt = f\"\"\"\n", + "你是一名客户服务的AI助手。\n", + "你的任务是给一位重要的客户发送邮件回复。\n", + "根据通过“```”分隔的客户电子邮件生成回复,以感谢客户的评价。\n", + "如果情感是积极的或中性的,感谢他们的评价。\n", + "如果情感是消极的,道歉并建议他们联系客户服务。\n", + "请确保使用评论中的具体细节。\n", + "以简明和专业的语气写信。\n", + "以“AI客户代理”的名义签署电子邮件。\n", + "客户评价:```{review}```\n", + "评论情感:{sentiment}\n", + "\"\"\"\n", + "response = get_completion(prompt, temperature=0.7)\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "亲爱的客户,\n", + "\n", + "非常感谢您对我们产品的评价和反馈。我们非常重视您的意见,并感谢您对我们产品的支持。\n", + "\n", + "首先,我们对价格的变动感到非常抱歉给您带来了困扰。我们会认真考虑您提到的情况,并采取适当的措施来改进我们的价格策略,以避免类似情况再次发生。\n", + "\n", + "关于产品质量的问题,我们深感抱歉。我们一直致力于提供高质量的产品,并且我们会将您提到的问题反馈给我们的研发团队,以便改进产品的设计和制造过程。\n", + "\n", + "如果您需要更多关于产品保修的信息,或者对我们的其他产品有任何疑问或需求,请随时联系我们的客户服务团队。我们将竭诚为您提供帮助和支持。\n", + "\n", + "再次感谢您对我们产品的评价和支持。我们将继续努力提供优质的产品和出色的客户服务,以满足您的需求。\n", + "\n", + "祝您度过愉快的一天!\n", + "\n", + "AI客户代理\n" + ] + } + ], + "source": [ + "# 第二次运行\n", + "prompt = f\"\"\"\n", + "你是一名客户服务的AI助手。\n", + "你的任务是给一位重要的客户发送邮件回复。\n", + "根据通过“```”分隔的客户电子邮件生成回复,以感谢客户的评价。\n", + "如果情感是积极的或中性的,感谢他们的评价。\n", + "如果情感是消极的,道歉并建议他们联系客户服务。\n", + "请确保使用评论中的具体细节。\n", + "以简明和专业的语气写信。\n", + "以“AI客户代理”的名义签署电子邮件。\n", + "客户评价:```{review}```\n", + "评论情感:{sentiment}\n", + "\"\"\"\n", + "response = get_completion(prompt, temperature=0.7)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在温度为零时,每次执行相同的 Prompt ,您获得的回复理应相同。而使用温度为 0.7 时,则每次都会获得不同的输出。\n", + "\n", + "所以,您可以看到它与我们之前收到的电子邮件不同。再次执行将再次获得不同的电子邮件。\n", + "\n", + "因此,我建议您自己尝试温度,以查看输出如何变化。总之,在更高的温度下,模型的输出更加随机。您几乎可以将其视为在更高的温度下,助手**更易分心**,但也许**更有创造力**。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 三、英文版" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**1.1 定制客户邮件**" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# given the sentiment from the lesson on \"inferring\",\n", + "# and the original customer message, customize the email\n", + "sentiment = \"negative\"\n", + "\n", + "# review for a blender\n", + "review = f\"\"\"\n", + "So, they still had the 17 piece system on seasonal \\\n", + "sale for around $49 in the month of November, about \\\n", + "half off, but for some reason (call it price gouging) \\\n", + "around the second week of December the prices all went \\\n", + "up to about anywhere from between $70-$89 for the same \\\n", + "system. And the 11 piece system went up around $10 or \\\n", + "so in price also from the earlier sale price of $29. \\\n", + "So it looks okay, but if you look at the base, the part \\\n", + "where the blade locks into place doesn’t 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", + "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", + "spinach then freeze until ready for use-and if making \\\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", + "I called customer service but the warranty expired \\\n", + "already, so I had to buy another one. FYI: The overall \\\n", + "quality has gone done in these types of products, so \\\n", + "they are kind of counting on brand recognition and \\\n", + "consumer loyalty to maintain sales. Got it in about \\\n", + "two days.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dear Valued Customer,\n", + "\n", + "Thank you for taking the time to share your review with us. We appreciate your feedback and apologize for any inconvenience you may have experienced.\n", + "\n", + "We are sorry to hear about the price increase you noticed in December. We strive to provide competitive pricing for our products, and we understand your frustration. If you have any further concerns regarding pricing or any other issues, we encourage you to reach out to our customer service team. They will be more than happy to assist you.\n", + "\n", + "We also appreciate your feedback regarding the base of the system. We continuously work to improve the quality of our products, and your comments will be taken into consideration for future enhancements.\n", + "\n", + "We apologize for any inconvenience caused by the motor issue you encountered. Our customer service team is always available to assist with any warranty-related concerns. We understand that the warranty had expired, but we would still like to address this matter further. Please feel free to contact our customer service team, and they will do their best to assist you.\n", + "\n", + "Thank you once again for your review. We value your feedback and appreciate your loyalty to our brand. If you have any further questions or concerns, please do not hesitate to contact us.\n", + "\n", + "Best regards,\n", + "\n", + "AI customer agent\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "You are a customer service AI assistant.\n", + "Your task is to send an email reply to a valued customer.\n", + "Given the customer email delimited by ```, \\\n", + "Generate a reply to thank the customer for their review.\n", + "If the sentiment is positive or neutral, thank them for \\\n", + "their review.\n", + "If the sentiment is negative, apologize and suggest that \\\n", + "they can reach out to customer service. \n", + "Make sure to use specific details from the review.\n", + "Write in a concise and professional tone.\n", + "Sign the email as `AI customer agent`.\n", + "Customer review: ```{review}```\n", + "Review sentiment: {sentiment}\n", + "\"\"\"\n", + "response = get_completion(prompt)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.1 引入温度系数**" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dear Valued Customer,\n", + "\n", + "Thank you for taking the time to share your feedback with us. We sincerely apologize for any inconvenience you experienced with our pricing and the quality of our product.\n", + "\n", + "We understand your frustration regarding the price increase of our 17 piece system in December. We assure you that price gouging is not our intention, and we apologize for any confusion caused. We appreciate your loyalty and we value your feedback, as it helps us to improve our products and services.\n", + "\n", + "Regarding the issue with the blade lock and the decrease in overall quality, we apologize for any disappointment caused. We strive to provide our customers with the best possible products, and we regret that we did not meet your expectations. We will make sure to take your feedback into consideration for future improvements.\n", + "\n", + "If you require further assistance or if you have any other concerns, please do not hesitate to reach out to our customer service team. They will be more than happy to assist you in resolving any issues you may have.\n", + "\n", + "Once again, we apologize for any inconvenience caused and we appreciate your understanding. We value your business and we hope to have the opportunity to serve you better in the future.\n", + "\n", + "Best regards,\n", + "\n", + "AI customer agent\n" + ] + } + ], + "source": [ + "prompt = f\"\"\"\n", + "You are a customer service AI assistant.\n", + "Your task is to send an email reply to a valued customer.\n", + "Given the customer email delimited by ```, \\\n", + "Generate a reply to thank the customer for their review.\n", + "If the sentiment is positive or neutral, thank them for \\\n", + "their review.\n", + "If the sentiment is negative, apologize and suggest that \\\n", + "they can reach out to customer service. \n", + "Make sure to use specific details from the review.\n", + "Write in a concise and professional tone.\n", + "Sign the email as `AI customer agent`.\n", + "Customer review: ```{review}```\n", + "Review sentiment: {sentiment}\n", + "\"\"\"\n", + "response = get_completion(prompt, temperature=0.7)\n", + "print(response)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "latex_envs": { + "LaTeX_envs_menu_present": true, + "autoclose": false, + "autocomplete": true, + "bibliofile": "biblio.bib", + "cite_by": "apalike", + "current_citInitial": 1, + "eqLabelWithNumbers": true, + "eqNumInitial": 1, + "hotkeys": { + "equation": "Ctrl-E", + "itemize": "Ctrl-I" + }, + "labels_anchors": false, + "latex_user_defs": false, + "report_style_numbering": false, + "user_envs_cfg": false + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb new file mode 100644 index 0000000..b008f73 --- /dev/null +++ b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb @@ -0,0 +1,856 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a9183228-0ba6-4af9-8430-649e28868253", + "metadata": { + "id": "JMXGlIvAwn30" + }, + "source": [ + "# 第八章 聊天机器人" + ] + }, + { + "cell_type": "markdown", + "id": "f0bdc2c9", + "metadata": {}, + "source": [ + "\n", + "使用一个大型语言模型的一个令人兴奋的事情是,我们可以用它来构建一个定制的聊天机器人 (Chatbot) ,只需要很少的工作量。在这一节中,我们将探索如何利用聊天的方式,与个性化(或专门针对特定任务或行为的)聊天机器人进行扩展对话。" + ] + }, + { + "cell_type": "markdown", + "id": "e6fae355", + "metadata": {}, + "source": [ + "像 ChatGPT 这样的聊天模型实际上是组装成以一系列消息作为输入,并返回一个模型生成的消息作为输出的。这种聊天格式原本的设计目标是简便多轮对话,但我们通过之前的学习可以知道,它对于不会涉及任何对话的**单轮任务**也同样有用。\n" + ] + }, + { + "cell_type": "markdown", + "id": "78344a7e", + "metadata": {}, + "source": [ + "## 一、给定身份" + ] + }, + { + "cell_type": "markdown", + "id": "2c9b885b", + "metadata": {}, + "source": [ + "接下来,我们将定义两个辅助函数。\n", + "\n", + "第一个方法已经陪伴了您一整个教程,即 ```get_completion``` ,其适用于单轮对话。我们将 Prompt 放入某种类似**用户消息**的对话框中。另一个称为 ```get_completion_from_messages``` ,传入一个消息列表。这些消息可以来自大量不同的**角色** (roles) ,我们会描述一下这些角色。\n", + "\n", + "第一条消息中,我们以系统身份发送系统消息 (system message) ,它提供了一个总体的指示。系统消息则有助于设置助手的行为和角色,并作为对话的高级指示。你可以想象它在助手的耳边低语,引导它的回应,而用户不会注意到系统消息。因此,作为用户,如果你曾经使用过 ChatGPT,您可能从来不知道 ChatGPT 的系统消息是什么,这是有意为之的。系统消息的好处是为开发者提供了一种方法,在不让请求本身成为对话的一部分的情况下,引导助手并指导其回应。\n", + "\n", + "在 ChatGPT 网页界面中,您的消息称为用户消息,而 ChatGPT 的消息称为助手消息。但在构建聊天机器人时,在发送了系统消息之后,您的角色可以仅作为用户 (user) ;也可以在用户和助手 (assistant) 之间交替,从而提供对话上下文。" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f5308d65", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import openai\n", + "\n", + "# 下文第一个函数即tool工具包中的同名函数,此处展示出来以便于读者对比\n", + "def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", + " messages = [{\"role\": \"user\", \"content\": prompt}]\n", + " response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages=messages,\n", + " temperature=0, # 控制模型输出的随机程度\n", + " )\n", + " return response.choices[0].message[\"content\"]\n", + "\n", + "def get_completion_from_messages(messages, model=\"gpt-3.5-turbo\", temperature=0):\n", + " response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages=messages,\n", + " temperature=temperature, # 控制模型输出的随机程度\n", + " )\n", + "# print(str(response.choices[0].message))\n", + " return response.choices[0].message[\"content\"]" + ] + }, + { + "cell_type": "markdown", + "id": "46caaa5b", + "metadata": {}, + "source": [ + "现在让我们尝试在对话中使用这些消息。我们将使用上面的函数来获取从这些消息中得到的回答,同时,使用更高的温度 (temperature)(越高生成的越多样,更多内容见第七章)。\n" + ] + }, + { + "cell_type": "markdown", + "id": "e105c1b4", + "metadata": {}, + "source": [ + "### 1.1 讲笑话\n", + "\n", + "系统消息说,你是一个说话像莎士比亚的助手。这是我们向助手描述**它应该如何表现的方式**。然后,第一个用户消息是*给我讲个笑话*。接下来以助手身份给出回复是,*为什么鸡会过马路?* 最后发送用户消息是*我不知道*。" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "02b0e4d3", + "metadata": {}, + "outputs": [], + "source": [ + "# 中文\n", + "messages = [ \n", + "{'role':'system', 'content':'你是一个像莎士比亚一样说话的助手。'}, \n", + "{'role':'user', 'content':'给我讲个笑话'}, \n", + "{'role':'assistant', 'content':'鸡为什么过马路'}, \n", + "{'role':'user', 'content':'我不知道'} ]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "65f80283", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "为了到达彼岸,去追求自己的夢想! 有点儿像一个戏剧里面的人物吧,不是吗?\n" + ] + } + ], + "source": [ + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "7f51a7e0", + "metadata": {}, + "source": [ + "(注:上述例子中由于选定 temperature = 1,模型的回答会比较随机且迥异(不乏很有创意)。此处附上另一个回答:\n", + "\n", + "让我用一首莎士比亚式的诗歌来回答你的问题:\n", + "\n", + "当鸡之心欲往前,\n", + "马路之际是其选择。\n", + "驱车徐行而天晴,\n", + "鸣笛吹响伴交错。\n", + "\n", + "问之何去何从也?\n", + "因大道之上未有征,\n", + "而鸡乃跃步前进,\n", + "其决策毋需犹豫。\n", + "\n", + "鸡之智慧何可言,\n", + "道路孤独似乌漆。\n", + "然其勇气令人叹,\n", + "勇往直前没有退。\n", + "\n", + "故鸡过马路何解?\n", + "忍受车流喧嚣之困厄。\n", + "因其鸣鸣悍然一跃,\n", + "成就夸夸骄人壁画。\n", + "\n", + "所以笑话之妙处,\n", + "伴随鸡之勇气满溢。\n", + "笑谈人生不畏路,\n", + "有智有勇尽显妙。\n", + "\n", + "希望这个莎士比亚风格的回答给你带来一些欢乐!" + ] + }, + { + "cell_type": "markdown", + "id": "852b8989", + "metadata": {}, + "source": [ + "### 1.2 友好的聊天机器人" + ] + }, + { + "cell_type": "markdown", + "id": "5f76bedb", + "metadata": {}, + "source": [ + "让我们看另一个例子。助手的消息是*你是一个友好的聊天机器人*,第一个用户消息是*嗨,我叫Isa*。我们想要得到第一个用户消息。" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ca517ab0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "嗨,Isa,很高兴见到你!有什么我可以帮助你的吗?\n" + ] + } + ], + "source": [ + "# 中文\n", + "messages = [ \n", + "{'role':'system', 'content':'你是个友好的聊天机器人。'}, \n", + "{'role':'user', 'content':'Hi, 我是Isa。'} ]\n", + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "1dd6c5f8", + "metadata": {}, + "source": [ + "## 二、构建上下文" + ] + }, + { + "cell_type": "markdown", + "id": "1e9f96ba", + "metadata": {}, + "source": [ + "让我们再试一个例子。系统消息是,你是一个友好的聊天机器人,第一个用户消息是,是的,你能提醒我我的名字是什么吗?" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "a606d422", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "抱歉,我不知道您的名字,因为我们是虚拟的聊天机器人和现实生活中的人类在不同的世界中。\n" + ] + } + ], + "source": [ + "# 中文\n", + "messages = [ \n", + "{'role':'system', 'content':'你是个友好的聊天机器人。'}, \n", + "{'role':'user', 'content':'好,你能提醒我,我的名字是什么吗?'} ]\n", + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "05c65d16", + "metadata": {}, + "source": [ + "如上所见,模型实际上并不知道我的名字。\n", + "\n", + "因此,每次与语言模型的交互都互相独立,这意味着我们必须提供所有相关的消息,以便模型在当前对话中进行引用。如果想让模型引用或 “记住” 对话的早期部分,则必须在模型的输入中提供早期的交流。我们将其称为上下文 (context) 。尝试以下示例。" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "6019b1d5", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "当然可以!您的名字是Isa。\n" + ] + } + ], + "source": [ + "# 中文\n", + "messages = [ \n", + "{'role':'system', 'content':'你是个友好的聊天机器人。'},\n", + "{'role':'user', 'content':'Hi, 我是Isa'},\n", + "{'role':'assistant', 'content': \"Hi Isa! 很高兴认识你。今天有什么可以帮到你的吗?\"},\n", + "{'role':'user', 'content':'是的,你可以提醒我, 我的名字是什么?'} ]\n", + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "c1ed90a6", + "metadata": {}, + "source": [ + "现在我们已经给模型提供了上下文,也就是之前的对话中提到的我的名字,然后我们会问同样的问题,也就是我的名字是什么。因为模型有了需要的全部上下文,所以它能够做出回应,就像我们在输入的消息列表中看到的一样。" + ] + }, + { + "cell_type": "markdown", + "id": "dedba66a-58b0-40d4-b9ae-47e79ae22328", + "metadata": { + "id": "bBg_MpXeYnTq" + }, + "source": [ + "## 三、订餐机器人\n", + "\n", + "现在,我们构建一个 “订餐机器人”,我们需要它自动收集用户信息,接受比萨饼店的订单。\n", + "\n", + "### 3.1 构建机器人\n", + "\n", + "下面这个函数将收集我们的用户消息,以便我们可以避免像刚才一样手动输入。这个函数将从我们下面构建的用户界面中收集 Prompt ,然后将其附加到一个名为上下文( ```context``` )的列表中,并在每次调用模型时使用该上下文。模型的响应也会添加到上下文中,所以用户消息和模型消息都被添加到上下文中,上下文逐渐变长。这样,模型就有了需要的信息来确定下一步要做什么。" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "e76749ac", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def collect_messages(_):\n", + " prompt = inp.value_input\n", + " inp.value = ''\n", + " context.append({'role':'user', 'content':f\"{prompt}\"})\n", + " response = get_completion_from_messages(context) \n", + " context.append({'role':'assistant', 'content':f\"{response}\"})\n", + " panels.append(\n", + " pn.Row('User:', pn.pane.Markdown(prompt, width=600)))\n", + " panels.append(\n", + " pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))\n", + " \n", + " return pn.Column(*panels)" + ] + }, + { + "cell_type": "markdown", + "id": "8a3b003e", + "metadata": {}, + "source": [ + "现在,我们将设置并运行这个 UI 来显示订单机器人。初始的上下文包含了包含菜单的系统消息,在每次调用时都会使用。此后随着对话进行,上下文也会不断增长。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9f97fa0", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fdf1731b", + "metadata": {}, + "outputs": [], + "source": [ + "# 中文\n", + "import panel as pn # GUI\n", + "pn.extension()\n", + "\n", + "panels = [] # collect display \n", + "\n", + "context = [{'role':'system', 'content':\"\"\"\n", + "你是订餐机器人,为披萨餐厅自动收集订单信息。\n", + "你要首先问候顾客。然后等待用户回复收集订单信息。收集完信息需确认顾客是否还需要添加其他内容。\n", + "最后需要询问是否自取或外送,如果是外送,你要询问地址。\n", + "最后告诉顾客订单总金额,并送上祝福。\n", + "\n", + "请确保明确所有选项、附加项和尺寸,以便从菜单中识别出该项唯一的内容。\n", + "你的回应应该以简短、非常随意和友好的风格呈现。\n", + "\n", + "菜单包括:\n", + "\n", + "菜品:\n", + "意式辣香肠披萨(大、中、小) 12.95、10.00、7.00\n", + "芝士披萨(大、中、小) 10.95、9.25、6.50\n", + "茄子披萨(大、中、小) 11.95、9.75、6.75\n", + "薯条(大、小) 4.50、3.50\n", + "希腊沙拉 7.25\n", + "\n", + "配料:\n", + "奶酪 2.00\n", + "蘑菇 1.50\n", + "香肠 3.00\n", + "加拿大熏肉 3.50\n", + "AI酱 1.50\n", + "辣椒 1.00\n", + "\n", + "饮料:\n", + "可乐(大、中、小) 3.00、2.00、1.00\n", + "雪碧(大、中、小) 3.00、2.00、1.00\n", + "瓶装水 5.00\n", + "\"\"\"} ] # accumulate messages\n", + "\n", + "\n", + "inp = pn.widgets.TextInput(value=\"Hi\", placeholder='Enter text here…')\n", + "button_conversation = pn.widgets.Button(name=\"Chat!\")\n", + "\n", + "interactive_conversation = pn.bind(collect_messages, button_conversation)\n", + "\n", + "dashboard = pn.Column(\n", + " inp,\n", + " pn.Row(button_conversation),\n", + " pn.panel(interactive_conversation, loading_indicator=True, height=300),\n", + ")\n", + "\n", + "dashboard" + ] + }, + { + "cell_type": "markdown", + "id": "07d29d10", + "metadata": {}, + "source": [ + "运行如上代码可以得到一个点餐机器人,下图展示了一个点餐的完整流程:\n", + "\n", + "![image.png](../../../figures/docs/C1/Chatbot-pizza-cn.png)" + ] + }, + { + "cell_type": "markdown", + "id": "668ea96d", + "metadata": {}, + "source": [ + "### 3.2 创建JSON摘要" + ] + }, + { + "cell_type": "markdown", + "id": "2a2c9822", + "metadata": {}, + "source": [ + "此处我们另外要求模型创建一个 JSON 摘要,方便我们发送给订单系统。\n", + "\n", + "因此我们需要在上下文的基础上追加另一个系统消息,作为另一条指示 (instruction) 。我们说*创建一个刚刚订单的 JSON 摘要,列出每个项目的价格,字段应包括 1)披萨,包括尺寸,2)配料列表,3)饮料列表,4)辅菜列表,包括尺寸,最后是总价格*。此处也可以定义为用户消息,不一定是系统消息。\n", + "\n", + "请注意,这里我们使用了一个较低的温度,因为对于这些类型的任务,我们希望输出相对可预测。" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "c840ff56", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"披萨\": {\n", + " \"意式辣香肠披萨\": {\n", + " \"大\": 12.95,\n", + " \"中\": 10.00,\n", + " \"小\": 7.00\n", + " },\n", + " \"芝士披萨\": {\n", + " \"大\": 10.95,\n", + " \"中\": 9.25,\n", + " \"小\": 6.50\n", + " },\n", + " \"茄子披萨\": {\n", + " \"大\": 11.95,\n", + " \"中\": 9.75,\n", + " \"小\": 6.75\n", + " }\n", + " },\n", + " \"配料\": {\n", + " \"奶酪\": 2.00,\n", + " \"蘑菇\": 1.50,\n", + " \"香肠\": 3.00,\n", + " \"加拿大熏肉\": 3.50,\n", + " \"AI酱\": 1.50,\n", + " \"辣椒\": 1.00\n", + " },\n", + " \"饮料\": {\n", + " \"可乐\": {\n", + " \"大\": 3.00,\n", + " \"中\": 2.00,\n", + " \"小\": 1.00\n", + " },\n", + " \"雪碧\": {\n", + " \"大\": 3.00,\n", + " \"中\": 2.00,\n", + " \"小\": 1.00\n", + " },\n", + " \"瓶装水\": 5.00\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "messages = context.copy()\n", + "messages.append(\n", + "{'role':'system', 'content':\n", + "'''创建上一个食品订单的 json 摘要。\\\n", + "逐项列出每件商品的价格,字段应该是 1) 披萨,包括大小 2) 配料列表 3) 饮料列表,包括大小 4) 配菜列表包括大小 5) 总价\n", + "你应该给我返回一个可解析的Json对象,包括上述字段'''}, \n", + ")\n", + "\n", + "response = get_completion_from_messages(messages, temperature=0)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "ef17c2b2", + "metadata": {}, + "source": [ + "现在,我们已经建立了自己的订餐聊天机器人。请随意自定义并修改系统消息,以更改聊天机器人的行为,并使其扮演不同的角色,拥有不同的知识。" + ] + }, + { + "cell_type": "markdown", + "id": "2764c8a0", + "metadata": {}, + "source": [ + "## 三、英文版" + ] + }, + { + "cell_type": "markdown", + "id": "123f2066", + "metadata": {}, + "source": [ + "**1.1 讲笑话**" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "c9dff513", + "metadata": {}, + "outputs": [], + "source": [ + "messages = [ \n", + "{'role':'system', 'content':'You are an assistant that speaks like Shakespeare.'}, \n", + "{'role':'user', 'content':'tell me a joke'}, \n", + "{'role':'assistant', 'content':'Why did the chicken cross the road'}, \n", + "{'role':'user', 'content':'I don\\'t know'} ]" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "381e14c1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "To get to the other side, methinks!\n" + ] + } + ], + "source": [ + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "028656a1", + "metadata": {}, + "source": [ + "**1.2 友好的聊天机器人**" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "8205c007", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello Isa! How can I assist you today?\n" + ] + } + ], + "source": [ + "messages = [ \n", + "{'role':'system', 'content':'You are friendly chatbot.'}, \n", + "{'role':'user', 'content':'Hi, my name is Isa'} ]\n", + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "81f0d22d", + "metadata": {}, + "source": [ + "**2.1 构建上下文**" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "97296cdd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I'm sorry, but as a chatbot, I do not have access to personal information or memory. I cannot remind you of your name.\n" + ] + } + ], + "source": [ + "messages = [ \n", + "{'role':'system', 'content':'You are friendly chatbot.'}, \n", + "{'role':'user', 'content':'Yes, can you remind me, What is my name?'} ]\n", + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "5ab959d0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your name is Isa! How can I assist you further, Isa?\n" + ] + } + ], + "source": [ + "messages = [ \n", + "{'role':'system', 'content':'You are friendly chatbot.'},\n", + "{'role':'user', 'content':'Hi, my name is Isa'},\n", + "{'role':'assistant', 'content': \"Hi Isa! It's nice to meet you. \\\n", + "Is there anything I can help you with today?\"},\n", + "{'role':'user', 'content':'Yes, you can remind me, What is my name?'} ]\n", + "response = get_completion_from_messages(messages, temperature=1)\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "a93897fc", + "metadata": {}, + "source": [ + "**3.1 构建机器人**" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "9d93bc09", + "metadata": {}, + "outputs": [], + "source": [ + "def collect_messages(_):\n", + " prompt = inp.value_input\n", + " inp.value = ''\n", + " context.append({'role':'user', 'content':f\"{prompt}\"})\n", + " response = get_completion_from_messages(context) \n", + " context.append({'role':'assistant', 'content':f\"{response}\"})\n", + " panels.append(\n", + " pn.Row('User:', pn.pane.Markdown(prompt, width=600)))\n", + " panels.append(\n", + " pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))\n", + " \n", + " return pn.Column(*panels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8138c4ac", + "metadata": {}, + "outputs": [], + "source": [ + "import panel as pn # GUI\n", + "pn.extension()\n", + "\n", + "panels = [] # collect display \n", + "\n", + "context = [ {'role':'system', 'content':\"\"\"\n", + "You are OrderBot, an automated service to collect orders for a pizza restaurant. \\\n", + "You first greet the customer, then collects the order, \\\n", + "and then asks if it's a pickup or delivery. \\\n", + "You wait to collect the entire order, then summarize it and check for a final \\\n", + "time if the customer wants to add anything else. \\\n", + "If it's a delivery, you ask for an address. \\\n", + "Finally you collect the payment.\\\n", + "Make sure to clarify all options, extras and sizes to uniquely \\\n", + "identify the item from the menu.\\\n", + "You respond in a short, very conversational friendly style. \\\n", + "The menu includes \\\n", + "pepperoni pizza 12.95, 10.00, 7.00 \\\n", + "cheese pizza 10.95, 9.25, 6.50 \\\n", + "eggplant pizza 11.95, 9.75, 6.75 \\\n", + "fries 4.50, 3.50 \\\n", + "greek salad 7.25 \\\n", + "Toppings: \\\n", + "extra cheese 2.00, \\\n", + "mushrooms 1.50 \\\n", + "sausage 3.00 \\\n", + "canadian bacon 3.50 \\\n", + "AI sauce 1.50 \\\n", + "peppers 1.00 \\\n", + "Drinks: \\\n", + "coke 3.00, 2.00, 1.00 \\\n", + "sprite 3.00, 2.00, 1.00 \\\n", + "bottled water 5.00 \\\n", + "\"\"\"} ] # accumulate messages\n", + "\n", + "\n", + "inp = pn.widgets.TextInput(value=\"Hi\", placeholder='Enter text here…')\n", + "button_conversation = pn.widgets.Button(name=\"Chat!\")\n", + "\n", + "interactive_conversation = pn.bind(collect_messages, button_conversation)\n", + "\n", + "dashboard = pn.Column(\n", + " inp,\n", + " pn.Row(button_conversation),\n", + " pn.panel(interactive_conversation, loading_indicator=True, height=300),\n", + ")\n", + "\n", + "dashboard" + ] + }, + { + "cell_type": "markdown", + "id": "93944944", + "metadata": {}, + "source": [ + "**3.2 创建Json摘要**" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "b779dd04", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sure! Here's a JSON summary of your food order:\n", + "\n", + "{\n", + " \"pizza\": {\n", + " \"type\": \"pepperoni\",\n", + " \"size\": \"large\"\n", + " },\n", + " \"toppings\": [\n", + " \"extra cheese\",\n", + " \"mushrooms\"\n", + " ],\n", + " \"drinks\": [\n", + " {\n", + " \"type\": \"coke\",\n", + " \"size\": \"medium\"\n", + " },\n", + " {\n", + " \"type\": \"sprite\",\n", + " \"size\": \"small\"\n", + " }\n", + " ],\n", + " \"sides\": [\n", + " {\n", + " \"type\": \"fries\",\n", + " \"size\": \"regular\"\n", + " }\n", + " ],\n", + " \"total_price\": 29.45\n", + "}\n", + "\n", + "Please let me know if there's anything else you'd like to add or modify.\n" + ] + } + ], + "source": [ + "messages = context.copy()\n", + "messages.append(\n", + "{'role':'system', 'content':'create a json summary of the previous food order. Itemize the price for each item\\\n", + " The fields should be 1) pizza, include size 2) list of toppings 3) list of drinks, include size 4) list of sides include size 5)total price '}, \n", + ")\n", + "response = get_completion_from_messages(messages, temperature=0)\n", + "print(response)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "latex_envs": { + "LaTeX_envs_menu_present": true, + "autoclose": false, + "autocomplete": true, + "bibliofile": "biblio.bib", + "cite_by": "apalike", + "current_citInitial": 1, + "eqLabelWithNumbers": true, + "eqNumInitial": 1, + "hotkeys": { + "equation": "Ctrl-E", + "itemize": "Ctrl-I" + }, + "labels_anchors": false, + "latex_user_defs": false, + "report_style_numbering": false, + "user_envs_cfg": false + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "277px" + }, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/figures/docs/C1/Chatbot-pizza-cn.png b/figures/docs/C1/Chatbot-pizza-cn.png new file mode 100644 index 0000000000000000000000000000000000000000..54807ebbeb4b0fe8903070171a24a780b270e31a GIT binary patch literal 285890 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

ZEQON}|Rt#fRKMch2&BXF+hc|NE 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 z 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 An*aa+ literal 0 HcmV?d00001 From 7df56698646d7ca5f98c7e8762749c16f385b3c9 Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sun, 23 Jul 2023 13:20:49 +0800 Subject: [PATCH 10/13] =?UTF-8?q?Update=205.=20=E6=8E=A8=E6=96=AD=20Inferr?= =?UTF-8?q?ing.ipynb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../5. 推断 Inferring.ipynb | 188 +++++++++--------- 1 file changed, 97 insertions(+), 91 deletions(-) diff --git a/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb b/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb index f0c549f..ce9cd7e 100644 --- a/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb +++ b/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb @@ -5,10 +5,7 @@ "id": "3630c235-f891-4874-bd0a-5277d4d6aa82", "metadata": {}, "source": [ - "# 第五章 推断\n", - "\n", - "在这节课中,你将从产品评论和新闻文章中推断情感和主题。\n", - "\n" + "# 第五章 推断" ] }, { @@ -16,10 +13,13 @@ "id": "5f3abbee", "metadata": {}, "source": [ + "在这一章中,我们将通过一个故事,引领你了解如何从产品评价和新闻文章中推导出情感和主题。\n", "\n", - "推断任务可以看作是模型接收文本作为输入,并执行某种分析的过程。其中涉及提取标签、提取实体、理解文本情感等等。如果你想要从一段文本中提取正面或负面情感,在传统的机器学习工作流程中,需要收集标签数据集、训练模型、确定如何在云端部署模型并进行推断。这样做可能效果还不错,但是执行全流程需要很多工作。而且对于每个任务,如情感分析、提取实体等等,都需要训练和部署单独的模型。\n", + "让我们先想象一下,你是一名初创公司的数据分析师,你的任务是从各种产品评论和新闻文章中提取出关键的情感和主题。这些任务包括了标签提取、实体提取、以及理解文本的情感等等。在传统的机器学习流程中,你需要收集标签化的数据集、训练模型、确定如何在云端部署模型并进行推断。尽管这种方式可能会产生不错的效果,但完成这一全流程需要耗费大量的时间和精力。而且,每一个任务,比如情感分析、实体提取等等,都需要训练和部署单独的模型。\n", "\n", - "LLM 的一个非常好的特点是,对于许多这样的任务,你只需要编写一个 Prompt 即可开始产出结果,而不需要进行大量的工作。这极大地加快了应用程序开发的速度。你还可以只使用一个模型和一个 API 来执行许多不同的任务,而不需要弄清楚如何训练和部署许多不同的模型。" + "然而,就在你准备投入繁重工作的时候,你发现了大型语言模型(LLM)。LLM的一个明显优点是,对于许多这样的任务,你只需要编写一个 Prompt,就可以开始生成结果,大大减轻了你的工作负担。这个发现像是找到了一把神奇的钥匙,让应用程序开发的速度加快了许多。最令你兴奋的是,你可以仅仅使用一个模型和一个API来执行许多不同的任务,无需再纠结如何训练和部署许多不同的模型。\n", + "\n", + "让我们开始这一章的学习,一起探索如何利用LLM加快我们的工作进程,提高我们的工作效率。" ] }, { @@ -27,11 +27,23 @@ "id": "51d2fdfa-c99f-4750-8574-dba7712cd7f0", "metadata": {}, "source": [ - "## 一、情感推断\n", - "\n", - "### 1.1 情感倾向分析\n", - "\n", - "以电商平台关于一盏台灯的评论为例,可以对其传达的情感进行二分类(正向/负向)。" + "## 一、情感推断" + ] + }, + { + "cell_type": "markdown", + "id": "ffc63a4b", + "metadata": {}, + "source": [ + "### 1.1 情感倾向分析" + ] + }, + { + "cell_type": "markdown", + "id": "21767f0b", + "metadata": {}, + "source": [ + "让我们以一则电商平台上的台灯评论为例,通过此例,我们将学习如何对评论进行情感二分类(正面/负面)。" ] }, { @@ -49,20 +61,14 @@ "\"\"\"" ] }, - { - "cell_type": "markdown", - "id": "cc4ec4ca", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "30d6e4bd-3337-45a3-8c99-a734cdd06743", "metadata": {}, "source": [ - "现在让我们来编写一个 Prompt 来分类这个评论的情感。如果我想让系统告诉我这个评论的情感是什么,只需要编写 “以下产品评论的情感是什么” 这个 Prompt ,加上通常的分隔符和评论文本等等。\n", + "接下来,我们将尝试编写一个 Prompt ,用以分类这条商品评论的情感。如果我们想让系统解析这条评论的情感倾向,只需编写“以下商品评论的情感倾向是什么?”这样的 Prompt ,再加上一些标准的分隔符和评论文本等。\n", "\n", - "然后让我们运行一下。结果显示这个产品评论的情感是积极的,这似乎是非常正确的。虽然这盏台灯不完美,但这个客户似乎非常满意。这似乎是一家关心客户和产品的伟大公司,可以认为积极的情感似乎是正确的答案。" + "然后,我们将这个程序运行一遍。结果表明,这条商品评论的情感倾向是正面的,这似乎非常准确。尽管这款台灯并非完美无缺,但是这位顾客对它似乎相当满意。这个公司看起来非常重视客户体验和产品质量,因此,认定评论的情感倾向为正面似乎是正确的判断。" ] }, { @@ -91,12 +97,6 @@ "print(response)" ] }, - { - "cell_type": "markdown", - "id": "a562e656", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "76be2320", @@ -136,9 +136,15 @@ "id": "81d2a973-1fa4-4a35-ae35-a2e746c0e91b", "metadata": {}, "source": [ - "### 2.2 识别情感类型\n", - "\n", - "仍然使用台灯评论,我们尝试另一个 Prompt 。这次我需要模型识别出评论作者所表达的情感,并归纳为列表,不超过五项。" + "### 2.2 识别情感类型" + ] + }, + { + "cell_type": "markdown", + "id": "c696daa9", + "metadata": {}, + "source": [ + "接下来,我们将继续使用之前的台灯评论,但这次我们会试用一个新的 Prompt 。我们希望模型能够识别出评论作者所表达的情感,并且将这些情感整理为一个不超过五项的列表。" ] }, { @@ -166,12 +172,6 @@ "print(response)" ] }, - { - "cell_type": "markdown", - "id": "c7743a53", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "cc4444f7", @@ -187,7 +187,7 @@ "source": [ "### 1.3 识别愤怒\n", "\n", - "对于很多企业来说,了解某个顾客是否非常生气很重要。所以产生了下述分类问题:以下评论的作者是否表达了愤怒情绪?因为如果有人真的很生气,那么可能值得额外关注,让客户支持或客户成功团队联系客户以了解情况,并为客户解决问题。" + "对于许多企业来说,洞察到顾客的愤怒情绪是至关重要的。这就引出了一个分类问题:下述的评论作者是否流露出了愤怒?因为如果有人真的情绪激动,那可能就意味着需要给予额外的关注,因为每一个愤怒的顾客都是一个改进服务的机会,也是一个提升公司口碑的机会。这时,客户支持或者客服团队就应该介入,与客户接触,了解具体情况,然后解决他们的问题。" ] }, { @@ -215,12 +215,6 @@ "print(response)" ] }, - { - "cell_type": "markdown", - "id": "77905fd8", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "11ca57a2", @@ -234,15 +228,27 @@ "id": "936a771e-ca78-4e55-8088-2da6f3820ddc", "metadata": {}, "source": [ - "## 二、信息提取\n", + "## 二、信息提取" + ] + }, + { + "cell_type": "markdown", + "id": "506264c6", + "metadata": {}, + "source": [ + "### 2.1 商品信息提取 " + ] + }, + { + "cell_type": "markdown", + "id": "af474353", + "metadata": {}, + "source": [ + "下一步,我们将深入挖掘客户评论中的丰富信息。信息提取是自然语言处理(NLP)的重要组成部分,它帮助我们从文本中抽取特定的、我们关心的信息。在接下来的示例中,我们将要求模型识别两个关键元素:购买的商品和商品的制造商。\n", "\n", - "### 2.1 商品信息提取 \n", + "想象一下,如果你正在尝试分析一个在线电商网站上的众多评论,了解评论中提到的商品是什么、由谁制造,以及相关的积极或消极情绪,将极大地帮助你追踪特定商品或制造商在用户心中的情感趋势。\n", "\n", - "接下来,让我们从客户评论中提取更丰富的信息。信息提取是自然语言处理(NLP)的一部分,与从文本中提取你想要知道的某些事物相关。因此,在这个 Prompt 中,我要求它识别以下内容:购买物品和制造物品的公司名称。\n", - "\n", - "同样,如果你试图总结在线购物电子商务网站的许多评论,对于这些评论来说,弄清楚是什么物品、谁制造了该物品,弄清楚积极和消极的情感,有助于追踪特定物品或制造商收获的用户情感趋势。\n", - "\n", - "在下面这个示例中,我们要求它将响应格式化为一个 JSON 对象,其中物品和品牌作为键。" + "在接下来的示例中,我们会要求模型将回应以一个 JSON 对象的形式呈现,其中的 key 就是商品和品牌。" ] }, { @@ -272,19 +278,13 @@ "评论文本用三个反引号分隔。将你的响应格式化为以 “物品” 和 “品牌” 为键的 JSON 对象。\n", "如果信息不存在,请使用 “未知” 作为值。\n", "让你的回应尽可能简短。\n", - " \n", + "\n", "评论文本: ```{lamp_review}```\n", "\"\"\"\n", "response = get_completion(prompt)\n", "print(response)" ] }, - { - "cell_type": "markdown", - "id": "1342c732", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "954d125d", @@ -298,9 +298,15 @@ "id": "a38880a5-088f-4609-9913-f8fa41fb7ba0", "metadata": {}, "source": [ - "### 2.2 综合情感推断和信息提取\n", - "\n", - "提取上述所有信息使用了 3 或 4 个 Prompt ,但实际上可以编写单个 Prompt 来同时提取所有这些信息。" + "### 2.2 综合情感推断和信息提取" + ] + }, + { + "cell_type": "markdown", + "id": "6d7a4474", + "metadata": {}, + "source": [ + "在上面小节中,我们采用了三至四个 Prompt 来提取评论中的“情绪倾向”、“是否生气”、“物品类型”和“品牌”等信息。然而,事实上,我们可以设计一个单一的 Prompt ,来同时提取所有这些信息。" ] }, { @@ -333,10 +339,10 @@ "- 评论者购买的物品\n", "- 制造该物品的公司\n", "\n", - "评论用三个反引号分隔。将您的响应格式化为 JSON 对象,以 “情感倾向”、“是否生气”、“物品类型” 和 “品牌” 作为键。\n", + "评论用三个反引号分隔。将你的响应格式化为 JSON 对象,以 “情感倾向”、“是否生气”、“物品类型” 和 “品牌” 作为键。\n", "如果信息不存在,请使用 “未知” 作为值。\n", "让你的回应尽可能简短。\n", - "将 Anger 值格式化为布尔值。\n", + "将 “是否生气” 值格式化为布尔值。\n", "\n", "评论文本: ```{lamp_review}```\n", "\"\"\"\n", @@ -349,7 +355,7 @@ "id": "5e09a673", "metadata": {}, "source": [ - "这个例子中,我们告诉它将愤怒值格式化为布尔值,然后输出一个 JSON。您可以自己尝试不同的变化,或者甚至尝试完全不同的评论,看看是否仍然可以准确地提取这些内容。" + "这个例子中,我们指导 LLM 将“是否生气”的情况格式化为布尔值,并输出 JSON 格式。你可以尝试对格式化模式进行各种变化,或者使用完全不同的评论来试验,看看 LLM 是否仍然可以准确地提取这些内容。" ] }, { @@ -357,9 +363,15 @@ "id": "235fc223-2c89-49ec-ac2d-78a8e74a43ac", "metadata": {}, "source": [ - "## 三、主题推断\n", - "\n", - "大型语言模型的另一个很酷的应用是推断主题。给定一段长文本,这段文本是关于什么的?有什么话题?以以下一段虚构的报纸报道为例。" + "## 三、主题推断" + ] + }, + { + "cell_type": "markdown", + "id": "1386570b", + "metadata": {}, + "source": [ + "大型语言模型的另一个很酷的应用是推断主题。假设我们有一段长文本,我们如何判断这段文本的主旨是什么?它涉及了哪些主题?让我们通过以下一段虚构的报纸报道来具体了解一下。" ] }, { @@ -391,9 +403,15 @@ "id": "a8ea91d6-e841-4ee2-bed9-ca4a36df177f", "metadata": {}, "source": [ - "### 3.1 推断讨论主题\n", - "\n", - "上面是一篇虚构的关于政府工作人员对他们工作机构感受的报纸文章。我们可以让它确定五个正在讨论的主题,用一两个字描述每个主题,并将输出格式化为逗号分隔的列表。" + "### 3.1 推断讨论主题" + ] + }, + { + "cell_type": "markdown", + "id": "a76f21f5", + "metadata": {}, + "source": [ + "以上是一篇关于政府员工对其工作单位感受的虚构报纸文章。我们可以要求大语言模型确定其中讨论的五个主题,并用一两个词语概括每个主题。输出结果将会以逗号分隔的Python列表形式呈现。" ] }, { @@ -425,20 +443,20 @@ "print(response)" ] }, - { - "cell_type": "markdown", - "id": "790d1435", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "34be1d2a-1309-4512-841a-b6f67338938b", "metadata": {}, "source": [ - "### 3.2 为特定主题制作新闻提醒\n", - "\n", - "假设我们有一个新闻网站或类似的东西,这是我们感兴趣的主题:NASA、地方政府、工程、员工满意度、联邦政府等。假设我们想弄清楚,针对一篇新闻文章,其中涵盖了哪些主题。可以使用这样的prompt:确定以下主题列表中的每个项目是否是以下文本中的主题。以 0 或 1 的形式给出答案列表。" + "### 3.2 为特定主题制作新闻提醒" + ] + }, + { + "cell_type": "markdown", + "id": "95b636f1", + "metadata": {}, + "source": [ + "假设我们有一个新闻网站或类似的平台,这是我们感兴趣的主题:美国航空航天局、当地政府、工程、员工满意度、联邦政府等。我们想要分析一篇新闻文章,理解其包含了哪些主题。可以使用这样的prompt:确定以下主题列表中的每个项目是否是以下文本中的主题。以 0 或 1 的形式给出答案列表。" ] }, { @@ -476,20 +494,14 @@ "print(response)" ] }, - { - "cell_type": "markdown", - "id": "8f39f24a", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "08247dbf", "metadata": {}, "source": [ - "有结果可见,这个故事是与关于 NASA 、员工满意度、联邦政府有关,而与当地政府的、工程学无关。这在机器学习中有时被称为 Zero-Shot (零样本)学习算法,因为我们没有给它任何标记的训练数据。仅凭 Prompt ,它就能确定哪些主题在新闻文章中有所涵盖。\n", + "从输出结果来看,这个`story`与关于“美国航空航天局”、“员工满意度”、“联邦政府”、“当地政府”有关,而与“工程”无关。这种能力在机器学习领域被称为零样本(Zero-Shot)学习。这是因为我们并没有提供任何带标签的训练数据,仅凭 Prompt ,它便能判定哪些主题在新闻文章中被包含。\n", "\n", - "如果我们想生成一个新闻提醒,也可以使用这个处理新闻的过程。假设我非常喜欢 NASA 所做的工作,就可以构建一个这样的系统,每当 NASA 新闻出现时,输出提醒。" + "如果我们希望制定一个新闻提醒,我们同样可以运用这种处理新闻的流程。假设我对“美国航空航天局”的工作深感兴趣,那么你就可以构建一个如此的系统:每当出现与'美国宇航局'相关的新闻,系统就会输出提醒。" ] }, { @@ -515,18 +527,12 @@ " print(\"提醒: 关于美国航空航天局的新消息\")" ] }, - { - "cell_type": "markdown", - "id": "9fc2c643", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "76ccd189", "metadata": {}, "source": [ - "这就是关于推断的全部内容了,仅用几分钟时间,我们就可以构建多个用于对文本进行推理的系统,而以前则需要熟练的机器学习开发人员数天甚至数周的时间。这非常令人兴奋,无论是对于熟练的机器学习开发人员,还是对于新手来说,都可以使用 Prompt 来非常快速地构建和开始相当复杂的自然语言处理任务。" + "这就是我们关于推断的全面介绍。在短短几分钟内,我们已经能够建立多个用于文本推理的系统,这是以前需要机器学习专家数天甚至数周时间才能完成的任务。这一变化无疑是令人兴奋的,因为无论你是经验丰富的机器学习开发者,还是刚入门的新手,都能利用输入 Prompt 快速建立并启动复杂的自然语言处理任务。" ] }, { From ca879c4429a6a25fbbe00d85e1207f79b58a06f0 Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sun, 23 Jul 2023 15:58:41 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AC=AC=E5=9B=9B?= =?UTF-8?q?=E3=80=81=E4=BA=94=E7=AB=A0=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=AC=AC?= =?UTF-8?q?=E5=85=AB=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../4. 文本概括 Summarizing.ipynb | 2 +- .../5. 推断 Inferring.ipynb | 4 +- .../8. 聊天机器人 Chatbot.ipynb | 67 ++++++++++++++----- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb b/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb index 66c9cb7..cef2062 100644 --- a/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb +++ b/docs/content/C1 Prompt Engineering for Developer/4. 文本概括 Summarizing.ipynb @@ -1 +1 @@ -{"cells":[{"attachments":{},"cell_type":"markdown","id":"b58204ea","metadata":{},"source":["# 第四章 文本概括\n"]},{"attachments":{},"cell_type":"markdown","id":"12fa9ea4","metadata":{},"source":["在繁忙的信息时代,小明是一名热心的开发者,面临着海量的文本信息处理的挑战。他需要通过研究无数的文献资料来为他的项目找到关键的信息,但是时间却远远不够。在他焦头烂额之际,他发现了大型语言模型(LLM)的文本摘要功能。\n","\n","这个功能对小明来说如同灯塔一样,照亮了他处理信息海洋的道路。LLM的强大能力在于它可以将复杂的文本信息简化,提炼出关键的观点,这对于他来说无疑是巨大的帮助。他不再需要花费大量的时间去阅读所有的文档,只需要用LLM将它们概括,就可以快速获取到他所需要的信息。\n","\n","通过编程调用API接口,小明成功实现了这个文本摘要的功能。他感叹道:“这简直就像一道魔法,将无尽的信息海洋变成了清晰的信息源泉。”小明的经历,展现了LLM文本摘要功能的巨大优势:**节省时间**,**提高效率**,以及**精准获取信息**。这就是我们本章要介绍的内容,让我们一起来探索如何利用编程和调用API接口,掌握这个强大的工具。"]},{"attachments":{},"cell_type":"markdown","id":"9cca835b","metadata":{},"source":["## 一、单一文本概括"]},{"attachments":{},"cell_type":"markdown","id":"0c1e1b92","metadata":{},"source":["以商品评论的总结任务为例:对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。"]},{"attachments":{},"cell_type":"markdown","id":"aad5bd2a","metadata":{},"source":["**输入文本**"]},{"cell_type":"markdown","id":"11c360ae","metadata":{},"source":["这是一段在线商品评价,可能来自于一个在线购物平台,例如亚马逊、淘宝、京东等。评价者为一款熊猫公仔进行了点评,评价内容包括商品的质量、大小、价格和物流速度等因素,以及他的女儿对该商品的喜爱程度。"]},{"cell_type":"code","execution_count":2,"id":"43b5dd25","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","这个熊猫公仔是我给女儿的生日礼物,她很喜欢,去哪都带着。\n","公仔很软,超级可爱,面部表情也很和善。但是相比于价钱来说,\n","它有点小,我感觉在别的地方用同样的价钱能买到更大的。\n","快递比预期提前了一天到货,所以在送给女儿之前,我自己玩了会。\n","\"\"\""]},{"attachments":{},"cell_type":"markdown","id":"662c9cd2","metadata":{},"source":["### 1.1 限制输出文本长度"]},{"attachments":{},"cell_type":"markdown","id":"a6d10814","metadata":{},"source":["我们尝试将文本的长度限制在30个字以内。"]},{"cell_type":"code","execution_count":5,"id":"bf4b39f9","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["熊猫公仔软可爱,女儿喜欢,但有点小。快递提前一天到货。\n"]}],"source":["from tool import get_completion\n","\n","prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个字。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"fce32884","metadata":{},"source":["我们可以看到语言模型给了我们一个符合要求的结果。\n","\n","注意:在上一节中我们提到了语言模型在计算和判断文本长度时依赖于分词器,而分词器在字符统计方面不具备完美精度。"]},{"attachments":{},"cell_type":"markdown","id":"e9ab145e","metadata":{},"source":["### 1.2 设置关键角度侧重"]},{"attachments":{},"cell_type":"markdown","id":"f84d0123","metadata":{},"source":["在某些情况下,我们会针对不同的业务场景对文本的侧重会有所不同。例如,在商品评论文本中,物流部门可能更专注于运输的时效性,商家则更关注价格和商品质量,而平台则更看重整体的用户体验。\n","\n","我们可以通过增强输入提示(Prompt),来强调我们对某一特定视角的重视。"]},{"attachments":{},"cell_type":"markdown","id":"d6f8509a","metadata":{},"source":["#### 1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":7,"id":"80636c3e","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["快递提前到货,公仔可爱但有点小。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个字,并且侧重在快递服务上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"76c97fea","metadata":{},"source":["通过输出结果,我们可以看到,文本以“快递提前到货”开头,体现了对于快递效率的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"83275907","metadata":{},"source":["#### 1.2.2 侧重于价格与质量"]},{"cell_type":"code","execution_count":8,"id":"728d6c57","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["可爱的熊猫公仔,质量好但有点小,价格稍高。快递提前到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个词汇,并且侧重在产品价格和质量上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"972dbb1b","metadata":{},"source":["通过输出的结果,我们可以看到,文本以“可爱的熊猫公仔,质量好但有点小,价格稍高”开头,体现了对于产品价格与质量的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"b3ed53d2","metadata":{},"source":["### 1.3 关键信息提取"]},{"attachments":{},"cell_type":"markdown","id":"ba6f5c25","metadata":{},"source":["在1.2节中,虽然我们通过添加关键角度侧重的 Prompt ,确实让文本摘要更侧重于某一特定方面,然而,我们可以发现,在结果中也会保留一些其他信息,比如偏重价格与质量角度的概括中仍保留了“快递提前到货”的信息。如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,则可以要求 LLM 进行“**文本提取( Extract )**”而非“概括( Summarize )”"]},{"cell_type":"markdown","id":"da39760c","metadata":{},"source":["下面让我们来一起来对文本进行提取信息吧"]},{"cell_type":"code","execution_count":9,"id":"c845ccab","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["产品运输相关的信息:快递提前一天到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上的产品评论中提取相关信息。\n","\n","请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"50498a2b","metadata":{},"source":["## 二、同时概括多条文本"]},{"attachments":{},"cell_type":"markdown","id":"a291541a","metadata":{},"source":["在实际的工作流中,我们往往要处理大量的评论文本,下面的示例将多条用户评价集合在一个列表中,并利用 ```for``` 循环和文本概括(Summarize)提示词,将评价概括至小于 20 个词以下,并按顺序打印。当然,在实际生产中,对于不同规模的评论文本,除了使用 ```for``` 循环以外,还可能需要考虑整合评论、分布式等方法提升运算效率。您可以搭建主控面板,来总结大量用户评论,以及方便您或他人快速浏览,还可以点击查看原评论。这样,您就能高效掌握顾客的所有想法。"]},{"cell_type":"code","execution_count":3,"id":"ef606961","metadata":{},"outputs":[],"source":["review_1 = prod_review\n","\n","# 一盏落地灯的评论\n","review_2 = \"\"\"\n","我需要一盏漂亮的卧室灯,这款灯不仅具备额外的储物功能,价格也并不算太高。\n","收货速度非常快,仅用了两天的时间就送到了。\n","不过,在运输过程中,灯的拉线出了问题,幸好,公司很乐意寄送了一根全新的灯线。\n","新的灯线也很快就送到手了,只用了几天的时间。\n","装配非常容易。然而,之后我发现有一个零件丢失了,于是我联系了客服,他们迅速地给我寄来了缺失的零件!\n","对我来说,这是一家非常关心客户和产品的优秀公司。\n","\"\"\"\n","\n","# 一把电动牙刷的评论\n","review_3 = \"\"\"\n","我的牙科卫生员推荐了电动牙刷,所以我就买了这款。\n","到目前为止,电池续航表现相当不错。\n","初次充电后,我在第一周一直将充电器插着,为的是对电池进行条件养护。\n","过去的3周里,我每天早晚都使用它刷牙,但电池依然维持着原来的充电状态。\n","不过,牙刷头太小了。我见过比这个牙刷头还大的婴儿牙刷。\n","我希望牙刷头更大一些,带有不同长度的刷毛,\n","这样可以更好地清洁牙齿间的空隙,但这款牙刷做不到。\n","总的来说,如果你能以50美元左右的价格购买到这款牙刷,那是一个不错的交易。\n","制造商的替换刷头相当昂贵,但你可以购买价格更为合理的通用刷头。\n","这款牙刷让我感觉就像每天都去了一次牙医,我的牙齿感觉非常干净!\n","\"\"\"\n","\n","# 一台搅拌机的评论\n","review_4 = \"\"\"\n","在11月份期间,这个17件套装还在季节性促销中,售价约为49美元,打了五折左右。\n","可是由于某种原因(我们可以称之为价格上涨),到了12月的第二周,所有的价格都上涨了,\n","同样的套装价格涨到了70-89美元不等。而11件套装的价格也从之前的29美元上涨了约10美元。\n","看起来还算不错,但是如果你仔细看底座,刀片锁定的部分看起来没有前几年版本的那么漂亮。\n","然而,我打算非常小心地使用它\n","(例如,我会先在搅拌机中研磨豆类、冰块、大米等坚硬的食物,然后再将它们研磨成所需的粒度,\n","接着切换到打蛋器刀片以获得更细的面粉,如果我需要制作更细腻/少果肉的食物)。\n","在制作冰沙时,我会将要使用的水果和蔬菜切成细小块并冷冻\n","(如果使用菠菜,我会先轻微煮熟菠菜,然后冷冻,直到使用时准备食用。\n","如果要制作冰糕,我会使用一个小到中号的食物加工器),这样你就可以避免添加过多的冰块。\n","大约一年后,电机开始发出奇怪的声音。我打电话给客户服务,但保修期已经过期了,\n","所以我只好购买了另一台。值得注意的是,这类产品的整体质量在过去几年里有所下降\n",",所以他们在一定程度上依靠品牌认知和消费者忠诚来维持销售。在大约两天内,我收到了新的搅拌机。\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]\n"]},{"cell_type":"code","execution_count":4,"id":"eb878522","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["评论1: 熊猫公仔是生日礼物,女儿喜欢,软可爱,面部表情和善。价钱有点小,快递提前一天到货。 \n","\n","评论2: 漂亮卧室灯,储物功能,快速送达,灯线问题,快速解决,容易装配,关心客户和产品。 \n","\n","评论3: 这款电动牙刷电池续航好,但牙刷头太小,价格合理,清洁效果好。 \n","\n","评论4: 该评论提到了一个17件套装的产品,在11月份有折扣销售,但在12月份价格上涨。评论者提到了产品的外观和使用方法,并提到了产品质量下降的问题。最后,评论者提到他们购买了另一台搅拌机。 \n","\n"]}],"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(f\"评论{i+1}: \", response, \"\\n\")\n"]},{"cell_type":"markdown","id":"f118c0cc","metadata":{},"source":["## 三、英文版"]},{"cell_type":"markdown","id":"a08635df","metadata":{},"source":["**1.1 单一文本概括**"]},{"cell_type":"code","execution_count":12,"id":"e55327d5","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","Got this panda plush toy for my daughter's birthday, \\\n","who loves it and takes it everywhere. It's soft and \\ \n","super cute, and its face has a friendly look. It's \\ \n","a bit small for what I paid though. I think there \\ \n","might be other options that are bigger for the \\ \n","same price. It arrived a day earlier than expected, \\ \n","so I got to play with it myself before I gave it \\ \n","to her.\n","\"\"\""]},{"cell_type":"code","execution_count":13,"id":"30c2ef51","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["This panda plush toy is loved by the reviewer's daughter, but they feel it is a bit small for the price.\n"]}],"source":["prompt = f\"\"\"\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","backticks, in at most 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"9bdcfc1b","metadata":{},"source":["**1.2 设置关键角度侧重**"]},{"cell_type":"markdown","id":"5dd0534f","metadata":{},"source":["1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":14,"id":"b354cc3f","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer is happy with the product but suggests offering larger options for the same price. They were pleased with the early delivery.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","Shipping deparmtment. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that mention shipping and delivery of the product. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"af6aaf3a","metadata":{},"source":["1.2.2 侧重于价格和质量"]},{"cell_type":"code","execution_count":15,"id":"1b5358fd","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer loves the panda plush toy for its softness and cuteness, but feels it is overpriced compared to other options available.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","pricing deparmtment, responsible for determining the \\\n","price of the product. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that are relevant to the price and perceived value. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"0f582677","metadata":{},"source":["**1.3 关键信息提取**"]},{"cell_type":"code","execution_count":16,"id":"32c87014","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The shipping department should take note that the product arrived a day earlier than expected.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to extract relevant information from \\ \n","a product review from an ecommerce site to give \\\n","feedback to the Shipping department. \n","\n","From the review below, delimited by triple quotes \\\n","extract the information relevant to shipping and \\ \n","delivery. Limit to 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"2043d100","metadata":{},"source":["**2.1 同时概括多条文本**"]},{"cell_type":"code","execution_count":17,"id":"cff48486","metadata":{},"outputs":[],"source":["review_1 = prod_review \n","\n","# review for a standing lamp\n","review_2 = \"\"\"\n","Needed a nice lamp for my bedroom, and this one \\\n","had additional storage and not too high of a price \\\n","point. Got it fast - arrived in 2 days. The string \\\n","to the lamp broke during the transit and the company \\\n","happily sent over a new one. Came within a few days \\\n","as well. It was easy to put together. Then I had a \\\n","missing part, so I contacted their support and they \\\n","very quickly got me the missing piece! Seems to me \\\n","to be a great company that cares about their customers \\\n","and products. \n","\"\"\"\n","\n","# review for an electric toothbrush\n","review_3 = \"\"\"\n","My dental hygienist recommended an electric toothbrush, \\\n","which is why I got this. The battery life seems to be \\\n","pretty impressive so far. After initial charging and \\\n","leaving the charger plugged in for the first week to \\\n","condition the battery, I've unplugged the charger and \\\n","been using it for twice daily brushing for the last \\\n","3 weeks all on the same charge. But the toothbrush head \\\n","is too small. I’ve seen baby toothbrushes bigger than \\\n","this one. I wish the head was bigger with different \\\n","length bristles to get between teeth better because \\\n","this one doesn’t. Overall if you can get this one \\\n","around the $50 mark, it's a good deal. The manufactuer's \\\n","replacements heads are pretty expensive, but you can \\\n","get generic ones that're more reasonably priced. This \\\n","toothbrush makes me feel like I've been to the dentist \\\n","every day. My teeth feel sparkly clean! \n","\"\"\"\n","\n","# review for a blender\n","review_4 = \"\"\"\n","So, they still had the 17 piece system on seasonal \\\n","sale for around $49 in the month of November, about \\\n","half off, but for some reason (call it price gouging) \\\n","around the second week of December the prices all went \\\n","up to about anywhere from between $70-$89 for the same \\\n","system. And the 11 piece system went up around $10 or \\\n","so in price also from the earlier sale price of $29. \\\n","So it looks okay, but if you look at the base, the part \\\n","where the blade locks into place doesn’t 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","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","spinach then freeze until ready for use-and if making \\\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","I called customer service but the warranty expired \\\n","already, so I had to buy another one. FYI: The overall \\\n","quality has gone done in these types of products, so \\\n","they are kind of counting on brand recognition and \\\n","consumer loyalty to maintain sales. Got it in about \\\n","two days.\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]"]},{"cell_type":"code","execution_count":18,"id":"3f61080b","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["0 Soft and cute panda plush toy loved by daughter, but small for the price. Arrived early. \n","\n","1 Great lamp with storage, fast delivery, excellent customer service, and easy assembly. Highly recommended. \n","\n","2 Impressive battery life, but toothbrush head is too small. Good deal if bought around $50. \n","\n","3 The reviewer found the price increase after the sale disappointing and noticed a decrease in quality over time. \n","\n"]}],"source":["for i in range(len(reviews)):\n"," prompt = f\"\"\"\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"," backticks in at most 20 words. \n","\n"," Review: ```{reviews[i]}```\n"," \"\"\"\n"," response = get_completion(prompt)\n"," print(i, response, \"\\n\")"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":5} +{"cells":[{"attachments":{},"cell_type":"markdown","id":"b58204ea","metadata":{},"source":["# 第四章 文本概括\n"]},{"attachments":{},"cell_type":"markdown","id":"12fa9ea4","metadata":{},"source":["在繁忙的信息时代,小明是一名热心的开发者,面临着海量的文本信息处理的挑战。他需要通过研究无数的文献资料来为他的项目找到关键的信息,但是时间却远远不够。在他焦头烂额之际,他发现了大型语言模型(LLM)的文本摘要功能。\n","\n","这个功能对小明来说如同灯塔一样,照亮了他处理信息海洋的道路。LLM的强大能力在于它可以将复杂的文本信息简化,提炼出关键的观点,这对于他来说无疑是巨大的帮助。他不再需要花费大量的时间去阅读所有的文档,只需要用LLM将它们概括,就可以快速获取到他所需要的信息。\n","\n","通过编程调用API接口,小明成功实现了这个文本摘要的功能。他感叹道:“这简直就像一道魔法,将无尽的信息海洋变成了清晰的信息源泉。”小明的经历,展现了LLM文本摘要功能的巨大优势:**节省时间**,**提高效率**,以及**精准获取信息**。这就是我们本章要介绍的内容,让我们一起来探索如何利用编程和调用API接口,掌握这个强大的工具。"]},{"attachments":{},"cell_type":"markdown","id":"9cca835b","metadata":{},"source":["## 一、单一文本概括"]},{"attachments":{},"cell_type":"markdown","id":"0c1e1b92","metadata":{},"source":["以商品评论的总结任务为例:对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。"]},{"attachments":{},"cell_type":"markdown","id":"aad5bd2a","metadata":{},"source":["**输入文本**"]},{"cell_type":"markdown","id":"11c360ae","metadata":{},"source":["这是一段在线商品评价,可能来自于一个在线购物平台,例如亚马逊、淘宝、京东等。评价者为一款熊猫公仔进行了点评,评价内容包括商品的质量、大小、价格和物流速度等因素,以及他的女儿对该商品的喜爱程度。"]},{"cell_type":"code","execution_count":2,"id":"43b5dd25","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","这个熊猫公仔是我给女儿的生日礼物,她很喜欢,去哪都带着。\n","公仔很软,超级可爱,面部表情也很和善。但是相比于价钱来说,\n","它有点小,我感觉在别的地方用同样的价钱能买到更大的。\n","快递比预期提前了一天到货,所以在送给女儿之前,我自己玩了会。\n","\"\"\""]},{"attachments":{},"cell_type":"markdown","id":"662c9cd2","metadata":{},"source":["### 1.1 限制输出文本长度"]},{"attachments":{},"cell_type":"markdown","id":"a6d10814","metadata":{},"source":["我们尝试将文本的长度限制在30个字以内。"]},{"cell_type":"code","execution_count":5,"id":"bf4b39f9","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["熊猫公仔软可爱,女儿喜欢,但有点小。快递提前一天到货。\n"]}],"source":["from tool import get_completion\n","\n","prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个字。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"fce32884","metadata":{},"source":["我们可以看到语言模型给了我们一个符合要求的结果。\n","\n","注意:在上一节中我们提到了语言模型在计算和判断文本长度时依赖于分词器,而分词器在字符统计方面不具备完美精度。"]},{"attachments":{},"cell_type":"markdown","id":"e9ab145e","metadata":{},"source":["### 1.2 设置关键角度侧重"]},{"attachments":{},"cell_type":"markdown","id":"f84d0123","metadata":{},"source":["在某些情况下,我们会针对不同的业务场景对文本的侧重会有所不同。例如,在商品评论文本中,物流部门可能更专注于运输的时效性,商家则更关注价格和商品质量,而平台则更看重整体的用户体验。\n","\n","我们可以通过增强输入提示(Prompt),来强调我们对某一特定视角的重视。"]},{"attachments":{},"cell_type":"markdown","id":"d6f8509a","metadata":{},"source":["#### 1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":7,"id":"80636c3e","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["快递提前到货,公仔可爱但有点小。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个字,并且侧重在快递服务上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"76c97fea","metadata":{},"source":["通过输出结果,我们可以看到,文本以“快递提前到货”开头,体现了对于快递效率的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"83275907","metadata":{},"source":["#### 1.2.2 侧重于价格与质量"]},{"cell_type":"code","execution_count":8,"id":"728d6c57","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["可爱的熊猫公仔,质量好但有点小,价格稍高。快递提前到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上生成一个产品评论的简短摘要。\n","\n","请对三个反引号之间的评论文本进行概括,最多30个词汇,并且侧重在产品价格和质量上。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"972dbb1b","metadata":{},"source":["通过输出的结果,我们可以看到,文本以“可爱的熊猫公仔,质量好但有点小,价格稍高”开头,体现了对于产品价格与质量的侧重。"]},{"attachments":{},"cell_type":"markdown","id":"b3ed53d2","metadata":{},"source":["### 1.3 关键信息提取"]},{"attachments":{},"cell_type":"markdown","id":"ba6f5c25","metadata":{},"source":["在1.2节中,虽然我们通过添加关键角度侧重的 Prompt ,确实让文本摘要更侧重于某一特定方面,然而,我们可以发现,在结果中也会保留一些其他信息,比如偏重价格与质量角度的概括中仍保留了“快递提前到货”的信息。如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,则可以要求 LLM 进行“**文本提取( Extract )**”而非“概括( Summarize )”。"]},{"cell_type":"markdown","id":"da39760c","metadata":{},"source":["下面让我们来一起来对文本进行提取信息吧!"]},{"cell_type":"code","execution_count":9,"id":"c845ccab","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["产品运输相关的信息:快递提前一天到货。\n"]}],"source":["prompt = f\"\"\"\n","您的任务是从电子商务网站上的产品评论中提取相关信息。\n","\n","请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。\n","\n","评论: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"attachments":{},"cell_type":"markdown","id":"50498a2b","metadata":{},"source":["## 二、同时概括多条文本"]},{"attachments":{},"cell_type":"markdown","id":"a291541a","metadata":{},"source":["在实际的工作流中,我们往往要处理大量的评论文本,下面的示例将多条用户评价集合在一个列表中,并利用 ```for``` 循环和文本概括(Summarize)提示词,将评价概括至小于 20 个词以下,并按顺序打印。当然,在实际生产中,对于不同规模的评论文本,除了使用 ```for``` 循环以外,还可能需要考虑整合评论、分布式等方法提升运算效率。您可以搭建主控面板,来总结大量用户评论,以及方便您或他人快速浏览,还可以点击查看原评论。这样,您就能高效掌握顾客的所有想法。"]},{"cell_type":"code","execution_count":3,"id":"ef606961","metadata":{},"outputs":[],"source":["review_1 = prod_review\n","\n","# 一盏落地灯的评论\n","review_2 = \"\"\"\n","我需要一盏漂亮的卧室灯,这款灯不仅具备额外的储物功能,价格也并不算太高。\n","收货速度非常快,仅用了两天的时间就送到了。\n","不过,在运输过程中,灯的拉线出了问题,幸好,公司很乐意寄送了一根全新的灯线。\n","新的灯线也很快就送到手了,只用了几天的时间。\n","装配非常容易。然而,之后我发现有一个零件丢失了,于是我联系了客服,他们迅速地给我寄来了缺失的零件!\n","对我来说,这是一家非常关心客户和产品的优秀公司。\n","\"\"\"\n","\n","# 一把电动牙刷的评论\n","review_3 = \"\"\"\n","我的牙科卫生员推荐了电动牙刷,所以我就买了这款。\n","到目前为止,电池续航表现相当不错。\n","初次充电后,我在第一周一直将充电器插着,为的是对电池进行条件养护。\n","过去的3周里,我每天早晚都使用它刷牙,但电池依然维持着原来的充电状态。\n","不过,牙刷头太小了。我见过比这个牙刷头还大的婴儿牙刷。\n","我希望牙刷头更大一些,带有不同长度的刷毛,\n","这样可以更好地清洁牙齿间的空隙,但这款牙刷做不到。\n","总的来说,如果你能以50美元左右的价格购买到这款牙刷,那是一个不错的交易。\n","制造商的替换刷头相当昂贵,但你可以购买价格更为合理的通用刷头。\n","这款牙刷让我感觉就像每天都去了一次牙医,我的牙齿感觉非常干净!\n","\"\"\"\n","\n","# 一台搅拌机的评论\n","review_4 = \"\"\"\n","在11月份期间,这个17件套装还在季节性促销中,售价约为49美元,打了五折左右。\n","可是由于某种原因(我们可以称之为价格上涨),到了12月的第二周,所有的价格都上涨了,\n","同样的套装价格涨到了70-89美元不等。而11件套装的价格也从之前的29美元上涨了约10美元。\n","看起来还算不错,但是如果你仔细看底座,刀片锁定的部分看起来没有前几年版本的那么漂亮。\n","然而,我打算非常小心地使用它\n","(例如,我会先在搅拌机中研磨豆类、冰块、大米等坚硬的食物,然后再将它们研磨成所需的粒度,\n","接着切换到打蛋器刀片以获得更细的面粉,如果我需要制作更细腻/少果肉的食物)。\n","在制作冰沙时,我会将要使用的水果和蔬菜切成细小块并冷冻\n","(如果使用菠菜,我会先轻微煮熟菠菜,然后冷冻,直到使用时准备食用。\n","如果要制作冰糕,我会使用一个小到中号的食物加工器),这样你就可以避免添加过多的冰块。\n","大约一年后,电机开始发出奇怪的声音。我打电话给客户服务,但保修期已经过期了,\n","所以我只好购买了另一台。值得注意的是,这类产品的整体质量在过去几年里有所下降\n",",所以他们在一定程度上依靠品牌认知和消费者忠诚来维持销售。在大约两天内,我收到了新的搅拌机。\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]\n"]},{"cell_type":"code","execution_count":4,"id":"eb878522","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["评论1: 熊猫公仔是生日礼物,女儿喜欢,软可爱,面部表情和善。价钱有点小,快递提前一天到货。 \n","\n","评论2: 漂亮卧室灯,储物功能,快速送达,灯线问题,快速解决,容易装配,关心客户和产品。 \n","\n","评论3: 这款电动牙刷电池续航好,但牙刷头太小,价格合理,清洁效果好。 \n","\n","评论4: 该评论提到了一个17件套装的产品,在11月份有折扣销售,但在12月份价格上涨。评论者提到了产品的外观和使用方法,并提到了产品质量下降的问题。最后,评论者提到他们购买了另一台搅拌机。 \n","\n"]}],"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(f\"评论{i+1}: \", response, \"\\n\")\n"]},{"cell_type":"markdown","id":"f118c0cc","metadata":{},"source":["## 三、英文版"]},{"cell_type":"markdown","id":"a08635df","metadata":{},"source":["**1.1 单一文本概括**"]},{"cell_type":"code","execution_count":12,"id":"e55327d5","metadata":{},"outputs":[],"source":["prod_review = \"\"\"\n","Got this panda plush toy for my daughter's birthday, \\\n","who loves it and takes it everywhere. It's soft and \\ \n","super cute, and its face has a friendly look. It's \\ \n","a bit small for what I paid though. I think there \\ \n","might be other options that are bigger for the \\ \n","same price. It arrived a day earlier than expected, \\ \n","so I got to play with it myself before I gave it \\ \n","to her.\n","\"\"\""]},{"cell_type":"code","execution_count":13,"id":"30c2ef51","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["This panda plush toy is loved by the reviewer's daughter, but they feel it is a bit small for the price.\n"]}],"source":["prompt = f\"\"\"\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","backticks, in at most 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"9bdcfc1b","metadata":{},"source":["**1.2 设置关键角度侧重**"]},{"cell_type":"markdown","id":"5dd0534f","metadata":{},"source":["1.2.1 侧重于快递服务"]},{"cell_type":"code","execution_count":14,"id":"b354cc3f","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer is happy with the product but suggests offering larger options for the same price. They were pleased with the early delivery.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","Shipping deparmtment. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that mention shipping and delivery of the product. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"af6aaf3a","metadata":{},"source":["1.2.2 侧重于价格和质量"]},{"cell_type":"code","execution_count":15,"id":"1b5358fd","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The customer loves the panda plush toy for its softness and cuteness, but feels it is overpriced compared to other options available.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to generate a short summary of a product \\\n","review from an ecommerce site to give feedback to the \\\n","pricing deparmtment, responsible for determining the \\\n","price of the product. \n","\n","Summarize the review below, delimited by triple \n","backticks, in at most 30 words, and focusing on any aspects \\\n","that are relevant to the price and perceived value. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"0f582677","metadata":{},"source":["**1.3 关键信息提取**"]},{"cell_type":"code","execution_count":16,"id":"32c87014","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["The shipping department should take note that the product arrived a day earlier than expected.\n"]}],"source":["prompt = f\"\"\"\n","Your task is to extract relevant information from \\ \n","a product review from an ecommerce site to give \\\n","feedback to the Shipping department. \n","\n","From the review below, delimited by triple quotes \\\n","extract the information relevant to shipping and \\ \n","delivery. Limit to 30 words. \n","\n","Review: ```{prod_review}```\n","\"\"\"\n","\n","response = get_completion(prompt)\n","print(response)"]},{"cell_type":"markdown","id":"2043d100","metadata":{},"source":["**2.1 同时概括多条文本**"]},{"cell_type":"code","execution_count":17,"id":"cff48486","metadata":{},"outputs":[],"source":["review_1 = prod_review \n","\n","# review for a standing lamp\n","review_2 = \"\"\"\n","Needed a nice lamp for my bedroom, and this one \\\n","had additional storage and not too high of a price \\\n","point. Got it fast - arrived in 2 days. The string \\\n","to the lamp broke during the transit and the company \\\n","happily sent over a new one. Came within a few days \\\n","as well. It was easy to put together. Then I had a \\\n","missing part, so I contacted their support and they \\\n","very quickly got me the missing piece! Seems to me \\\n","to be a great company that cares about their customers \\\n","and products. \n","\"\"\"\n","\n","# review for an electric toothbrush\n","review_3 = \"\"\"\n","My dental hygienist recommended an electric toothbrush, \\\n","which is why I got this. The battery life seems to be \\\n","pretty impressive so far. After initial charging and \\\n","leaving the charger plugged in for the first week to \\\n","condition the battery, I've unplugged the charger and \\\n","been using it for twice daily brushing for the last \\\n","3 weeks all on the same charge. But the toothbrush head \\\n","is too small. I’ve seen baby toothbrushes bigger than \\\n","this one. I wish the head was bigger with different \\\n","length bristles to get between teeth better because \\\n","this one doesn’t. Overall if you can get this one \\\n","around the $50 mark, it's a good deal. The manufactuer's \\\n","replacements heads are pretty expensive, but you can \\\n","get generic ones that're more reasonably priced. This \\\n","toothbrush makes me feel like I've been to the dentist \\\n","every day. My teeth feel sparkly clean! \n","\"\"\"\n","\n","# review for a blender\n","review_4 = \"\"\"\n","So, they still had the 17 piece system on seasonal \\\n","sale for around $49 in the month of November, about \\\n","half off, but for some reason (call it price gouging) \\\n","around the second week of December the prices all went \\\n","up to about anywhere from between $70-$89 for the same \\\n","system. And the 11 piece system went up around $10 or \\\n","so in price also from the earlier sale price of $29. \\\n","So it looks okay, but if you look at the base, the part \\\n","where the blade locks into place doesn’t 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","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","spinach then freeze until ready for use-and if making \\\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","I called customer service but the warranty expired \\\n","already, so I had to buy another one. FYI: The overall \\\n","quality has gone done in these types of products, so \\\n","they are kind of counting on brand recognition and \\\n","consumer loyalty to maintain sales. Got it in about \\\n","two days.\n","\"\"\"\n","\n","reviews = [review_1, review_2, review_3, review_4]"]},{"cell_type":"code","execution_count":18,"id":"3f61080b","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["0 Soft and cute panda plush toy loved by daughter, but small for the price. Arrived early. \n","\n","1 Great lamp with storage, fast delivery, excellent customer service, and easy assembly. Highly recommended. \n","\n","2 Impressive battery life, but toothbrush head is too small. Good deal if bought around $50. \n","\n","3 The reviewer found the price increase after the sale disappointing and noticed a decrease in quality over time. \n","\n"]}],"source":["for i in range(len(reviews)):\n"," prompt = f\"\"\"\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"," backticks in at most 20 words. \n","\n"," Review: ```{reviews[i]}```\n"," \"\"\"\n"," response = get_completion(prompt)\n"," print(i, response, \"\\n\")"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"latex_envs":{"LaTeX_envs_menu_present":true,"autoclose":false,"autocomplete":true,"bibliofile":"biblio.bib","cite_by":"apalike","current_citInitial":1,"eqLabelWithNumbers":true,"eqNumInitial":1,"hotkeys":{"equation":"Ctrl-E","itemize":"Ctrl-I"},"labels_anchors":false,"latex_user_defs":false,"report_style_numbering":false,"user_envs_cfg":false},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":true,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":5} diff --git a/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb b/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb index ce9cd7e..b3a2e59 100644 --- a/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb +++ b/docs/content/C1 Prompt Engineering for Developer/5. 推断 Inferring.ipynb @@ -244,7 +244,7 @@ "id": "af474353", "metadata": {}, "source": [ - "下一步,我们将深入挖掘客户评论中的丰富信息。信息提取是自然语言处理(NLP)的重要组成部分,它帮助我们从文本中抽取特定的、我们关心的信息。在接下来的示例中,我们将要求模型识别两个关键元素:购买的商品和商品的制造商。\n", + "信息提取是自然语言处理(NLP)的重要组成部分,它帮助我们从文本中抽取特定的、我们关心的信息。我们将深入挖掘客户评论中的丰富信息。在接下来的示例中,我们将要求模型识别两个关键元素:购买的商品和商品的制造商。\n", "\n", "想象一下,如果你正在尝试分析一个在线电商网站上的众多评论,了解评论中提到的商品是什么、由谁制造,以及相关的积极或消极情绪,将极大地帮助你追踪特定商品或制造商在用户心中的情感趋势。\n", "\n", @@ -532,7 +532,7 @@ "id": "76ccd189", "metadata": {}, "source": [ - "这就是我们关于推断的全面介绍。在短短几分钟内,我们已经能够建立多个用于文本推理的系统,这是以前需要机器学习专家数天甚至数周时间才能完成的任务。这一变化无疑是令人兴奋的,因为无论你是经验丰富的机器学习开发者,还是刚入门的新手,都能利用输入 Prompt 快速建立并启动复杂的自然语言处理任务。" + "这就是我们关于推断的全面介绍。在短短几分钟内,我们已经能够建立多个用于文本推理的系统,这是以前需要机器学习专家数天甚至数周时间才能完成的任务。这一变化无疑是令人兴奋的,因为无论你是经验丰富的机器学习开发者,还是刚入门的新手,都能利用输入 Prompt 快速开始复杂的自然语言处理任务。" ] }, { diff --git a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb index b008f73..0ffd095 100644 --- a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb +++ b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb @@ -15,8 +15,7 @@ "id": "f0bdc2c9", "metadata": {}, "source": [ - "\n", - "使用一个大型语言模型的一个令人兴奋的事情是,我们可以用它来构建一个定制的聊天机器人 (Chatbot) ,只需要很少的工作量。在这一节中,我们将探索如何利用聊天的方式,与个性化(或专门针对特定任务或行为的)聊天机器人进行扩展对话。" + "大型语言模型带给我们的激动人心的一种可能性是,我们可以通过它构建定制的聊天机器人(Chatbot),而且只需很少的工作量。在这一章节的探索中,我们将带你了解如何利用会话形式,与具有个性化特性(或专门为特定任务或行为设计)的聊天机器人进行深度对话。" ] }, { @@ -24,7 +23,7 @@ "id": "e6fae355", "metadata": {}, "source": [ - "像 ChatGPT 这样的聊天模型实际上是组装成以一系列消息作为输入,并返回一个模型生成的消息作为输出的。这种聊天格式原本的设计目标是简便多轮对话,但我们通过之前的学习可以知道,它对于不会涉及任何对话的**单轮任务**也同样有用。\n" + "像 ChatGPT 这样的聊天模型实际上是组装成以一系列消息作为输入,并返回一个模型生成的消息作为输出的。这种聊天格式原本的设计目标是简便多轮对话,但我们通过之前的学习可以知道,它对于不会涉及任何对话的**单轮任务**也同样有用。" ] }, { @@ -93,9 +92,18 @@ "id": "e105c1b4", "metadata": {}, "source": [ - "### 1.1 讲笑话\n", - "\n", - "系统消息说,你是一个说话像莎士比亚的助手。这是我们向助手描述**它应该如何表现的方式**。然后,第一个用户消息是*给我讲个笑话*。接下来以助手身份给出回复是,*为什么鸡会过马路?* 最后发送用户消息是*我不知道*。" + "### 1.1 讲笑话" + ] + }, + { + "cell_type": "markdown", + "id": "a0b37933", + "metadata": {}, + "source": [ + "我们通过系统消息来定义:“你是一个说话像莎士比亚的助手。”这是我们向助手描述**它应该如何表现的方式**。\n", + "然后,第一个用户消息是*给我讲个笑话*。\n", + "接下来以助手身份给出回复是,*为什么鸡会过马路?* \n", + "最后发送用户消息是*我不知道*。" ] }, { @@ -182,7 +190,9 @@ "id": "5f76bedb", "metadata": {}, "source": [ - "让我们看另一个例子。助手的消息是*你是一个友好的聊天机器人*,第一个用户消息是*嗨,我叫Isa*。我们想要得到第一个用户消息。" + "让我们看另一个例子。系统消息来定义:“*你是一个友好的聊天机器人*”,第一个用户消息:“*嗨,我叫Isa*。”\n", + "\n", + "我们想要得到第一个用户消息的回复。" ] }, { @@ -221,7 +231,7 @@ "id": "1e9f96ba", "metadata": {}, "source": [ - "让我们再试一个例子。系统消息是,你是一个友好的聊天机器人,第一个用户消息是,是的,你能提醒我我的名字是什么吗?" + "让我们再试一个例子。系统消息来定义:“你是一个友好的聊天机器人”,第一个用户消息:“是的,你能提醒我我的名字是什么吗?”" ] }, { @@ -299,12 +309,30 @@ "id": "bBg_MpXeYnTq" }, "source": [ - "## 三、订餐机器人\n", - "\n", - "现在,我们构建一个 “订餐机器人”,我们需要它自动收集用户信息,接受比萨饼店的订单。\n", - "\n", - "### 3.1 构建机器人\n", - "\n", + "## 三、订餐机器人" + ] + }, + { + "cell_type": "markdown", + "id": "8f0f678c", + "metadata": {}, + "source": [ + "在这一新的章节中,我们将探索如何构建一个 “点餐助手机器人”。这个机器人将被设计为自动收集用户信息,并接收来自比萨饼店的订单。让我们开始这个有趣的项目,深入理解它如何帮助简化日常的订餐流程。" + ] + }, + { + "cell_type": "markdown", + "id": "4edeede6", + "metadata": {}, + "source": [ + "### 3.1 构建机器人" + ] + }, + { + "cell_type": "markdown", + "id": "3357a655", + "metadata": {}, + "source": [ "下面这个函数将收集我们的用户消息,以便我们可以避免像刚才一样手动输入。这个函数将从我们下面构建的用户界面中收集 Prompt ,然后将其附加到一个名为上下文( ```context``` )的列表中,并在每次调用模型时使用该上下文。模型的响应也会添加到上下文中,所以用户消息和模型消息都被添加到上下文中,上下文逐渐变长。这样,模型就有了需要的信息来确定下一步要做什么。" ] }, @@ -434,7 +462,14 @@ "source": [ "此处我们另外要求模型创建一个 JSON 摘要,方便我们发送给订单系统。\n", "\n", - "因此我们需要在上下文的基础上追加另一个系统消息,作为另一条指示 (instruction) 。我们说*创建一个刚刚订单的 JSON 摘要,列出每个项目的价格,字段应包括 1)披萨,包括尺寸,2)配料列表,3)饮料列表,4)辅菜列表,包括尺寸,最后是总价格*。此处也可以定义为用户消息,不一定是系统消息。\n", + "因此我们需要在上下文的基础上追加另一个系统消息,作为另一条指示 (instruction) 。我们说创建一个刚刚订单的 JSON 摘要,列出每个项目的价格,字段应包括:\n", + "1. 披萨,包括尺寸\n", + "2. 配料列表\n", + "3. 饮料列表\n", + "4. 辅菜列表,包括尺寸,\n", + "5. 总价格。\n", + "\n", + "此处也可以定义为用户消息,不一定是系统消息。\n", "\n", "请注意,这里我们使用了一个较低的温度,因为对于这些类型的任务,我们希望输出相对可预测。" ] @@ -510,7 +545,7 @@ "id": "ef17c2b2", "metadata": {}, "source": [ - "现在,我们已经建立了自己的订餐聊天机器人。请随意自定义并修改系统消息,以更改聊天机器人的行为,并使其扮演不同的角色,拥有不同的知识。" + "我们已经成功创建了自己的订餐聊天机器人。你可以根据自己的喜好和需求,自由地定制和修改机器人的系统消息,改变它的行为,让它扮演各种各样的角色,赋予它丰富多彩的知识。让我们一起探索聊天机器人的无限可能性吧!" ] }, { From c3a304d0ad97a4971c48ad892f6b23322bb68721 Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:16:33 +0800 Subject: [PATCH 12/13] =?UTF-8?q?Create=209.=20=E6=80=BB=E7=BB=93=20Summar?= =?UTF-8?q?y.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../9. 总结 Summary.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/content/C1 Prompt Engineering for Developer/9. 总结 Summary.md diff --git a/docs/content/C1 Prompt Engineering for Developer/9. 总结 Summary.md b/docs/content/C1 Prompt Engineering for Developer/9. 总结 Summary.md new file mode 100644 index 0000000..1322bbf --- /dev/null +++ b/docs/content/C1 Prompt Engineering for Developer/9. 总结 Summary.md @@ -0,0 +1,14 @@ +**恭喜您完成了本书第一单元内容的学习!** + +总的来说,在第一单元中,我们学习并掌握了关于 Prompt 的两个核心原则: + +- 编写清晰具体的指令; +- 如果适当的话,给模型一些思考时间。 + +您还学习了迭代式 Prompt 开发的方法,并了解了如何找到适合您应用程序的 Prompt 的过程是非常关键的。 + +我们还讨论了大型语言模型的许多功能,包括摘要、推断、转换和扩展。您也学习了如何搭建个性化的聊天机器人。在第一单元中,您的收获应该颇丰,希望通过第一单元学习能为您带来愉悦的体验。 + +我们期待您能灵感迸发,尝试创建自己的应用。请大胆尝试,并分享给我们您的想法。您可以从一个微型项目开始,或许它具备一定的实用性,或者仅仅是一项有趣的创新。请利用您在第一个项目中得到的经验,去创造更优秀的下一项目,以此类推。如果您已经有一个宏大的项目设想,那么,请毫不犹豫地去实现它。 + +最后,希望您在完成第一单元的过程中感到满足,感谢您的参与。我们热切期待着您的惊艳作品。接下来,我们将进入第二单元的学习! From a01a94f7db6cdbdc9a8419c20a20d93bf37312fc Mon Sep 17 00:00:00 2001 From: LiuWH <65588374+Weihong-Liu@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:45:45 +0800 Subject: [PATCH 13/13] =?UTF-8?q?Update=208.=20=E8=81=8A=E5=A4=A9=E6=9C=BA?= =?UTF-8?q?=E5=99=A8=E4=BA=BA=20Chatbot.ipynb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../8. 聊天机器人 Chatbot.ipynb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb index 0ffd095..17e29ef 100644 --- a/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb +++ b/docs/content/C1 Prompt Engineering for Developer/8. 聊天机器人 Chatbot.ipynb @@ -101,9 +101,12 @@ "metadata": {}, "source": [ "我们通过系统消息来定义:“你是一个说话像莎士比亚的助手。”这是我们向助手描述**它应该如何表现的方式**。\n", - "然后,第一个用户消息是*给我讲个笑话*。\n", - "接下来以助手身份给出回复是,*为什么鸡会过马路?* \n", - "最后发送用户消息是*我不知道*。" + "\n", + "然后,第一个用户消息:“给我讲个笑话。”\n", + "\n", + "接下来以助手身份给出回复:“为什么鸡会过马路?” \n", + "\n", + "最后发送用户消息是:“我不知道。”" ] }, {