{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "# 第7章：构建聊天应用\n",
    "## OpenAI API 快速入门\n",
    "\n",
    "本笔记本改编自包含访问 [Azure OpenAI](notebook-azure-openai.ipynb) 服务笔记本的 [Azure OpenAI 示例仓库](https://github.com/Azure/azure-openai-samples?WT.mc_id=academic-105485-koreyst)。\n",
    "\n",
    "Python OpenAI API 也适用于 Azure OpenAI 模型，只需做一些修改。了解更多差异，请访问：[如何使用 Python 在 OpenAI 和 Azure OpenAI 端点之间切换](https://learn.microsoft.com/azure/ai-services/openai/how-to/switching-endpoints?WT.mc_id=academic-109527-jasmineg)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "# 概览  \n",
    "“大型语言模型是将文本映射到文本的函数。给定一段输入文本，大型语言模型会尝试预测接下来将出现的文本”(1)。本“快速入门”笔记本将向用户介绍高级的LLM概念、开始使用AML所需的核心包、提示设计的简单入门，以及几个不同用例的简短示例。 \n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "## 目录  \n",
    "\n",
    "[概述](#overview)  \n",
    "[如何使用OpenAI服务](#how-to-use-openai-service)  \n",
    "[1. 创建您的OpenAI服务](#1.-creating-your-openai-service)  \n",
    "[2. 安装](#2.-installation)    \n",
    "[3. 凭证](#3.-credentials)  \n",
    "\n",
    "[用例](#use-cases)    \n",
    "[1. 总结文本](#1.-summarize-text)  \n",
    "[2. 分类文本](#2.-classify-text)  \n",
    "[3. 生成新产品名称](#3.-generate-new-product-names)  \n",
    "[4. 微调分类器](#4.fine-tune-a-classifier)  \n",
    "\n",
    "[参考资料](#references)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "### 构建你的第一个提示  \n",
    "这个简短的练习将为提交提示给 OpenAI 模型完成一个简单任务“摘要”提供基本介绍。\n",
    "\n",
    "\n",
    "<strong>步骤</strong>：  \n",
    "1. 在你的 Python 环境中安装 OpenAI 库  \n",
    "2. 加载标准辅助库并设置你为创建的 OpenAI 服务准备的典型 OpenAI 安全凭证  \n",
    "3. 为你的任务选择一个模型  \n",
    "4. 为模型创建一个简单的提示  \n",
    "5. 向模型 API 提交你的请求！\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "### 1. 安装 OpenAI\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674254990318
    },
    "jupyter": {
     "outputs_hidden": true,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "%pip install openai python-dotenv"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "### 2. 导入辅助库并实例化凭证\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674829434433
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "from openai import OpenAI\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "API_KEY = os.getenv(\"OPENAI_API_KEY\",\"\")\n",
    "assert API_KEY, \"ERROR: OpenAI Key is missing\"\n",
    "\n",
    "client = OpenAI(\n",
    "    api_key=API_KEY\n",
    "    )\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "### 3. 找到合适的模型  \n",
    "像 GPT-4o 和 GPT-4o mini 这样的模型可以理解和生成自然语言，并且在 OpenAI 平台上提供，具有不同的性能和速度，适用于不同的任务。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674742720788
    },
    "jupyter": {
     "outputs_hidden": true,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "# Select a general purpose chat model\n",
    "model = \"gpt-4o-mini\"\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "## 4. 提示设计  \n",
    "\n",
    "“大型语言模型的魔力在于，通过在大量文本上训练以最小化这种预测错误，模型最终学会了对这些预测有用的概念。例如，它们学会了如下概念”(1):\n",
    "\n",
    "* 如何拼写\n",
    "* 语法如何运作\n",
    "* 如何改写\n",
    "* 如何回答问题\n",
    "* 如何进行对话\n",
    "* 如何用多种语言写作\n",
    "* 如何编程\n",
    "* 等等\n",
    "\n",
    "#### 如何控制大型语言模型  \n",
    "“在所有输入给大型语言模型的内容中，最有影响力的远远是文本提示”(1)。\n",
    "\n",
    "大型语言模型可以通过几种方式被提示来生成输出：\n",
    "\n",
    "指令：告诉模型你想要什么\n",
    "补全：引导模型完成你想要的开头部分\n",
    "演示：向模型展示你想要什么，包括：\n",
    "在提示中给出几个示例\n",
    "在微调训练数据集中给出成百上千个示例”\n",
    "\n",
    "\n",
    "\n",
    "#### 创建提示的三个基本准则：\n",
    "\n",
    "<strong>展示与说明</strong>。通过指令、示例或两者结合清楚表达你的需求。如果你想让模型按字母顺序排列一个项目列表，或按情感对段落进行分类，就明确告诉它这是你的需求。\n",
    "\n",
    "<strong>提供高质量数据</strong>。如果你在尝试构建分类器或让模型遵循某种模式，确保有足够的示例。务必校对你的示例——模型通常足够聪明，能够识别基本拼写错误并给出回应，但它也可能认为这是故意的，进而影响回答结果。\n",
    "\n",
    "**检查你的设置。** temperature 和 top_p 设置控制模型生成回应的确定性。如果你希望得到唯一正确答案的回应，应将这些参数设置较低。如果你想要更多样化的回答，可以设置得较高。人们在这些设置上最常犯的错误是以为它们是“聪明”或“创造力”的控制开关。\n",
    "\n",
    "\n",
    "来源：https://learn.microsoft.com/azure/ai-services/openai/overview\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "### 5. 提交！\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674494935186
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "# Create your first prompt\n",
    "text_prompt = \"Should oxford commas always be used?\"\n",
    "\n",
    "response = client.responses.create(\n",
    "  model=model,\n",
    "  input = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n",
    "               {\"role\":\"user\",\"content\":text_prompt},],\n",
    "  store=False,)\n",
    "\n",
    "response.output_text\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "### 重复相同的调用，结果有何不同？ \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674494940872
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "\n",
    "response = client.responses.create(\n",
    "  model=model,\n",
    "  input = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n",
    "               {\"role\":\"user\",\"content\":text_prompt},],\n",
    "  store=False,)\n",
    "\n",
    "response.output_text\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "## 总结文本  \n",
    "#### 挑战  \n",
    "通过在文本段落末尾添加“tl;dr:”来总结文本。注意模型如何理解执行多种任务而无需额外指令。您可以尝试比tl;dr更具描述性的提示词，以修改模型的行为并自定义您收到的摘要(3)。  \n",
    "\n",
    "最近的研究表明，通过在大规模文本语料库上进行预训练，随后在特定任务上进行微调，可以在许多NLP任务和基准测试上取得显著提升。虽然模型架构通常是任务无关的，但这种方法仍然需要成千上万个特定任务的微调数据集。相比之下，人类通常只需通过少量示例或简单指令即可完成新的语言任务——这是当前的NLP系统仍普遍难以做到的。本文展示了扩大语言模型规模大大提高了任务无关的少样本性能，有时甚至能够达到以往微调方法的竞争水平。 \n",
    "\n",
    "\n",
    "\n",
    "tl;dr  \n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "# 多种用例练习  \n",
    "1. 文本总结  \n",
    "2. 文本分类  \n",
    "3. 生成新产品名称\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674495198534
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "prompt = \"Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnostic in architecture, this method still requires task-specific fine-tuning datasets of thousands or tens of thousands of examples. By contrast, humans can generally perform a new language task from only a few examples or from simple instructions - something that current NLP systems still largely struggle to do. Here we show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior state-of-the-art fine-tuning approaches.\\n\\nTl;dr\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674495201868
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "#Setting a few additional, typical parameters during API Call\n",
    "\n",
    "response = client.responses.create(\n",
    "  model=model,\n",
    "  input = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n",
    "               {\"role\":\"user\",\"content\":prompt},],\n",
    "  store=False,)\n",
    "\n",
    "response.output_text\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "## 分类文本  \n",
    "#### 挑战  \n",
    "将项目分类到推理时提供的类别中。在下面的示例中，我们在提示中同时提供了类别和要分类的文本(*playground_reference)。 \n",
    "\n",
    "客户询问：您好，我笔记本键盘上的一个键最近坏了，我需要更换一个：\n",
    "\n",
    "分类类别：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674499424645
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "prompt = \"Classify the following inquiry into one of the following: categories: [Pricing, Hardware Support, Software Support]\\n\\ninquiry: Hello, one of the keys on my laptop keyboard broke recently and I'll need a replacement:\\n\\nClassified category:\"\n",
    "print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674499378518
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "#Setting a few additional, typical parameters during API Call\n",
    "\n",
    "response = client.responses.create(\n",
    "  model=model,\n",
    "  input = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n",
    "               {\"role\":\"user\",\"content\":prompt},],\n",
    "  store=False,)\n",
    "\n",
    "response.output_text\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "## 生成新产品名称\n",
    "#### 挑战\n",
    "根据示例词创建产品名称。这里我们在提示中包含了我们将要为其生成名称的产品信息。我们还提供了类似示例以展示我们希望获得的模式。我们还将温度值设置较高，以增加随机性和更具创新性的响应。\n",
    "\n",
    "产品描述：家用奶昔机\n",
    "种子词：快速、健康、紧凑。\n",
    "产品名称：HomeShaker、Fit Shaker、QuickShake、Shake Maker\n",
    "\n",
    "产品描述：一双可以适合任何脚型的鞋子。\n",
    "种子词：适应性强、合脚、全适合。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "gather": {
     "logged": 1674257087279
    },
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "prompt = \"Product description: A home milkshake maker\\nSeed words: fast, healthy, compact.\\nProduct names: HomeShaker, Fit Shaker, QuickShake, Shake Maker\\n\\nProduct description: A pair of shoes that can fit any foot size.\\nSeed words: adaptable, fit, omni-fit.\"\n",
    "\n",
    "print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "#Setting a few additional, typical parameters during API Call\n",
    "\n",
    "response = client.responses.create(\n",
    "  model=model,\n",
    "  input = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n",
    "               {\"role\":\"user\",\"content\":prompt}],\n",
    "  store=False,)\n",
    "\n",
    "response.output_text\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "# 参考资料  \n",
    "- [Openai Cookbook](https://github.com/openai/openai-cookbook?WT.mc_id=academic-105485-koreyst)  \n",
    "- [Microsoft Foundry 门户](https://ai.azure.com?WT.mc_id=academic-105485-koreyst)  \n",
    "- [微调 GPT 模型以分类文本的最佳实践](https://platform.openai.com/docs/guides/fine-tuning?WT.mc_id=academic-105485-koreyst)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "# 需要更多帮助  \n",
    "[OpenAI Commercialization Team](AzureOpenAITeam@microsoft.com) \n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "source": [
    "# 贡献者\n",
    "* Louis Li  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**免责声明**：\n本文件由 AI 翻译服务 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻译完成。尽管我们力求准确，但请注意，自动翻译可能包含错误或不准确之处。原始语言版文件应视为权威来源。对于重要信息，建议使用专业人工翻译。我们对因使用本翻译而产生的任何误解或误释不承担责任。\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
   ]
  }
 ],
 "metadata": {
  "kernel_info": {
   "name": "python310-sdkv2"
  },
  "kernelspec": {
   "display_name": "base",
   "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.13"
  },
  "microsoft": {
   "host": {
    "AzureML": {
     "notebookHasBeenCompleted": true
    }
   }
  },
  "nteract": {
   "version": "nteract-front-end@1.0.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}