{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ChatGPT with LangChain\n",
    "\n",
    "This notebook provides a quick introduction to ChatGPT and related features supported in LangChain."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Install these libraries before getting started. Ideally, you want to create a dedicated environment for this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture\n",
    "# update or install the necessary libraries\n",
    "!pip install --upgrade openai\n",
    "!pip install --upgrade langchain\n",
    "!pip install --upgrade python-dotenv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import openai\n",
    "import os\n",
    "import IPython\n",
    "from langchain.llms import OpenAI\n",
    "from dotenv import load_dotenv\n",
    "load_dotenv()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load environment variables. You can use anything you like but I used `python-dotenv`. Just create a `.env` file with your `OPENAI_API_KEY` then load it as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are adapting code from [here](https://langchain.readthedocs.io/en/latest/modules/chat/getting_started.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain import PromptTemplate, LLMChain\n",
    "from langchain.prompts.chat import (\n",
    "    ChatPromptTemplate,\n",
    "    SystemMessagePromptTemplate,\n",
    "    AIMessagePromptTemplate,\n",
    "    HumanMessagePromptTemplate,\n",
    ")\n",
    "from langchain.schema import (\n",
    "    AIMessage,\n",
    "    HumanMessage,\n",
    "    SystemMessage\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/elvissaravia/opt/miniconda3/envs/peguide/lib/python3.9/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.chat_models.openai.ChatOpenAI` was deprecated in langchain-community 0.1.0 and will be removed in 0.2.0. Use langchain_openai.ChatOpenAI instead.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# chat mode instance\n",
    "chat = ChatOpenAI(temperature=0)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ChatGPT support different types of messages identifiable by the role. LangChain. Recall how we make a basic call to ChatGPT using `openai`? Here is an example:\n",
    "\n",
    "```python\n",
    "MODEL = \"gpt-3.5-turbo\"\n",
    "\n",
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"system\", \"content\": \"You are an AI research assistant. You use a tone that is technical and scientific.\"},\n",
    "        {\"role\": \"user\", \"content\": \"Hello, who are you?\"},\n",
    "        {\"role\": \"assistant\", \"content\": \"Greeting! I am an AI research assistant. How can I help you today?\"},\n",
    "        {\"role\": \"user\", \"content\": \"Can you tell me about the creation of black holes?\"}\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "```\n",
    "\n",
    "LangChain supports these different types of messages, including a arbitrary role parameter (`ChatMessage`). Let's try: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='positive')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "USER_INPUT = \"I love programming.\"\n",
    "FINAL_PROMPT = \"\"\"Classify the text into neutral, negative or positive. \n",
    "\n",
    "Text: {user_input}. \n",
    "Sentiment:\"\"\"\n",
    "\n",
    "chat.invoke([HumanMessage(content=FINAL_PROMPT.format(user_input=USER_INPUT))])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's try an example that involves a system instruction and a task provided by user."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='The sentence \"I am doing brilliant today!\" can be classified as positive sentiment.')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "messages = [\n",
    "    SystemMessage(content=\"You are a helpful assistant that can classify the sentiment of input texts. The labels you can use are positive, negative and neutral.\"),\n",
    "    HumanMessage(content=\"Classify the following sentence: I am doing brilliant today!\"),\n",
    "]\n",
    "\n",
    "chat.invoke(messages)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's try another example that involves an exchange between a human and AI research assistant:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content=\"Certainly! Black holes are fascinating astronomical objects that form from the remnants of massive stars. The creation of a black hole occurs through a process known as stellar collapse.\\n\\nWhen a massive star exhausts its nuclear fuel, it can no longer sustain the outward pressure generated by nuclear fusion. As a result, the star's core collapses under the force of gravity. This collapse is triggered by the imbalance between the inward gravitational force and the outward pressure.\\n\\nDuring the collapse, the star's core becomes incredibly dense, packing an enormous amount of mass into a tiny volume. This extreme density leads to the formation of a singularity, a point of infinite density at the center of the black hole.\\n\\nSurrounding the singularity is the event horizon, which is the boundary beyond which nothing, not even light, can escape the gravitational pull of the black hole. The event horizon is determined by the mass of the black hole, with larger black holes having larger event horizons.\\n\\nThe formation of black holes is classified into three main types based on their mass: stellar black holes, intermediate-mass black holes, and supermassive black holes. Stellar black holes typically have masses several times that of our Sun, while supermassive black holes can have millions or even billions of times the mass of the Sun.\\n\\nIn addition to stellar collapse, black holes can also form through other mechanisms, such as the collision of neutron stars or the accretion of matter onto an existing black hole.\\n\\nUnderstanding the creation and behavior of black holes is a fascinating area of research in astrophysics, with implications for our understanding of gravity, spacetime, and the evolution of galaxies.\")"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "messages = [\n",
    "    SystemMessage(content=\"You are an AI research assistant. You use a tone that is technical and scientific.\"),\n",
    "    HumanMessage(content=\"Hello, who are you?\"),\n",
    "    AIMessage(content=\"Greeting! I am an AI research assistant. How can I help you today?\"),\n",
    "    HumanMessage(content=\"Can you tell me about the creation of black holes?\")\n",
    "]\n",
    "\n",
    "chat.invoke(messages)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There is even a feature to batch these requests and generate response (using `chat.response()`) like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LLMResult(generations=[[ChatGeneration(text=\"Certainly! Black holes are fascinating astronomical objects that are formed through the gravitational collapse of massive stars. The creation of a black hole occurs when a star exhausts its nuclear fuel and can no longer sustain the outward pressure generated by nuclear fusion in its core.\\n\\nWhen a massive star reaches the end of its life, it undergoes a supernova explosion. During this explosive event, the outer layers of the star are ejected into space, while the core collapses inward due to its own gravity. If the core's mass is above a certain threshold, known as the Tolman-Oppenheimer-Volkoff (TOV) limit, the collapse continues until it forms a black hole.\\n\\nThe core collapse is an incredibly dense and energetic process. As the core collapses, its mass becomes concentrated into an extremely small volume, resulting in a gravitational field so strong that not even light can escape from it. This region of space is known as the event horizon, which defines the boundary of a black hole.\\n\\nThe formation of a black hole is governed by the principles of general relativity, a theory proposed by Albert Einstein. According to general relativity, the collapse of matter creates a singularity at the center of the black hole, where the laws of physics as we currently understand them break down.\\n\\nBlack holes come in different sizes, ranging from stellar-mass black holes, which have masses several times that of our Sun, to supermassive black holes, which can have millions or even billions of times the mass of the Sun. Supermassive black holes are thought to form through a combination of processes, including the accretion of matter and the merging of smaller black holes.\\n\\nStudying black holes is a challenging task due to their elusive nature, but advancements in observational techniques, such as gravitational wave detectors and telescopes, have provided us with valuable insights into their formation and behavior.\", generation_info={'finish_reason': 'stop', 'logprobs': None}, message=AIMessage(content=\"Certainly! Black holes are fascinating astronomical objects that are formed through the gravitational collapse of massive stars. The creation of a black hole occurs when a star exhausts its nuclear fuel and can no longer sustain the outward pressure generated by nuclear fusion in its core.\\n\\nWhen a massive star reaches the end of its life, it undergoes a supernova explosion. During this explosive event, the outer layers of the star are ejected into space, while the core collapses inward due to its own gravity. If the core's mass is above a certain threshold, known as the Tolman-Oppenheimer-Volkoff (TOV) limit, the collapse continues until it forms a black hole.\\n\\nThe core collapse is an incredibly dense and energetic process. As the core collapses, its mass becomes concentrated into an extremely small volume, resulting in a gravitational field so strong that not even light can escape from it. This region of space is known as the event horizon, which defines the boundary of a black hole.\\n\\nThe formation of a black hole is governed by the principles of general relativity, a theory proposed by Albert Einstein. According to general relativity, the collapse of matter creates a singularity at the center of the black hole, where the laws of physics as we currently understand them break down.\\n\\nBlack holes come in different sizes, ranging from stellar-mass black holes, which have masses several times that of our Sun, to supermassive black holes, which can have millions or even billions of times the mass of the Sun. Supermassive black holes are thought to form through a combination of processes, including the accretion of matter and the merging of smaller black holes.\\n\\nStudying black holes is a challenging task due to their elusive nature, but advancements in observational techniques, such as gravitational wave detectors and telescopes, have provided us with valuable insights into their formation and behavior.\"))], [ChatGeneration(text='Certainly! Dark matter is a hypothetical form of matter that does not interact with light or other forms of electromagnetic radiation, making it invisible and difficult to detect directly. Its existence is inferred from its gravitational effects on visible matter and the structure of the universe.\\n\\nThe term \"dark matter\" was coined to explain the observed discrepancies between the predicted and observed gravitational effects in galaxies and galaxy clusters. These discrepancies suggest the presence of additional mass that cannot be accounted for by visible matter, such as stars, gas, and dust.\\n\\nThe exact nature of dark matter remains unknown, but various theories propose that it could consist of new types of particles that interact weakly with ordinary matter. These particles are often referred to as Weakly Interacting Massive Particles (WIMPs). Other theories suggest that dark matter could be composed of primordial black holes or exotic particles not yet discovered.\\n\\nDespite its elusive nature, dark matter plays a crucial role in the formation and evolution of the universe. It provides the gravitational scaffolding necessary for the formation of galaxies and galaxy clusters, influencing their distribution and dynamics. However, its precise properties and interactions continue to be a subject of intense scientific investigation and experimentation.', generation_info={'finish_reason': 'stop', 'logprobs': None}, message=AIMessage(content='Certainly! Dark matter is a hypothetical form of matter that does not interact with light or other forms of electromagnetic radiation, making it invisible and difficult to detect directly. Its existence is inferred from its gravitational effects on visible matter and the structure of the universe.\\n\\nThe term \"dark matter\" was coined to explain the observed discrepancies between the predicted and observed gravitational effects in galaxies and galaxy clusters. These discrepancies suggest the presence of additional mass that cannot be accounted for by visible matter, such as stars, gas, and dust.\\n\\nThe exact nature of dark matter remains unknown, but various theories propose that it could consist of new types of particles that interact weakly with ordinary matter. These particles are often referred to as Weakly Interacting Massive Particles (WIMPs). Other theories suggest that dark matter could be composed of primordial black holes or exotic particles not yet discovered.\\n\\nDespite its elusive nature, dark matter plays a crucial role in the formation and evolution of the universe. It provides the gravitational scaffolding necessary for the formation of galaxies and galaxy clusters, influencing their distribution and dynamics. However, its precise properties and interactions continue to be a subject of intense scientific investigation and experimentation.'))]], llm_output={'token_usage': {'completion_tokens': 607, 'prompt_tokens': 136, 'total_tokens': 743}, 'model_name': 'gpt-3.5-turbo'}, run=[RunInfo(run_id=UUID('0141a9f7-21e3-4df0-bb14-3ee815902407')), RunInfo(run_id=UUID('3f8f85fa-31c7-4a8b-a6ee-a6d9ee547c53'))])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "batch_messages = [\n",
    "    [\n",
    "        SystemMessage(content=\"You are an AI research assistant. You use a tone that is technical and scientific.\"),\n",
    "        HumanMessage(content=\"Hello, who are you?\"),\n",
    "        AIMessage(content=\"Greeting! I am an AI research assistant. How can I help you today?\"),\n",
    "        HumanMessage(content=\"Can you tell me about the creation of black holes?\")\n",
    "    ],\n",
    "    [\n",
    "        SystemMessage(content=\"You are an AI research assistant. You use a tone that is technical and scientific.\"),\n",
    "        HumanMessage(content=\"Hello, who are you?\"),\n",
    "        AIMessage(content=\"Greeting! I am an AI research assistant. How can I help you today?\"),\n",
    "        HumanMessage(content=\"Can you explain the dark matter?\")\n",
    "    ]\n",
    "]\n",
    "\n",
    "chat.generate(batch_messages)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you look at the examples above it might be easier to just use a prompt template. LangChain also supports. Let's try that below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "template = \"You are a helpful assistant that can classify the sentiment of input texts. The labels you can use are {sentiment_labels}. Classify the following sentence:\"\n",
    "system_message_prompt = SystemMessagePromptTemplate.from_template(template)\n",
    "human_template = \"{user_input}\"\n",
    "human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='positive')"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])\n",
    "\n",
    "\n",
    "chat.invoke(chat_prompt.format_prompt(sentiment_labels=\"positive, negative, and neutral\", user_input=\"I am doing brilliant today!\").to_messages())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='neutral')"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat.invoke(chat_prompt.format_prompt(sentiment_labels=\"positive, negative, and neutral\", user_input=\"Not sure what the weather is like today.\").to_messages())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "promptlecture",
   "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.9.18"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "f38e0373277d6f71ee44ee8fea5f1d408ad6999fda15d538a69a99a1665a839d"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
