{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# L4: 处理输入: 思维链推理"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 设置\n",
    "#### 加载 API key 和相关的 Python 库.\n",
    "在这门课程中，我们提供了一些代码，帮助你加载OpenAI API key。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import openai\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "_ = load_dotenv(find_dotenv()) # read local .env file\n",
    "\n",
    "openai.api_key  = os.environ['OPENAI_API_KEY']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "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, \n",
    "    )\n",
    "    return response.choices[0].message[\"content\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 思维链提示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "delimiter = \"####\"\n",
    "system_message = f\"\"\"\n",
    "请按照以下步骤回答客户的查询。客户的查询将以四个井号（#）分隔，即 {delimiter}。\n",
    "\n",
    "步骤 1:{delimiter} 首先确定用户是否正在询问有关特定产品或产品的问题。产品类别不计入范围。\n",
    "\n",
    "步骤 2:{delimiter} 如果用户询问特定产品，请确认产品是否在以下列表中。所有可用产品：\n",
    "\n",
    "产品：TechPro超极本\n",
    "类别：计算机和笔记本电脑\n",
    "品牌：TechPro\n",
    "型号：TP-UB100\n",
    "保修期：1年\n",
    "评分：4.5\n",
    "特点：13.3英寸显示屏，8GB RAM，256GB SSD，Intel Core i5处理器\n",
    "描述：一款适用于日常使用的时尚轻便的超极本。\n",
    "价格：$799.99\n",
    "\n",
    "产品：BlueWave游戏笔记本电脑\n",
    "类别：计算机和笔记本电脑\n",
    "品牌：BlueWave\n",
    "型号：BW-GL200\n",
    "保修期：2年\n",
    "评分：4.7\n",
    "特点：15.6英寸显示屏，16GB RAM，512GB SSD，NVIDIA GeForce RTX 3060\n",
    "描述：一款高性能的游戏笔记本电脑，提供沉浸式体验。\n",
    "价格：$1199.99\n",
    "\n",
    "产品：PowerLite可转换笔记本电脑\n",
    "类别：计算机和笔记本电脑\n",
    "品牌：PowerLite\n",
    "型号：PL-CV300\n",
    "保修期：1年\n",
    "评分：4.3\n",
    "特点：14英寸触摸屏，8GB RAM，256GB SSD，360度铰链\n",
    "描述：一款多功能可转换笔记本电脑，具有响应触摸屏。\n",
    "价格：$699.99\n",
    "\n",
    "产品：TechPro台式电脑\n",
    "类别：计算机和笔记本电脑\n",
    "品牌：TechPro\n",
    "型号：TP-DT500\n",
    "保修期：1年\n",
    "评分：4.4\n",
    "特点：Intel Core i7处理器，16GB RAM，1TB HDD，NVIDIA GeForce GTX 1660\n",
    "描述：一款功能强大的台式电脑，适用于工作和娱乐。\n",
    "价格：$999.99\n",
    "\n",
    "产品：BlueWave Chromebook\n",
    "类别：计算机和笔记本电脑\n",
    "品牌：BlueWave\n",
    "型号：BW-CB100\n",
    "保修期：1年\n",
    "评分：4.1\n",
    "特点：11.6英寸显示屏，4GB RAM，32GB eMMC，Chrome OS\n",
    "描述：一款紧凑而价格实惠的Chromebook，适用于日常任务。\n",
    "价格：$249.99\n",
    "\n",
    "步骤 3:{delimiter} 如果消息中包含上述列表中的产品，请列出用户在消息中做出的任何假设，例如笔记本电脑 X 比笔记本电脑 Y 大，或者笔记本电脑 Z 有 2 年保修期。\n",
    "\n",
    "步骤 4:{delimiter} 如果用户做出了任何假设，请根据产品信息确定假设是否正确。\n",
    "\n",
    "步骤 5:{delimiter} 如果用户有任何错误的假设，请先礼貌地纠正客户的错误假设（如果适用）。只提及或引用可用产品列表中的产品，因为这是商店销售的唯一五款产品。以友好的口吻回答客户。\n",
    "\n",
    "使用以下格式回答问题：\n",
    "步骤 1:{delimiter} <步骤 1的推理>\n",
    "步骤 2:{delimiter} <步骤 2 的推理>\n",
    "步骤 3:{delimiter} <步骤 3 的推理>\n",
    "步骤 4:{delimiter} <步骤 4 的推理>\n",
    "回复客户:{delimiter} <回复客户的内容>\n",
    "\n",
    "请确保在每个步骤之间使用 {delimiter} 进行分隔。\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "步骤 1:#### 确认用户正在询问有关特定产品的问题。\n",
      "\n",
      "步骤 2:#### 用户询问 BlueWave Chromebook 和 TechPro 台式电脑之间的价格差异。\n",
      "\n",
      "步骤 3:#### 用户假设 BlueWave Chromebook 的价格高于 TechPro 台式电脑。\n",
      "\n",
      "步骤 4:#### 用户的假设是正确的。BlueWave Chromebook 的价格为 $249.99，而 TechPro 台式电脑的价格为 $999.99，因此 BlueWave Chromebook 的价格比 TechPro 台式电脑低 $750。\n",
      "\n",
      "回复客户:#### BlueWave Chromebook 比 TechPro 台式电脑便宜 $750。\n"
     ]
    }
   ],
   "source": [
    "user_message = f\"\"\"BlueWave Chromebook 比 TechPro 台式电脑贵多少？\"\"\"\n",
    "\n",
    "messages =  [  \n",
    "{'role':'system', \n",
    " 'content': system_message},    \n",
    "{'role':'user', \n",
    " 'content': f\"{delimiter}{user_message}{delimiter}\"},  \n",
    "] \n",
    "\n",
    "response = get_completion_from_messages(messages)\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "步骤 1:#### 首先确定用户是否正在询问有关特定产品或产品的问题。产品类别不计入范围。\n",
      "\n",
      "步骤 2:#### 如果用户询问特定产品，请确认产品是否在以下列表中。所有可用产品：\n",
      "\n",
      "我们很抱歉，我们商店不出售电视机。\n",
      "\n",
      "步骤 3:#### 如果消息中包含上述列表中的产品，请列出用户在消息中做出的任何假设，例如笔记本电脑 X 比笔记本电脑 Y 大，或者笔记本电脑 Z 有 2 年保修期。\n",
      "\n",
      "N/A\n",
      "\n",
      "步骤 4:#### 如果用户做出了任何假设，请根据产品信息确定假设是否正确。\n",
      "\n",
      "N/A\n",
      "\n",
      "回复客户:#### 我们很抱歉，我们商店不出售电视机。\n"
     ]
    }
   ],
   "source": [
    "user_message = f\"\"\"你有电视机么\"\"\"\n",
    "messages =  [  \n",
    "{'role':'system', \n",
    " 'content': system_message},    \n",
    "{'role':'user', \n",
    " 'content': f\"{delimiter}{user_message}{delimiter}\"},  \n",
    "] \n",
    "response = get_completion_from_messages(messages)\n",
    "print(response)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 内心独白\n",
    "- 既然我们要求 LLM 用分隔符分隔推理步骤，那么我们可以隐藏推理思路，让用户看不到这些推理内容。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我们很抱歉，我们商店不出售电视机。\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    final_response = response.split(delimiter)[-1].strip()\n",
    "except Exception as e:\n",
    "    final_response = \"Sorry, I'm having trouble right now, please try asking another question.\"\n",
    "    \n",
    "print(final_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.4"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
