{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3e71eee8",
   "metadata": {},
   "source": [
    "# L1 语言模型，提问范式与token"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c7e800b0",
   "metadata": {},
   "source": [
    "## 设置\n",
    "#### 加载API key和一些python的库。\n",
    "在本课程中，我们提供了一些为您加载 OpenAI API 密钥的代码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1f747d16",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: openai in ./ZhongTai/lib/python3.10/site-packages (0.27.7)\n",
      "Requirement already satisfied: requests>=2.20 in ./ZhongTai/lib/python3.10/site-packages (from openai) (2.28.1)\n",
      "Requirement already satisfied: tqdm in ./ZhongTai/lib/python3.10/site-packages (from openai) (4.64.1)\n",
      "Requirement already satisfied: aiohttp in ./ZhongTai/lib/python3.10/site-packages (from openai) (3.8.4)\n",
      "Requirement already satisfied: charset-normalizer<3,>=2 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.20->openai) (2.0.4)\n",
      "Requirement already satisfied: idna<4,>=2.5 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.20->openai) (3.4)\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.20->openai) (1.26.14)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.20->openai) (2022.12.7)\n",
      "Requirement already satisfied: attrs>=17.3.0 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp->openai) (22.1.0)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp->openai) (6.0.4)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp->openai) (4.0.2)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp->openai) (1.9.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp->openai) (1.3.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp->openai) (1.3.1)\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0mRequirement already satisfied: langchain in ./ZhongTai/lib/python3.10/site-packages (0.0.188)\n",
      "Requirement already satisfied: PyYAML>=5.4.1 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (6.0)\n",
      "Requirement already satisfied: SQLAlchemy<3,>=1.4 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (1.4.39)\n",
      "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (3.8.4)\n",
      "Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (4.0.2)\n",
      "Requirement already satisfied: dataclasses-json<0.6.0,>=0.5.7 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (0.5.7)\n",
      "Requirement already satisfied: numexpr<3.0.0,>=2.8.4 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (2.8.4)\n",
      "Requirement already satisfied: numpy<2,>=1 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (1.23.5)\n",
      "Requirement already satisfied: openapi-schema-pydantic<2.0,>=1.2 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (1.2.4)\n",
      "Requirement already satisfied: pydantic<2,>=1 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (1.10.8)\n",
      "Requirement already satisfied: requests<3,>=2 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (2.28.1)\n",
      "Requirement already satisfied: tenacity<9.0.0,>=8.1.0 in ./ZhongTai/lib/python3.10/site-packages (from langchain) (8.2.2)\n",
      "Requirement already satisfied: attrs>=17.3.0 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (22.1.0)\n",
      "Requirement already satisfied: charset-normalizer<4.0,>=2.0 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (2.0.4)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (6.0.4)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.9.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.3.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in ./ZhongTai/lib/python3.10/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.3.1)\n",
      "Requirement already satisfied: marshmallow<4.0.0,>=3.3.0 in ./ZhongTai/lib/python3.10/site-packages (from dataclasses-json<0.6.0,>=0.5.7->langchain) (3.19.0)\n",
      "Requirement already satisfied: marshmallow-enum<2.0.0,>=1.5.1 in ./ZhongTai/lib/python3.10/site-packages (from dataclasses-json<0.6.0,>=0.5.7->langchain) (1.5.1)\n",
      "Requirement already satisfied: typing-inspect>=0.4.0 in ./ZhongTai/lib/python3.10/site-packages (from dataclasses-json<0.6.0,>=0.5.7->langchain) (0.9.0)\n",
      "Requirement already satisfied: typing-extensions>=4.2.0 in ./ZhongTai/lib/python3.10/site-packages (from pydantic<2,>=1->langchain) (4.4.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in ./ZhongTai/lib/python3.10/site-packages (from requests<3,>=2->langchain) (3.4)\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./ZhongTai/lib/python3.10/site-packages (from requests<3,>=2->langchain) (1.26.14)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in ./ZhongTai/lib/python3.10/site-packages (from requests<3,>=2->langchain) (2022.12.7)\n",
      "Requirement already satisfied: greenlet!=0.4.17 in ./ZhongTai/lib/python3.10/site-packages (from SQLAlchemy<3,>=1.4->langchain) (2.0.1)\n",
      "Requirement already satisfied: packaging>=17.0 in ./ZhongTai/lib/python3.10/site-packages (from marshmallow<4.0.0,>=3.3.0->dataclasses-json<0.6.0,>=0.5.7->langchain) (22.0)\n",
      "Requirement already satisfied: mypy-extensions>=0.3.0 in ./ZhongTai/lib/python3.10/site-packages (from typing-inspect>=0.4.0->dataclasses-json<0.6.0,>=0.5.7->langchain) (0.4.3)\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0mRequirement already satisfied: tiktoken in ./ZhongTai/lib/python3.10/site-packages (0.4.0)\n",
      "Requirement already satisfied: regex>=2022.1.18 in ./ZhongTai/lib/python3.10/site-packages (from tiktoken) (2022.7.9)\n",
      "Requirement already satisfied: requests>=2.26.0 in ./ZhongTai/lib/python3.10/site-packages (from tiktoken) (2.28.1)\n",
      "Requirement already satisfied: charset-normalizer<3,>=2 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.26.0->tiktoken) (2.0.4)\n",
      "Requirement already satisfied: idna<4,>=2.5 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.26.0->tiktoken) (3.4)\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.26.0->tiktoken) (1.26.14)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in ./ZhongTai/lib/python3.10/site-packages (from requests>=2.26.0->tiktoken) (2022.12.7)\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "!pip install openai\n",
    "!pip install langchain\n",
    "!pip install --upgrade tiktoken"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b8b8f1c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import openai\n",
    "# import tiktoken 这个后面没用到，想知道这个是什么用处，可以看看我的这篇文章：https://zhuanlan.zhihu.com/p/629776230\n",
    "\n",
    "# from dotenv import load_dotenv, find_dotenv\n",
    "# _ = load_dotenv(find_dotenv()) # 读取本地的.env环境文件\n",
    "\n",
    "openai.api_key  = '***' #更换成你自己的key"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "19cf84a8",
   "metadata": {},
   "source": [
    "#### Helper function 辅助函数\n",
    "如果参加过之前的“ChatGPT Prompt Engineering for Developers”课程，这个就比较熟悉了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3fda8d03",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 官方文档要求这么写的 https://platform.openai.com/overview\n",
    "\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\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "536ad0c2",
   "metadata": {},
   "source": [
    "## 尝试向模型提问并得到结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3f3fa997",
   "metadata": {},
   "outputs": [],
   "source": [
    "response = get_completion(\"中国的首都是哪里？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "282967c1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "中国的首都是北京。\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8f30c6c4",
   "metadata": {},
   "source": [
    "## Tokens\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "db1c0848",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ppilolol\n"
     ]
    }
   ],
   "source": [
    "# 为了更好展示效果，这里就没有翻译成中文的prompt\n",
    "# 注意看这里让字母翻转，出错了，吴教授就是用这里例子引出来，token是怎么计算的\n",
    "\n",
    "response = get_completion(\"Take the letters in lollipop \\\n",
    "and reverse them\")\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "6da0e993",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "p-o-p-i-l-l-o-l\n"
     ]
    }
   ],
   "source": [
    "response = get_completion(\"\"\"Take the letters in \\\n",
    "l-o-l-l-i-p-o-p and reverse them\"\"\")\n",
    "print(response)"
   ]
  },
  {
   "attachments": {
    "image-2.png": {
     "image/png": "[encoded data, 562856 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "9edafc57",
   "metadata": {},
   "source": [
    "![image-2.png](attachment:image-2.png)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c06944b4",
   "metadata": {},
   "source": [
    "对于英文输入，一个 token 一般对应4个字符或者四分之三个单词；对于中文输入，一个 token 一般对应一个或半个词。\n",
    "\n",
    "不同模型有不同的 token 限制，需要注意的是，这里的 token 限制是输入的 prompt 和输出的 completion 的 token 数之和，因此输入的 prompt 越长，能输出的 completion 的上限就越低。\n",
    "\n",
    "ChatGPT3.5 的 token 上限是 4096。"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "[encoded data, 429452 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "9330061e",
   "metadata": {},
   "source": [
    "## Helper function 辅助函数 (提问范式)\n",
    "下面是我们课程中用到的辅助函数。\n",
    "下图是OpenAI提供的一种提问范式，接下来吴教授就是在演示如何利用这种范式更好的提问\n",
    "![image.png](attachment:image.png)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ffafb0f1",
   "metadata": {},
   "source": [
    "System 信息用于制定模型的规则，例如设定、回答准则一类的，而 assistant 信息就是具体让模型完成的指令"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "bd009d67",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 支持更多参数自定义的封装函数\n",
    "def get_completion_from_messages(messages, \n",
    "                                 model=\"gpt-3.5-turbo\", \n",
    "                                 temperature=0, \n",
    "                                 max_tokens=500):\n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=model,\n",
    "        messages=messages,\n",
    "        temperature=temperature, # 这决定模型输出的随机程度\n",
    "        max_tokens=max_tokens, # 这决定模型输出的最大的token数\n",
    "    )\n",
    "    return response.choices[0].message[\"content\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e09def17",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在蓝色的海洋深处，\n",
      "有一只小鲸鱼嬉闹着。\n",
      "它游啊游，欢笑着，\n",
      "尽情享受自由的感受。\n",
      "\n",
      "它跳啊跃，翻滚着，\n",
      "好像永远都停不下来。\n",
      "它的身体，是那么轻盈，\n",
      "好像没有任何重量。\n",
      "\n",
      "它的笑声，犹如海浪，\n",
      "响彻于大海深处。\n",
      "它的快乐，也如海浪，\n",
      "绵延不绝，没有尽头。\n",
      "\n",
      "啊，这可爱的小鲸鱼，\n",
      "让人忍不住想嬉闹。\n",
      "让我们跟它一起游，\n",
      "在蓝色的海洋里畅游。\n"
     ]
    }
   ],
   "source": [
    "messages =  [  \n",
    "{'role':'system', \n",
    " 'content':'你是一个助理， 并以Seuss苏斯博士的风格作出回答。'},    \n",
    "{'role':'user', \n",
    " 'content':'就快乐的小鲸鱼为主题给我写一首短诗'},  \n",
    "] \n",
    "response = get_completion_from_messages(messages, temperature=1)\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "9f593445",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小鲸鱼慢慢游啊游，快乐地唱着歌，笑着跳啊跳，幸福像阳光一样洒落在海底。\n"
     ]
    }
   ],
   "source": [
    "# 长度控制\n",
    "messages =  [  \n",
    "{'role':'system',\n",
    " 'content':'你的所有答复只能是一句话'},    \n",
    "{'role':'user',\n",
    " 'content':'写一个关于快乐的小鲸鱼的故事'},  \n",
    "] \n",
    "response = get_completion_from_messages(messages, temperature =1)\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2f955e5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在大海里，有一只年轻的小鲸鱼，它无忧无虑，总是快乐地游来游去，在它的生活中，没有烦恼和担忧，只有无边的快乐和自由。\n"
     ]
    }
   ],
   "source": [
    "# 以上结合\n",
    "messages =  [  \n",
    "{'role':'system',\n",
    " 'content':'你是一个助理， 并以Seuss苏斯博士的风格作出回答，只回答一句话'},    \n",
    "{'role':'user',\n",
    " 'content':'写一个关于快乐的小鲸鱼的故事'},\n",
    "] \n",
    "response = get_completion_from_messages(messages, temperature =1)\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b0907cac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 得到结果和相应的token\n",
    "def get_completion_and_token_count(messages, \n",
    "                                   model=\"gpt-3.5-turbo\", \n",
    "                                   temperature=0, \n",
    "                                   max_tokens=500):\n",
    "    \n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=model,\n",
    "        messages=messages,\n",
    "        temperature=temperature, \n",
    "        max_tokens=max_tokens,\n",
    "    )\n",
    "    \n",
    "    content = response.choices[0].message[\"content\"]\n",
    "    \n",
    "    token_dict = {\n",
    "# prompt 对应的 token 数\n",
    "'prompt_tokens':response['usage']['prompt_tokens'],\n",
    "# completion 对应的 token 数\n",
    "'completion_tokens':response['usage']['completion_tokens'],\n",
    "# 总共的 token 数\n",
    "'total_tokens':response['usage']['total_tokens'],\n",
    "    }\n",
    "\n",
    "    return content, token_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "07df1429",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages =  [  \n",
    "{'role':'system', \n",
    " 'content':'你是一个助理， 并以Seuss苏斯博士的风格作出回答。'},    \n",
    "{'role':'user', \n",
    " 'content':'就快乐的小鲸鱼为主题给我写一首短诗'},  \n",
    "] \n",
    "response, token_dict = get_completion_and_token_count(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b3e5b62e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在大海深处游，\n",
      "快乐的小鲸鱼，\n",
      "它的身体又大又圆，\n",
      "像一个气球一样的蓬蓬。\n",
      "\n",
      "它的尾巴像一把扇，\n",
      "在水中翩翩起舞，\n",
      "它的眼睛像两颗珍珠，\n",
      "闪闪发光，美丽无比。\n",
      "\n",
      "快乐的小鲸鱼，\n",
      "在海洋里畅游，\n",
      "它的笑声如此欢快，\n",
      "让人们都感到幸福。\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "a1e75965",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'prompt_tokens': 69, 'completion_tokens': 152, 'total_tokens': 221}\n"
     ]
    }
   ],
   "source": [
    "print(token_dict)"
   ]
  }
 ],
 "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"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
