From 58213a681635bf1000f517a055a3a917084aa819 Mon Sep 17 00:00:00 2001 From: Aniket Maurya Date: Mon, 3 Jun 2024 00:56:49 +0100 Subject: [PATCH] update --- README.md | 4 +- examples/01-introduction-to-agents.ipynb | 536 +++++++++++++++++++++++ 2 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 examples/01-introduction-to-agents.ipynb diff --git a/README.md b/README.md index cdeb2af..255e857 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,10 @@ pip install git+https://github.com/aniketmaurya/agents.git@main ## Supported LLMs ✅ OpenAI + ✅ Cohere Command R and Command R+ -✅ LlamaCPP + +✅ LlamaCPP (open-source) ## Usage/Examples diff --git a/examples/01-introduction-to-agents.ipynb b/examples/01-introduction-to-agents.ipynb new file mode 100644 index 0000000..59b40e2 --- /dev/null +++ b/examples/01-introduction-to-agents.ipynb @@ -0,0 +1,536 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "eb465089", + "metadata": {}, + "source": [ + "## LLM chat completions" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8f118047c0a8a9b1", + "metadata": { + "ExecuteTime": { + "end_time": "2024-06-02T22:35:46.326809Z", + "start_time": "2024-06-02T22:35:46.101194Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from openai import OpenAI\n", + "import json\n", + "from rich import print\n", + "\n", + "import dotenv\n", + "dotenv.load_dotenv()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7ddaea086ae998b7", + "metadata": { + "ExecuteTime": { + "end_time": "2024-06-02T22:35:47.043635Z", + "start_time": "2024-06-02T22:35:47.027588Z" + } + }, + "outputs": [], + "source": [ + "client = OpenAI()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a7adf5593fa962c6", + "metadata": { + "ExecuteTime": { + "end_time": "2024-06-02T22:36:31.796831Z", + "start_time": "2024-06-02T22:36:30.005094Z" + } + }, + "outputs": [], + "source": [ + "messages = [{\"role\": \"user\", \"content\": \"What's the weather like in London?\"}]\n", + "response = client.chat.completions.create(\n", + " model=\"gpt-4o\",\n", + " messages=messages,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a4a7f3401a7cac3e", + "metadata": { + "ExecuteTime": { + "end_time": "2024-06-02T22:36:32.560187Z", + "start_time": "2024-06-02T22:36:32.555838Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
ChatCompletion(\n",
+       "    id='chatcmpl-9VpIJALaA6vzFVBja2GoRVXzXiRox',\n",
+       "    choices=[\n",
+       "        Choice(\n",
+       "            finish_reason='stop',\n",
+       "            index=0,\n",
+       "            logprobs=None,\n",
+       "            message=ChatCompletionMessage(\n",
+       "                content=\"I'm unable to provide real-time information, including the current weather. To find out \n",
+       "the weather in London right now, you can check a reliable weather website, use a weather app, or ask a virtual \n",
+       "assistant equipped with real-time data capabilities.\",\n",
+       "                role='assistant',\n",
+       "                function_call=None,\n",
+       "                tool_calls=None\n",
+       "            )\n",
+       "        )\n",
+       "    ],\n",
+       "    created=1717372371,\n",
+       "    model='gpt-4o-2024-05-13',\n",
+       "    object='chat.completion',\n",
+       "    system_fingerprint='fp_319be4768e',\n",
+       "    usage=CompletionUsage(completion_tokens=48, prompt_tokens=14, total_tokens=62)\n",
+       ")\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1;35mChatCompletion\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mid\u001b[0m=\u001b[32m'chatcmpl-9VpIJALaA6vzFVBja2GoRVXzXiRox'\u001b[0m,\n", + " \u001b[33mchoices\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mChoice\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mfinish_reason\u001b[0m=\u001b[32m'stop'\u001b[0m,\n", + " \u001b[33mindex\u001b[0m=\u001b[1;36m0\u001b[0m,\n", + " \u001b[33mlogprobs\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mmessage\u001b[0m=\u001b[1;35mChatCompletionMessage\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mcontent\u001b[0m=\u001b[32m\"I\u001b[0m\u001b[32m'm unable to provide real-time information, including the current weather. To find out \u001b[0m\n", + "\u001b[32mthe weather in London right now, you can check a reliable weather website, use a weather app, or ask a virtual \u001b[0m\n", + "\u001b[32massistant equipped with real-time data capabilities.\"\u001b[0m,\n", + " \u001b[33mrole\u001b[0m=\u001b[32m'assistant'\u001b[0m,\n", + " \u001b[33mfunction_call\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mtool_calls\u001b[0m=\u001b[3;35mNone\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[33mcreated\u001b[0m=\u001b[1;36m1717372371\u001b[0m,\n", + " \u001b[33mmodel\u001b[0m=\u001b[32m'gpt-4o-2024-05-13'\u001b[0m,\n", + " \u001b[33mobject\u001b[0m=\u001b[32m'chat.completion'\u001b[0m,\n", + " \u001b[33msystem_fingerprint\u001b[0m=\u001b[32m'fp_319be4768e'\u001b[0m,\n", + " \u001b[33musage\u001b[0m=\u001b[1;35mCompletionUsage\u001b[0m\u001b[1m(\u001b[0m\u001b[33mcompletion_tokens\u001b[0m=\u001b[1;36m48\u001b[0m, \u001b[33mprompt_tokens\u001b[0m=\u001b[1;36m14\u001b[0m, \u001b[33mtotal_tokens\u001b[0m=\u001b[1;36m62\u001b[0m\u001b[1m)\u001b[0m\n", + "\u001b[1m)\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "c34cf502", + "metadata": {}, + "outputs": [], + "source": [ + "def get_current_weather(location):\n", + " \"\"\"Get the current weather in a given city\"\"\"\n", + " if \"london\" in location.lower():\n", + " return json.dumps({\"temperature\": \"20 C\"})\n", + " elif \"san francisco\" in location.lower():\n", + " return json.dumps({\"temperature\": \"15 C\"})\n", + " elif \"paris\" in location.lower():\n", + " return json.dumps({\"temperature\": \"22 C\"})\n", + " else:\n", + " return json.dumps({\"temperature\": \"unknown\"})\n", + "\n", + "\n", + "\n", + "messages = [{\"role\": \"user\", \"content\": \"What's the weather like in London?\"}]\n", + "tools = [\n", + " {\n", + " \"type\": \"function\",\n", + " \"function\": {\n", + " \"name\": \"get_current_weather\",\n", + " \"description\": \"Get the current weather in a given location\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"location\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The city and state, e.g. San Francisco\",\n", + " },\n", + " },\n", + " \"required\": [\"location\"],\n", + " },\n", + " },\n", + " }\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1810d401", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
ChatCompletion(\n",
+       "    id='chatcmpl-9VpILp6Z59Q0sIjRGAk14iktaUie6',\n",
+       "    choices=[\n",
+       "        Choice(\n",
+       "            finish_reason='tool_calls',\n",
+       "            index=0,\n",
+       "            logprobs=None,\n",
+       "            message=ChatCompletionMessage(\n",
+       "                content=None,\n",
+       "                role='assistant',\n",
+       "                function_call=None,\n",
+       "                tool_calls=[\n",
+       "                    ChatCompletionMessageToolCall(\n",
+       "                        id='call_KtSiNep0SfYtrlZGZ5v6umgT',\n",
+       "                        function=Function(arguments='{\"location\":\"London\"}', name='get_current_weather'),\n",
+       "                        type='function'\n",
+       "                    )\n",
+       "                ]\n",
+       "            )\n",
+       "        )\n",
+       "    ],\n",
+       "    created=1717372373,\n",
+       "    model='gpt-4o-2024-05-13',\n",
+       "    object='chat.completion',\n",
+       "    system_fingerprint='fp_319be4768e',\n",
+       "    usage=CompletionUsage(completion_tokens=15, prompt_tokens=66, total_tokens=81)\n",
+       ")\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1;35mChatCompletion\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mid\u001b[0m=\u001b[32m'chatcmpl-9VpILp6Z59Q0sIjRGAk14iktaUie6'\u001b[0m,\n", + " \u001b[33mchoices\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mChoice\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mfinish_reason\u001b[0m=\u001b[32m'tool_calls'\u001b[0m,\n", + " \u001b[33mindex\u001b[0m=\u001b[1;36m0\u001b[0m,\n", + " \u001b[33mlogprobs\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mmessage\u001b[0m=\u001b[1;35mChatCompletionMessage\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mcontent\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mrole\u001b[0m=\u001b[32m'assistant'\u001b[0m,\n", + " \u001b[33mfunction_call\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mtool_calls\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mid\u001b[0m=\u001b[32m'call_KtSiNep0SfYtrlZGZ5v6umgT'\u001b[0m,\n", + " \u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"location\":\"London\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'get_current_weather'\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[33mcreated\u001b[0m=\u001b[1;36m1717372373\u001b[0m,\n", + " \u001b[33mmodel\u001b[0m=\u001b[32m'gpt-4o-2024-05-13'\u001b[0m,\n", + " \u001b[33mobject\u001b[0m=\u001b[32m'chat.completion'\u001b[0m,\n", + " \u001b[33msystem_fingerprint\u001b[0m=\u001b[32m'fp_319be4768e'\u001b[0m,\n", + " \u001b[33musage\u001b[0m=\u001b[1;35mCompletionUsage\u001b[0m\u001b[1m(\u001b[0m\u001b[33mcompletion_tokens\u001b[0m=\u001b[1;36m15\u001b[0m, \u001b[33mprompt_tokens\u001b[0m=\u001b[1;36m66\u001b[0m, \u001b[33mtotal_tokens\u001b[0m=\u001b[1;36m81\u001b[0m\u001b[1m)\u001b[0m\n", + "\u001b[1m)\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "response = client.chat.completions.create(\n", + " model=\"gpt-4o\",\n", + " messages=messages,\n", + " tools=tools,\n", + ")\n", + "print(response)" + ] + }, + { + "cell_type": "markdown", + "id": "5d54a10b", + "metadata": {}, + "source": [ + "## Agents & Tool use" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b0bc6db9", + "metadata": {}, + "outputs": [], + "source": [ + "from agents.llms import OpenAIChatCompletion" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ecc4b19b", + "metadata": {}, + "outputs": [], + "source": [ + "from agents.tools import get_current_weather\n", + "from agents.tool_executor import need_tool_use" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "5023cac4", + "metadata": {}, + "outputs": [], + "source": [ + "llm = OpenAIChatCompletion()\n", + "llm.bind_tools([get_current_weather])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "a325bcb7", + "metadata": {}, + "outputs": [], + "source": [ + "messages = [\n", + " {\"role\": \"user\", \"content\": \"how is the weather in London today?\"}\n", + "]\n", + "\n", + "output = llm.chat_completion(messages)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "eca1a1d8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
ChatCompletion(\n",
+       "    id='chatcmpl-9VpIMyA2V34AZjastE7g98gNzCrSc',\n",
+       "    choices=[\n",
+       "        Choice(\n",
+       "            finish_reason='tool_calls',\n",
+       "            index=0,\n",
+       "            logprobs=None,\n",
+       "            message=ChatCompletionMessage(\n",
+       "                content=None,\n",
+       "                role='assistant',\n",
+       "                function_call=None,\n",
+       "                tool_calls=[\n",
+       "                    ChatCompletionMessageToolCall(\n",
+       "                        id='call_jqvvKaUmVUMl1WLej9AfGLpp',\n",
+       "                        function=Function(arguments='{\"city\":\"London\"}', name='get_current_weather'),\n",
+       "                        type='function'\n",
+       "                    )\n",
+       "                ]\n",
+       "            )\n",
+       "        )\n",
+       "    ],\n",
+       "    created=1717372374,\n",
+       "    model='gpt-4o-2024-05-13',\n",
+       "    object='chat.completion',\n",
+       "    system_fingerprint='fp_319be4768e',\n",
+       "    usage=CompletionUsage(completion_tokens=15, prompt_tokens=167, total_tokens=182)\n",
+       ")\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1;35mChatCompletion\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mid\u001b[0m=\u001b[32m'chatcmpl-9VpIMyA2V34AZjastE7g98gNzCrSc'\u001b[0m,\n", + " \u001b[33mchoices\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mChoice\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mfinish_reason\u001b[0m=\u001b[32m'tool_calls'\u001b[0m,\n", + " \u001b[33mindex\u001b[0m=\u001b[1;36m0\u001b[0m,\n", + " \u001b[33mlogprobs\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mmessage\u001b[0m=\u001b[1;35mChatCompletionMessage\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mcontent\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mrole\u001b[0m=\u001b[32m'assistant'\u001b[0m,\n", + " \u001b[33mfunction_call\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mtool_calls\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mid\u001b[0m=\u001b[32m'call_jqvvKaUmVUMl1WLej9AfGLpp'\u001b[0m,\n", + " \u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"city\":\"London\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'get_current_weather'\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[33mcreated\u001b[0m=\u001b[1;36m1717372374\u001b[0m,\n", + " \u001b[33mmodel\u001b[0m=\u001b[32m'gpt-4o-2024-05-13'\u001b[0m,\n", + " \u001b[33mobject\u001b[0m=\u001b[32m'chat.completion'\u001b[0m,\n", + " \u001b[33msystem_fingerprint\u001b[0m=\u001b[32m'fp_319be4768e'\u001b[0m,\n", + " \u001b[33musage\u001b[0m=\u001b[1;35mCompletionUsage\u001b[0m\u001b[1m(\u001b[0m\u001b[33mcompletion_tokens\u001b[0m=\u001b[1;36m15\u001b[0m, \u001b[33mprompt_tokens\u001b[0m=\u001b[1;36m167\u001b[0m, \u001b[33mtotal_tokens\u001b[0m=\u001b[1;36m182\u001b[0m\u001b[1m)\u001b[0m\n", + "\u001b[1m)\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print(output)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "4ce722d6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Using weather tool\n",
+       "
\n" + ], + "text/plain": [ + "Using weather tool\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
To determine the weather in London today based on the provided data, let's go through it step-by-step:\n",
+       "\n",
+       "1. **Temperature**:\n",
+       "    - Current temperature is 21°C (70°F).\n",
+       "    - Feels like temperature is also 21°C (70°F).\n",
+       "\n",
+       "2. **Weather Condition**:\n",
+       "    - The weather is described as \"Clear\".\n",
+       "\n",
+       "3. **Wind**:\n",
+       "    - Wind direction is North-Northwest (NNW) at a speed of 6 km/h (4 mph).\n",
+       "\n",
+       "4. **Precipitation**:\n",
+       "    - No precipitation is reported (0.0 mm or 0.0 inches).\n",
+       "\n",
+       "5. **Humidity**:\n",
+       "    - The humidity level is at 43%.\n",
+       "\n",
+       "6. **Pressure**:\n",
+       "    - The atmospheric pressure is 1024 hPa (30 inches).\n",
+       "\n",
+       "7. **Visibility**:\n",
+       "    - Visibility is 10 km (6 miles).\n",
+       "\n",
+       "8. **UV Index**:\n",
+       "    - UV Index is 5, which is moderate.\n",
+       "\n",
+       "Given this data, the weather in London today is clear with a temperature of around 21°C (70°F), light NNW wind, and\n",
+       "no precipitation.\n",
+       "
\n" + ], + "text/plain": [ + "To determine the weather in London today based on the provided data, let's go through it step-by-step:\n", + "\n", + "\u001b[1;36m1\u001b[0m. **Temperature**:\n", + " - Current temperature is \u001b[1;36m21\u001b[0m°C \u001b[1m(\u001b[0m\u001b[1;36m70\u001b[0m°F\u001b[1m)\u001b[0m.\n", + " - Feels like temperature is also \u001b[1;36m21\u001b[0m°C \u001b[1m(\u001b[0m\u001b[1;36m70\u001b[0m°F\u001b[1m)\u001b[0m.\n", + "\n", + "\u001b[1;36m2\u001b[0m. **Weather Condition**:\n", + " - The weather is described as \u001b[32m\"Clear\"\u001b[0m.\n", + "\n", + "\u001b[1;36m3\u001b[0m. **Wind**:\n", + " - Wind direction is North-Northwest \u001b[1m(\u001b[0mNNW\u001b[1m)\u001b[0m at a speed of \u001b[1;36m6\u001b[0m km/h \u001b[1m(\u001b[0m\u001b[1;36m4\u001b[0m mph\u001b[1m)\u001b[0m.\n", + "\n", + "\u001b[1;36m4\u001b[0m. **Precipitation**:\n", + " - No precipitation is reported \u001b[1m(\u001b[0m\u001b[1;36m0.0\u001b[0m mm or \u001b[1;36m0.0\u001b[0m inches\u001b[1m)\u001b[0m.\n", + "\n", + "\u001b[1;36m5\u001b[0m. **Humidity**:\n", + " - The humidity level is at \u001b[1;36m43\u001b[0m%.\n", + "\n", + "\u001b[1;36m6\u001b[0m. **Pressure**:\n", + " - The atmospheric pressure is \u001b[1;36m1024\u001b[0m hPa \u001b[1m(\u001b[0m\u001b[1;36m30\u001b[0m inches\u001b[1m)\u001b[0m.\n", + "\n", + "\u001b[1;36m7\u001b[0m. **Visibility**:\n", + " - Visibility is \u001b[1;36m10\u001b[0m km \u001b[1m(\u001b[0m\u001b[1;36m6\u001b[0m miles\u001b[1m)\u001b[0m.\n", + "\n", + "\u001b[1;36m8\u001b[0m. **UV Index**:\n", + " - UV Index is \u001b[1;36m5\u001b[0m, which is moderate.\n", + "\n", + "Given this data, the weather in London today is clear with a temperature of around \u001b[1;36m21\u001b[0m°C \u001b[1m(\u001b[0m\u001b[1;36m70\u001b[0m°F\u001b[1m)\u001b[0m, light NNW wind, and\n", + "no precipitation.\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "if need_tool_use(output):\n", + " print(\"Using weather tool\")\n", + " tool_results = llm.run_tools(output)\n", + " tool_results[0][\"role\"] = \"assistant\"\n", + "\n", + " updated_messages = messages + tool_results\n", + " updated_messages = updated_messages + [\n", + " {\"role\": \"user\", \"content\": \"Think step by step and answer my question based on the above context.\"}\n", + " ]\n", + " output = llm.chat_completion(updated_messages)\n", + "\n", + "print(output.choices[0].message.content)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12a66e9b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}