{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3d6bf25d-6a5e-48de-810c-4eafdec8783a",
      "metadata": {
        "id": "3d6bf25d-6a5e-48de-810c-4eafdec8783a"
      },
      "source": [
        "# <center id=\"c1\"><h1>  🕵️‍♂️ Агенты в LangChain 🦜🔗</h1></center>"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ec30b379-e427-4557-bf9f-7262ee23828c",
      "metadata": {
        "id": "ec30b379-e427-4557-bf9f-7262ee23828c"
      },
      "source": [
        "### Оглавление ноутбука\n",
        "<img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmGItXgOiUgudJ1R3P6gUfz4pZagEYjiyuQgdcuXVWTLoFFBfw9yBcYoatl5XqLCEbFRwMpYFVd2Zqxi-mAIRg5ZPTVKSl_18QWpKKL1XC3f2_OYbfm8wzQTn2mLE5kePr8ESKbTtT34sg1eboaJS0x49x6AYUFst-3XK8ZHjaNaI-uh2oUg4qI-Bk5Q/s1600/transformers_agent%20%281%29.png' align=\"right\" width=\"600\" height=\"650\" />\n",
        "<br>\n",
        "\n",
        "<p><font size=\"3\" face=\"Arial\" font-size=\"large\"><ul type=\"square\">\n",
        "    \n",
        "<li><a href=\"#c1\">🚀 Введение </a></li>\n",
        "<li><a href=\"#c2\">🛠🪚 Инструменты для агентов 🤖</a></li>\n",
        "<li><a href=\"#c3\">🐍 Python Agent 😎 </a>\n",
        "<li><a href=\"#c4\">✍️🤖 Создаём первый мини-сервис </a>\n",
        "<li><a href=\"#c5\"> 🧸 Выводы и заключения ✅</a>\n",
        "    \n",
        "</ul></font></p>"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6e7d6af-042a-493e-99a1-329b150168ca",
      "metadata": {
        "id": "d6e7d6af-042a-493e-99a1-329b150168ca"
      },
      "source": [
        "### В этом ноутбуке подробнее познакомимся с использованием `Agents` в `LangChain`."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6d789781-fdec-470e-b0d4-fc3f72d10668",
      "metadata": {
        "id": "6d789781-fdec-470e-b0d4-fc3f72d10668"
      },
      "source": [
        "<div class=\"alert alert-info\">\n",
        "    \n",
        "Агенты `LangChain` — это специализированные компоненты в рамках LangChain, которые взаимодействуют с реальным миром. Эти агенты специально разработаны для выполнения четко определенных задач, таких как ответы на вопросы, генерация текста, перевод на другие языки, обобщение текста и пр. <br>\n",
        "Например, при всех выдающихся результатах LLM в решении различных задач, модель не сможет ответить на такой простой вопрос: \"Какой сегодня день недели?\" или о каком-то событии, которое произошло месяц назад. Здесь на помощь LLM приходят различные инструменты (tools) взаимодействия с внешним миром, пользоваться которыми ей помогает агент. <br>\n",
        "Другими словами, **агент это посредник между LLM и Tools**."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1b635a87-ed5b-4f8f-8d0b-4ecba6ea4651",
      "metadata": {
        "id": "1b635a87-ed5b-4f8f-8d0b-4ecba6ea4651"
      },
      "source": [
        "Архитектура агента `LangChain` выглядит следующим образом:\n",
        "* **Прием ввода**: агент получает вводимые пользователем данные на естественном языке.\n",
        "* **Обработка с помощью LLM**: агент использует LLM для обработки входных данных и формулирования плана действий.\n",
        "* **Выполнение плана**: агент выполняет разработанный план действий, который может включать взаимодействие с другими инструментами или службами.\n",
        "* **Доставка выходных данных**: впоследствии агент доставляет выходные данные выполненного плана обратно пользователю.\n",
        "\n",
        "Существует 2 типа агентов:\n",
        "* `Toolkits` агенты (агент - ящик инструментов) - заточенные под выполнение конкретных задач или для работы с конкретным API.\n",
        "\n",
        "* `Generic` агенты (общего назначения) - универсальные, которые способны выполнять множество метазадач."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f136edc2-cfc9-4174-b19d-7297869fbf2c",
      "metadata": {
        "tags": [],
        "id": "f136edc2-cfc9-4174-b19d-7297869fbf2c"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from getpass import getpass\n",
        "import warnings\n",
        "warnings.filterwarnings('ignore')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5187a29a-8918-4c17-b8e3-b5bef1c57c3b",
      "metadata": {
        "tags": [],
        "id": "5187a29a-8918-4c17-b8e3-b5bef1c57c3b"
      },
      "outputs": [],
      "source": [
        "#!pip install langchain langchain_experimental langchain-openai openai tiktoken numexpr"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fa3df72e-4070-4912-927d-620070f48fda",
      "metadata": {
        "tags": [],
        "id": "fa3df72e-4070-4912-927d-620070f48fda"
      },
      "outputs": [],
      "source": [
        "# Для работы в колабе загрузите наш скрипт для использования ChatGPT на сервере курса!\n",
        "#!wget https://raw.githubusercontent.com/a-milenkin/LLM_practical_course/main/notebooks/utils.py"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4ac87aa2-1813-409c-bbaf-51a715b38dca",
      "metadata": {
        "tags": [],
        "id": "4ac87aa2-1813-409c-bbaf-51a715b38dca"
      },
      "outputs": [],
      "source": [
        "# # Если используете ключ от OpenAI, запустите эту ячейку\n",
        "# from langchain_openai import ChatOpenAI\n",
        "\n",
        "# # os.environ['OPENAI_API_KEY'] = \"Введите ваш OpenAI API ключ\"\n",
        "# os.environ['OPENAI_API_KEY'] = getpass(prompt='Введите ваш OpenAI API ключ')\n",
        "\n",
        "# # инициализируем языковую модель\n",
        "# llm = ChatOpenAI(temperature=0.0)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a32eddae-5c2f-4b38-8c77-39a93741d6ae",
      "metadata": {
        "tags": [],
        "id": "a32eddae-5c2f-4b38-8c77-39a93741d6ae"
      },
      "outputs": [],
      "source": [
        "from utils import ChatOpenAI\n",
        "# Если используете ключ из курса, запустите эту ячейку\n",
        "#from utils import ChatOpenAI\n",
        "\n",
        "#course_api_key= \"Введите ваш ключ, полученный в боте курса\"\n",
        "course_api_key = getpass(prompt=\"Введите ваш ключ, полученный в боте курса\")\n",
        "\n",
        "# инициализируем языковую модель\n",
        "llm = ChatOpenAI(temperature=0.0, course_api_key=course_api_key)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7ad37f1b-3d46-4316-b0b5-93d1927620dd",
      "metadata": {
        "id": "7ad37f1b-3d46-4316-b0b5-93d1927620dd"
      },
      "source": [
        " #  <center id=\"c2\"> 🛠🪚  Инструменты для агентов 🤖\n",
        "    \n",
        "<div class=\"alert alert-info\">\n",
        "\n",
        "Для использования агентов нам понадобятся 3 компонента:\n",
        "* LLM\n",
        "* Инструменты (Tools)\n",
        "* Сами агенты"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "219e4276-b822-4f8d-ae68-657d2d90775b",
      "metadata": {
        "id": "219e4276-b822-4f8d-ae68-657d2d90775b"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "\n",
        "Теперь давайте создадим наш первый `Tool` - калькулятор, используя уже знакомую нам `LLMMathChain`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "73333bea-1f9e-4414-b018-7501471d78c1",
      "metadata": {
        "tags": [],
        "id": "73333bea-1f9e-4414-b018-7501471d78c1"
      },
      "outputs": [],
      "source": [
        "from langchain.chains import LLMMathChain\n",
        "from langchain.agents import Tool\n",
        "\n",
        "llm_math = LLMMathChain.from_llm(llm=llm)\n",
        "\n",
        "# создаём math tool, задаём имя, описание и функцию\n",
        "math_tool = Tool(\n",
        "    name='Калькулятор',\n",
        "    func=llm_math.run,\n",
        "    description='Может производить математические расчёты.'\n",
        ")\n",
        "\n",
        "# Для передачи в агента, нам нужно поместить инструменты в список\n",
        "tools = [math_tool]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c46ee6e0-cbbd-483a-8bf3-43a39c8f4749",
      "metadata": {
        "tags": [],
        "id": "c46ee6e0-cbbd-483a-8bf3-43a39c8f4749",
        "outputId": "23800848-649a-4c17-9e78-ebde344773fa"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "('Калькулятор', 'Может производить математические расчёты.')"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "tools[0].name, tools[0].description"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b3aa3146-2d85-4602-a7fe-290da7f93310",
      "metadata": {
        "id": "b3aa3146-2d85-4602-a7fe-290da7f93310"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "\n",
        "Создадим нашего **первого агента**, передав в него инструменты (пока 1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d49aab2f-aaf7-438c-a588-592a926b866f",
      "metadata": {
        "tags": [],
        "id": "d49aab2f-aaf7-438c-a588-592a926b866f",
        "outputId": "ac425afc-8f3c-4041-eb5d-b89c444c6f90"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "/home/jovyan/.local/miniconda3/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `initialize_agent` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use Use new agent constructor methods like create_react_agent, create_json_agent, create_structured_chat_agent, etc. instead.\n",
            "  warn_deprecated(\n"
          ]
        }
      ],
      "source": [
        "from langchain.agents import initialize_agent\n",
        "\n",
        "first_agent = initialize_agent(\n",
        "    tools=tools,\n",
        "    llm=llm,\n",
        "    verbose=True,\n",
        "    handle_parsing_errors=True,\n",
        "    max_iterations=3\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "56d8c1c1-9f6c-4ab2-b0f6-e00aacbb8018",
      "metadata": {
        "tags": [],
        "id": "56d8c1c1-9f6c-4ab2-b0f6-e00aacbb8018",
        "outputId": "67a85af2-b4a4-49f7-979e-ffcf99cf1d54"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
            "\u001b[32;1m\u001b[1;3mI need to calculate the result of the given expression.\n",
            "Action: Калькулятор\n",
            "Action Input: (4.5*2.1)+2.2\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3mAnswer: 11.650000000000002\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mThe final answer is 11.650000000000002.\n",
            "Final Answer: 11.650000000000002\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "{'input': 'Сколько будет (4.5*2.1)+2.2?', 'output': '11.650000000000002'}"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "first_agent(\"Сколько будет (4.5*2.1)+2.2?\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f8ba035a-bf2f-431c-9c03-42192b49eaf8",
      "metadata": {
        "tags": [],
        "id": "f8ba035a-bf2f-431c-9c03-42192b49eaf8",
        "outputId": "26c5e25f-4864-47c6-f560-797e72505094"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11.650000000000002"
            ]
          },
          "execution_count": 50,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Проверим\n",
        "(4.5*2.1)+2.2"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7fc54b9c-91dd-4ef7-827b-3fb728a87ecc",
      "metadata": {
        "id": "7fc54b9c-91dd-4ef7-827b-3fb728a87ecc"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "    \n",
        "Попробуем по сложнее:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bc2e8361-9eca-4767-a1a2-2defab14527c",
      "metadata": {
        "tags": [],
        "id": "bc2e8361-9eca-4767-a1a2-2defab14527c",
        "outputId": "4024b1fc-f123-4ae8-fb9d-ad3b0d966d40"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
            "\u001b[32;1m\u001b[1;3mI need to calculate the total number of apples.\n",
            "Action: Калькулятор\n",
            "Action Input: 3 + (2.5 * 8)\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3mAnswer: 23.0\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mThe final answer is 23.\u001b[0m\n",
            "Observation: Invalid Format: Missing 'Action:' after 'Thought:\n",
            "Thought:\u001b[32;1m\u001b[1;3mI made a mistake in the format. I need to provide the correct format.\n",
            "Final Answer: The total number of apples is 23.\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "{'input': 'У Маши было 3 яблока, Гриша принёс ещё 2 с половиной ящика яблок.\\n            Сколько всего яблок у ребят, если ящик вмещает 8 яблок?',\n",
              " 'output': 'The total number of apples is 23.'}"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "first_agent('''У Маши было 3 яблока, Гриша принёс ещё 2 с половиной ящика яблок.\n",
        "            Сколько всего яблок у ребят, если ящик вмещает 8 яблок?''')"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1274a399-9064-4418-95f1-0329d1608573",
      "metadata": {
        "id": "1274a399-9064-4418-95f1-0329d1608573"
      },
      "source": [
        "### А что будет, если мы спросим не математический вопрос?\n",
        "```python\n",
        "first_agent(\"Столица Хорватии?\")\n",
        "```\n",
        "\n",
        "Получим ошибку: `ValueError: unknown format from LLM: I'm sorry, but I can only help with math-related questions.`\n",
        "\n",
        "<div class=\"alert alert-info\">\n",
        "\n",
        "Это происходит потому, что агент принуждает к использованию инструмента (это не всегда так). Обходной путь, который мы можем реализовать, — это просто добавить еще один инструмент, который может ответить на этот вопрос.\n",
        "\n",
        "Если мы хотим, чтобы агент мог отвечать на `general knowledge questions` (общие вопросы), можно добавить саму LLM как инструмент `LLM-tool`.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6dcaef08-4907-4763-8064-280c60e13f1d",
      "metadata": {
        "tags": [],
        "id": "6dcaef08-4907-4763-8064-280c60e13f1d"
      },
      "outputs": [],
      "source": [
        "# создаём LLM tool\n",
        "llm_tool = Tool(\n",
        "    name='Language Model',\n",
        "    func=llm.predict,\n",
        "    description='Отвечает на общие вопросы'\n",
        ")\n",
        "\n",
        "# Добавляем его к другим инструментам\n",
        "tools.append(llm_tool)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "ad63936b-a3b3-4610-b8cc-1dedb40a2bd8",
      "metadata": {
        "tags": [],
        "id": "ad63936b-a3b3-4610-b8cc-1dedb40a2bd8"
      },
      "outputs": [],
      "source": [
        "first_agent = initialize_agent(\n",
        "    tools=tools,\n",
        "    llm=llm,\n",
        "    verbose=True,\n",
        "    handle_parsing_errors=True,\n",
        "    max_iterations=3\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "23f4d000-8a9f-4ae9-b304-2c0bb5d8a9d1",
      "metadata": {
        "tags": [],
        "id": "23f4d000-8a9f-4ae9-b304-2c0bb5d8a9d1",
        "outputId": "82818df9-1e31-46f5-ee56-bda315e6af5b"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
            "\u001b[32;1m\u001b[1;3mI know that the capital of Croatia is Zagreb, but I can also confirm it using the language model.\n",
            "Action: Language Model\n",
            "Action Input: \"What is the capital of Croatia?\"\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3mThe capital of Croatia is Zagreb.\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mI now know the final answer\n",
            "Final Answer: The capital of Croatia is Zagreb.\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "{'input': 'Столица Хорватии?', 'output': 'The capital of Croatia is Zagreb.'}"
            ]
          },
          "execution_count": 38,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "first_agent(\"Столица Хорватии?\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2b52b3ec-9ac5-4352-829c-12771fcef9ae",
      "metadata": {
        "id": "2b52b3ec-9ac5-4352-829c-12771fcef9ae"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "\n",
        "Видим, что после ввода запроса, агент передаёт его в LLM, и модель решает какой из инструментов лучше использовать."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95b954ec-d04c-42f1-85fe-5c9a8620da8d",
      "metadata": {
        "id": "95b954ec-d04c-42f1-85fe-5c9a8620da8d"
      },
      "source": [
        "<div class=\"alert alert-info\">\n",
        "\n",
        "Иногда из-за особенностей токенизации, модель может ошибаться в ответах на достаточно простые вопросы:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e84fe0ce-d6c8-48e8-878a-fcd53e99aece",
      "metadata": {
        "tags": [],
        "id": "e84fe0ce-d6c8-48e8-878a-fcd53e99aece",
        "outputId": "49004ad4-99b6-4108-927c-c85c50d3346d"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "AIMessage(content='В слове \"зачёт\" 6 букв.')"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "llm.invoke(\"Сколько букв в слове зачёт?\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "628e6312-4b34-4ce4-9842-27dc01320598",
      "metadata": {
        "tags": [],
        "id": "628e6312-4b34-4ce4-9842-27dc01320598"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "\n",
        "Рассмотрим ещё один способ создания инструмента из Python-функции, при помощи декоратора `tool`.\n",
        "\n",
        "В функцию обязательно необходимо добавлять описание (`docstring`), чтобы агент понимал для чего её нужно применять!"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "0c89b312-d8b6-4e13-bca0-f5dc5689d18b",
      "metadata": {
        "tags": [],
        "id": "0c89b312-d8b6-4e13-bca0-f5dc5689d18b"
      },
      "outputs": [],
      "source": [
        "from langchain.agents import tool\n",
        "\n",
        "@tool\n",
        "def get_word_length(word: str) -> int:\n",
        "    \"\"\"Возвращает длину слова\"\"\" # добавляем docstring\n",
        "    return len(word)\n",
        "\n",
        "\n",
        "tools = [get_word_length]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6727ae05-912f-4005-86c1-332397df3491",
      "metadata": {
        "id": "6727ae05-912f-4005-86c1-332397df3491"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "\n",
        "Создадим агента с нашим инструментом, и посмотрим как он справится с задачей:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6f33bcf3-b1ea-4e12-9bdd-740cbf34db77",
      "metadata": {
        "tags": [],
        "id": "6f33bcf3-b1ea-4e12-9bdd-740cbf34db77",
        "outputId": "f108d4ce-626c-48b2-bbee-90424ac7c95a"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
            "\u001b[32;1m\u001b[1;3mI need to find the length of the word \"зачёт\".\n",
            "Action: get_word_length\n",
            "Action Input: \"зачёт\"\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3m5\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mThe word \"зачёт\" has 5 letters.\n",
            "Final Answer: 5\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "{'input': 'Сколько букв в слове зачёт?', 'output': '5'}"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "agent = initialize_agent(\n",
        "    tools=tools,\n",
        "    llm=llm,\n",
        "    verbose=True,\n",
        ")\n",
        "\n",
        "agent(\"Сколько букв в слове зачёт?\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ae9f529b-9978-4eb8-8ca2-645f92dc627d",
      "metadata": {
        "id": "ae9f529b-9978-4eb8-8ca2-645f92dc627d"
      },
      "source": [
        "# <center id=\"c3\"> 🐍 Python Agent 😎"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2ed4c889-7bbd-4176-aac1-aceda3f505fb",
      "metadata": {
        "id": "2ed4c889-7bbd-4176-aac1-aceda3f505fb"
      },
      "source": [
        "<div class=\"alert alert-info\">\n",
        "\n",
        "Если вы видели такие инструменты кодирования, как `GitHub Copilot`, и задавались вопросом, как они работают, то одна из задач, которые они делают, — это заставляют языковую модель написать код, а затем выполнить этот код. Мы можем сделать то же самое, создав агент `Python`. Для этого мы используем LLM, а также инструмент(tool) `PythonREPL`, который представляет собой способ выполнения`Python` кода, немного похожий на `Jupyter Notebook`, поэтому агент может выполнить этот код, используя его, получить некоторые результаты, и эти результаты будут переданы обратно агенту, чтобы он мог решить, что делать дальше."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5c3ba0ae-8e09-4db1-96f4-5d894fe8fa72",
      "metadata": {
        "tags": [],
        "id": "5c3ba0ae-8e09-4db1-96f4-5d894fe8fa72"
      },
      "outputs": [],
      "source": [
        "from langchain_experimental.tools.python.tool import PythonREPLTool\n",
        "from langchain.agents import initialize_agent\n",
        "\n",
        "py_agent = initialize_agent(\n",
        "    tools=[PythonREPLTool()],\n",
        "    llm=llm,\n",
        "    verbose=True,\n",
        "    handle_parsing_errors=True,\n",
        "    max_iterations=3\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c1398755-62be-413b-a008-e45a77e67184",
      "metadata": {
        "tags": [],
        "id": "c1398755-62be-413b-a008-e45a77e67184"
      },
      "outputs": [],
      "source": [
        "names = [\"Борис\", \"Олег\", \"Ия\", \"Александр\", \"Зоя\"]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fcc76e45-8c3d-42ca-9b64-36c57724c929",
      "metadata": {
        "tags": [],
        "id": "fcc76e45-8c3d-42ca-9b64-36c57724c929",
        "outputId": "471c1e11-11e5-4f96-e28e-21b96c34325a"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "Python REPL can execute arbitrary code. Use with caution.\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[32;1m\u001b[1;3mI can use the `sorted()` function with a custom key to sort the names by length in descending order.\n",
            "Action: Python_REPL\n",
            "Action Input: `names = ['Борис', 'Олег', 'Ия', 'Александр', 'Зоя']`\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3m\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mI can use the `sorted()` function with a custom key to sort the names by length in descending order.\n",
            "Action: Python_REPL\n",
            "Action Input: `sorted(names, key=lambda x: len(x), reverse=True)`\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3m\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mI now know the final answer\n",
            "Final Answer: ['Александр', 'Борис', 'Олег', 'Зоя', 'Ия']\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "\"['Александр', 'Борис', 'Олег', 'Зоя', 'Ия']\""
            ]
          },
          "execution_count": 45,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "py_agent.run(f'Отсортируй имена в списке по длине в порядке убывания и покажи результат: {names}')"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "45bcecb1-72cc-4b5a-9a6b-2593967095c0",
      "metadata": {
        "id": "45bcecb1-72cc-4b5a-9a6b-2593967095c0"
      },
      "source": [
        "# <center id=\"c4\"> ✍️🤖 Создаём первый мини-сервис"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "24e7d5c2-5889-4260-9275-e81e6aa74404",
      "metadata": {
        "id": "24e7d5c2-5889-4260-9275-e81e6aa74404"
      },
      "source": [
        "<div class=\"alert alert-info\">\n",
        "    \n",
        "Теперь давайте попробуем реализовать \"полезного\" агента с использованием нескольких инструментов.\n",
        "В этом примере мы будем использовать инструменты `Wikipedia`, `DuckDuckGo` и `Arxiv`, чтобы создать простой агент для написания эссе. <br> [Здесь](https://python.langchain.com/docs/integrations/tools/) доступен длинный список инструментов, которые агенты могут использовать для взаимодействия с внешним миром."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5bde2d7d-53bf-45ef-8c5b-311d9ed77c0e",
      "metadata": {
        "id": "5bde2d7d-53bf-45ef-8c5b-311d9ed77c0e"
      },
      "outputs": [],
      "source": [
        "#!pip install duckduckgo-search arxiv wikipedia"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d49e939d-0774-4bf2-8a07-4804c7fc8eed",
      "metadata": {
        "tags": [],
        "id": "d49e939d-0774-4bf2-8a07-4804c7fc8eed"
      },
      "outputs": [],
      "source": [
        "from langchain.agents import load_tools\n",
        "from langchain.tools import DuckDuckGoSearchRun\n",
        "\n",
        "search = DuckDuckGoSearchRun()\n",
        "\n",
        "# инструменты, поддерживаемые LangChain \"из коробки\", можно подгружать функцией load_tools\n",
        "tools = load_tools([\"arxiv\", \"wikipedia\"], llm=llm)\n",
        "\n",
        "tools.extend([\n",
        "    Tool(\n",
        "        name=\"Search\",\n",
        "        func=search.run,\n",
        "        description=\"useful for when you need to answer questions about current events.\"\n",
        "    ),\n",
        "])\n",
        "\n",
        "essay_agent = initialize_agent(\n",
        "    tools,\n",
        "    llm,\n",
        "    verbose=True,\n",
        "    handle_parsing_errors=True,\n",
        "    max_iterations=5)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "ea3d82cd-b1ce-4700-84de-18872c1ff388",
      "metadata": {
        "tags": [],
        "id": "ea3d82cd-b1ce-4700-84de-18872c1ff388",
        "outputId": "ab47be02-d09d-40a2-b59a-4fac59ea99cc"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
            "\u001b[32;1m\u001b[1;3mI need to gather information about Quentin Tarantino's style in cinema. I can use Wikipedia to get an overview of his career and arxiv to find any scholarly articles or research papers on his style.\n",
            "Action: Wikipedia\n",
            "Action Input: Quentin Tarantino\u001b[0m\n",
            "Observation: \u001b[33;1m\u001b[1;3mPage: Quentin Tarantino\n",
            "Summary: Quentin Jerome Tarantino (; born March 27, 1963) is an American film director, screenwriter, and actor. His films are characterized by stylized violence, extended dialogue including a pervasive use of profanity, and references to popular culture.\n",
            "Tarantino began his career as an independent filmmaker with the release of the crime film Reservoir Dogs in 1992. His second film, Pulp Fiction (1994), a dark comedy crime thriller, was a major success with critics and audiences winning numerous awards, including the Palme d'Or and the Academy Award for Best Original Screenplay. In 1996, he appeared in From Dusk till Dawn, also writing the screenplay. Tarantino's third film, Jackie Brown (1997), paid homage to blaxploitation films.\n",
            "In 2003, Tarantino directed Kill Bill: Volume 1, inspired by the traditions of martial arts films; it was followed by Volume 2 in 2004, with both volumes considered as a single film. He then made the exploitation-slasher Death Proof (2007), part of a double feature with Robert Rodriguez released under the collective title Grindhouse. His next film, Inglourious Basterds (2009), follows an alternate account of World War II. He followed this with Django Unchained (2012), a slave revenge Spaghetti Western, which won him his second Academy Award for Best Original Screenplay. His eighth film, The Hateful Eight (2015), is a revisionist Western thriller and opened to audiences with a roadshow release. His most recent film, Once Upon a Time in Hollywood (2019), is a comedy drama set in the late 1960s about the transition of Old Hollywood to New Hollywood. A novelization of the film was also published in 2021, becoming his debut novel.\n",
            "Tarantino's work has been subject to criticism, such as the depictions of violence and frequent inclusion of racial slurs. During Tarantino's career, his films have garnered a cult following; as well as critical and commercial success, he has been considered \"the single most influential director of his generation\". Apart from receiving the Palme d'Or and two Academy Awards, his other major awards include two BAFTAs and four Golden Globes.\n",
            "\n",
            "\n",
            "\n",
            "Page: Quentin Tarantino filmography\n",
            "Summary: Quentin Tarantino is an American filmmaker who has directed ten films. He first began his career in the 1980s by directing and writing Love Birds In Bondage and writing, directing and starring in the black-and-white My Best Friend's Birthday, a partially lost amateur short film which was never officially released. He impersonated musician Elvis Presley in a small role in the sitcom The Golden Girls (1988), and briefly appeared in Eddie Presley (1992). As an independent filmmaker, he directed, wrote, and appeared in the violent crime thriller Reservoir Dogs (1992), which tells the story of six strangers brought together for a jewelry heist. Proving to be Tarantino's breakthrough film, it was named the greatest independent film of all time by Empire. Tarantino's screenplay for Tony Scott's True Romance (1993) was nominated for a Saturn Award. Also in 1993, he served as an executive producer for Killing Zoe and wrote two other films.\n",
            "In 1994, Tarantino wrote and directed the neo-noir black comedy Pulp Fiction, a major critical and commercial success. Cited in the media as a defining film of modern Hollywood, the film earned Tarantino an Academy Award for Best Original Screenplay and a Best Director nomination. The following year, Tarantino directed The Man from Hollywood, one of the four segments of the anthology film Four Rooms, and an episode of ER, entitled \"Motherhood\". He wrote Robert Rodriguez's From Dusk till Dawn (1996)—one of the many collaborations between them—which attained cult status and spawned several sequels, in which they served as executive producers. Tarantino's next directorial ventures Jackie Brown (1997) and Kill Bill (2003–2004) were met with critical acclaim. The latter, a two-part martial arts film (Volume 1 and Volume 2), follows a former assassin \u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mI have gathered information about Quentin Tarantino's career and his films. Now I can use arxiv to find scholarly articles or research papers on his style in cinema.\n",
            "Action: arxiv\n",
            "Action Input: Quentin Tarantino cinema style\u001b[0m\n",
            "Observation: \u001b[36;1m\u001b[1;3mPublished: 2017-12-12\n",
            "Title: Generic Drone Control Platform for Autonomous Capture of Cinema Scenes\n",
            "Authors: Julien Fleureau, Quentin Galvane, François-Louis Tariolle, Philippe Guillotel\n",
            "Summary: The movie industry has been using Unmanned Aerial Vehicles as a new tool to\n",
            "produce more and more complex and aesthetic camera shots. However, the shooting\n",
            "process currently rely on manual control of the drones which makes it difficult\n",
            "and sometimes inconvenient to work with. In this paper we address the lack of\n",
            "autonomous system to operate generic rotary-wing drones for shooting purposes.\n",
            "We propose a global control architecture based on a high-level generic API used\n",
            "by many UAV. Our solution integrates a compound and coupled model of a generic\n",
            "rotary-wing drone and a Full State Feedback strategy. To address the specific\n",
            "task of capturing cinema scenes, we combine the control architecture with an\n",
            "automatic camera path planning approach that encompasses cinematographic\n",
            "techniques. The possibilities offered by our system are demonstrated through a\n",
            "series of experiments.\n",
            "\n",
            "Published: 2017-12-12\n",
            "Title: Automated Cinematography with Unmanned Aerial Vehicles\n",
            "Authors: Quentin Galvane, Julien Fleureau, Francois-Louis Tariolle, Philippe Guillotel\n",
            "Summary: The rise of Unmanned Aerial Vehicles and their increasing use in the cinema\n",
            "industry calls for the creation of dedicated tools. Though there is a range of\n",
            "techniques to automatically control drones for a variety of applications, none\n",
            "have considered the problem of producing cinematographic camera motion in\n",
            "real-time for shooting purposes. In this paper we present our approach to UAV\n",
            "navigation for autonomous cinematography. The contributions of this research\n",
            "are twofold: (i) we adapt virtual camera control techniques to UAV navigation;\n",
            "(ii) we introduce a drone-independent platform for high-level user interactions\n",
            "that integrates cinematographic knowledge. The results presented in this paper\n",
            "demonstrate the capacities of our tool to capture live movie scenes involving\n",
            "one or two moving actors.\n",
            "\n",
            "Published: 2009-01-22\n",
            "Title: Luce, Trasparenze e Cinema tra Arte e Scienza - Light, Transparency and Cinema between Art and Science\n",
            "Authors: Marcella Giulia Lorenzi\n",
            "Summary: From light and physical phenomena to cinema, an interdisciplinary percourse\n",
            "between art and science, from historical and critical references to the\n",
            "ultimate digital frontiers, including digital movies revolution, stereoscopy,\n",
            "holography, interfaces.\n",
            "  -----\n",
            "  Dalla luce ed i fenomeni fisici al cinema, un percorso interdisciplinare tra\n",
            "arte e scienza, dalle citazioni storiche e critiche alle ultime frontiere del\n",
            "digitale, inclusi il cinema digitale, la stereoscopia, la olografia, le\n",
            "interfacce.\u001b[0m\n",
            "Thought:\u001b[32;1m\u001b[1;3mI have gathered information about Quentin Tarantino's career and his films, as well as some scholarly articles on his style in cinema. I can now use this information to write a 1000-word essay on the topic: Style Quentin Tarantino in cinema.\n",
            "\n",
            "Final Answer: Quentin Tarantino's style in cinema is characterized by stylized violence, extended dialogue including a pervasive use of profanity, and references to popular culture. He is known for his independent filmmaking and has directed ten films, including Reservoir Dogs, Pulp Fiction, Kill Bill, Inglourious Basterds, Django Unchained, The Hateful Eight, and Once Upon a Time in Hollywood. Tarantino's films have garnered critical and commercial success, and he has been considered \"the single most influential director of his generation.\" His work has been subject to criticism for its depictions of violence and frequent inclusion of racial slurs. Overall, Tarantino's style in cinema is unique and has made a significant impact on the film industry.\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n",
            "Quentin Tarantino's style in cinema is characterized by stylized violence, extended dialogue including a pervasive use of profanity, and references to popular culture. He is known for his independent filmmaking and has directed ten films, including Reservoir Dogs, Pulp Fiction, Kill Bill, Inglourious Basterds, Django Unchained, The Hateful Eight, and Once Upon a Time in Hollywood. Tarantino's films have garnered critical and commercial success, and he has been considered \"the single most influential director of his generation.\" His work has been subject to criticism for its depictions of violence and frequent inclusion of racial slurs. Overall, Tarantino's style in cinema is unique and has made a significant impact on the film industry.\n"
          ]
        }
      ],
      "source": [
        "prompt = \"Write a 1000-word essay on topic: {topic}, use the tools to retrieve the necessary information.\"\n",
        "topic = \"Style Quentin Tarantino in cinema\"\n",
        "\n",
        "print(essay_agent.run(prompt.format(topic=topic)))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aa1b483f-7a17-491d-a3d0-9832997cb84b",
      "metadata": {
        "id": "aa1b483f-7a17-491d-a3d0-9832997cb84b"
      },
      "source": [
        "<div class=\"alert alert-success\">\n",
        "\n",
        "Агент, в целом, справился с задачей, видно, что сначала он сходил в Википедию, затем в Arxiv, потом выдал требуемое эссэ.\n",
        "Но в `Final answer` вместо эссэ на 1000 слов агент записал краткий ответ на вопрос, видимо, нужно получше составить промпт (можете потюнить промпт в качестве самостоятельной работы).\n",
        "    \n",
        "Тут мог возникнуть справедливый вопрос: А зачем использовать агента, если можно сделать тоже самое, например, с помощью `RouterChain`?\n",
        "В отличии от цепочек, где порядок действий жёстко прописан, агент получает на вход запрос (промпт), список доступных инструментов и сам решает какие именно инструменты и в каком порядке применить для решения задачи."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "54da8bb6-d9be-40c6-9098-a809c54c2fae",
      "metadata": {
        "id": "54da8bb6-d9be-40c6-9098-a809c54c2fae"
      },
      "source": [
        "### Так же с помощью `load_tools` можно подгрузить такой интересный tool:\n",
        "```python\n",
        "tools = load_tools([\"human\"])\n",
        "```\n",
        "\n",
        "<div class=\"alert alert-info\">\n",
        "\n",
        "В документации к этому tool сказано:\n",
        "> Human are AGI so they can certainly be used as a tool to help out AI agent when it is confused.\n",
        "\n",
        "[Здесь](https://python.langchain.com/docs/integrations/tools/human_tools) можно прочитать про этот инструмент подробнее, пока ещё ИИ не может справиться без нас 🫣"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "709e7b4a-8c43-4aee-a5e5-a485cd0bc567",
      "metadata": {
        "id": "709e7b4a-8c43-4aee-a5e5-a485cd0bc567"
      },
      "source": [
        "# <center id=\"c5\"> 🧸 Выводы и заключения ✅"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "55034146-01aa-4ae0-91fc-20f8decd6593",
      "metadata": {
        "id": "55034146-01aa-4ae0-91fc-20f8decd6593"
      },
      "source": [
        "<div class=\"alert alert-info\">\n",
        "    \n",
        "Подводя итог, можем выделить несколько явных преимуществ которые дают агенты `LangChain`:\n",
        "* **Удобство для пользователя**: агенты `LangChain` специально разработаны так, чтобы быть понятными и доступными даже для разработчиков, у которых нет большого опыта работы со сложными языковыми моделями.\n",
        "* **Универсальность**: адаптируемость агентов `LangChain` позволяет им находить применение для самых разных сценариев и требований.\n",
        "* **Расширенные возможности.** Используя возможности языковых моделей, агенты LangChain предоставляют такие функции, как понимание и генерация естественного языка, давая доступ к большому количеству функций.\n",
        "    \n",
        "В следующих уроках мы рассмотрим более сложные архитектуры агентов, с памятью, внешней базой знаний и пр."
      ]
    }
  ],
  "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.13"
    },
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}