{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "992c4695-ec4f-428d-bd05-fb3b5fbd70f4",
   "metadata": {},
   "source": [
    "# How to use the prebuilt ReAct agent"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0fcced0-9767-412f-90f9-7f3cd618ff90",
   "metadata": {},
   "source": [
    "In this how-to we'll create a simple [ReAct](https://arxiv.org/abs/2210.03629) agent app that can check the weather. The app consists of an agent (LLM) and tools. As we interact with the app, we will first call the agent (LLM) to decide if we should use tools. Then we will run a loop:  \n",
    "\n",
    "1. If the agent said to take an action (i.e. call tool), we'll run the tools and pass the results back to the agent\n",
    "2. If the agent did not ask to run tools, we will finish (respond to the user)\n",
    "\n",
    "<div class=\"admonition warning\">\n",
    "    <p class=\"admonition-title\">Prebuilt Agent</p>\n",
    "    <p>\n",
    "Please note that here will we use a prebuilt agent. One of the big benefits of LangGraph is that you can easily create your own agent architectures. So while it's fine to start here to build an agent quickly, we would strongly recommend learning how to build your own agent so that you can take full advantage of LangGraph.\n",
    "    </p>\n",
    "</div>   "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7be3889f-3c17-4fa1-bd2b-84114a2c7247",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a213e11a-5c62-4ddb-a707-490d91add383",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install -U langgraph langchain-openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "23a1885c-04ab-4750-aefa-105891fddf3e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OPENAI_API_KEY:  ········\n"
     ]
    }
   ],
   "source": [
    "import getpass\n",
    "import os\n",
    "\n",
    "\n",
    "def _set_env(var: str):\n",
    "    if not os.environ.get(var):\n",
    "        os.environ[var] = getpass.getpass(f\"{var}: \")\n",
    "\n",
    "\n",
    "_set_env(\"OPENAI_API_KEY\")\n",
    "\n",
    "# Recommended\n",
    "_set_env(\"LANGCHAIN_API_KEY\")\n",
    "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
    "os.environ[\"LANGCHAIN_PROJECT\"] = \"Create ReAct Agent Tutorial\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03c0f089-070c-4cd4-87e0-6c51f2477b82",
   "metadata": {},
   "source": [
    "## Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "7a154152-973e-4b5d-aa13-48c617744a4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# First we initialize the model we want to use.\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n",
    "\n",
    "\n",
    "# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF)\n",
    "\n",
    "from typing import Literal\n",
    "\n",
    "from langchain_core.tools import tool\n",
    "\n",
    "\n",
    "@tool\n",
    "def get_weather(city: Literal[\"nyc\", \"sf\"]):\n",
    "    \"\"\"Use this to get weather information.\"\"\"\n",
    "    if city == \"nyc\":\n",
    "        return \"It might be cloudy in nyc\"\n",
    "    elif city == \"sf\":\n",
    "        return \"It's always sunny in sf\"\n",
    "    else:\n",
    "        raise AssertionError(\"Unknown city\")\n",
    "\n",
    "\n",
    "tools = [get_weather]\n",
    "\n",
    "\n",
    "# Define the graph\n",
    "\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "\n",
    "graph = create_react_agent(model, tools=tools)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00407425-506d-4ffd-9c86-987921d8c844",
   "metadata": {},
   "source": [
    "## Usage\n",
    "\n",
    "First, let's visualize the graph we just created"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "fa16de4c-aac0-4ff4-ab69-60d399f75423",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 12316 characters]",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "display(Image(graph.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "16636975-5f2d-4dc7-ab8e-d0bea0830a28",
   "metadata": {},
   "outputs": [],
   "source": [
    "def print_stream(stream):\n",
    "    for s in stream:\n",
    "        message = s[\"messages\"][-1]\n",
    "        if isinstance(message, tuple):\n",
    "            print(message)\n",
    "        else:\n",
    "            message.pretty_print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d187d6b-0fb6-4860-8771-160c3cf403c6",
   "metadata": {},
   "source": [
    "Let's run the app with an input that needs a tool call"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9ffff6c3-a4f5-47c9-b51d-97caaee85cd6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "\n",
      "what is the weather in sf\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Tool Calls:\n",
      "  get_weather (call_jgO5OOUnugRkhRi3wAOHl8Et)\n",
      " Call ID: call_jgO5OOUnugRkhRi3wAOHl8Et\n",
      "  Args:\n",
      "    city: sf\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: get_weather\n",
      "\n",
      "It's always sunny in sf\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "The weather in San Francisco is currently sunny.\n"
     ]
    }
   ],
   "source": [
    "inputs = {\"messages\": [(\"user\", \"what is the weather in sf\")]}\n",
    "print_stream(graph.stream(inputs, stream_mode=\"values\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "838a043f-90ad-4e69-9d1d-6e22db2c346c",
   "metadata": {},
   "source": [
    "Now let's try a question that doesn't need tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "187479f9-32fa-4611-9487-cf816ba2e147",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "\n",
      "who built you?\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "I was created by OpenAI, a research organization focused on developing and advancing artificial intelligence technology.\n"
     ]
    }
   ],
   "source": [
    "inputs = {\"messages\": [(\"user\", \"who built you?\")]}\n",
    "print_stream(graph.stream(inputs, stream_mode=\"values\"))"
   ]
  }
 ],
 "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.11.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
