From a016a2844b5b2a73d0bb1f009ef7d429d713df43 Mon Sep 17 00:00:00 2001 From: bfdykstra Date: Mon, 6 Jan 2025 10:47:37 -0800 Subject: [PATCH] remove notebook, modify prepare output method --- libs/kotaemon/kotaemon/llms/chats/openai.py | 8 +- libs/kotaemon/test_structured_output.ipynb | 160 -------------------- 2 files changed, 2 insertions(+), 166 deletions(-) delete mode 100644 libs/kotaemon/test_structured_output.ipynb diff --git a/libs/kotaemon/kotaemon/llms/chats/openai.py b/libs/kotaemon/kotaemon/llms/chats/openai.py index 68786475e..13f3dbf9c 100644 --- a/libs/kotaemon/kotaemon/llms/chats/openai.py +++ b/libs/kotaemon/kotaemon/llms/chats/openai.py @@ -340,11 +340,6 @@ def prepare_output(self, resp: dict) -> StructuredOutputLLMInterface: """Convert the OpenAI response into StructuredOutputLLMInterface""" additional_kwargs = {} - if 'parsed' in resp['choices'][0]['message']: - additional_kwargs['parsed'] = resp["choices"][0]["message"][ - "parsed" - ] - if "tool_calls" in resp["choices"][0]["message"]: additional_kwargs["tool_calls"] = resp["choices"][0]["message"][ "tool_calls" @@ -359,7 +354,7 @@ def prepare_output(self, resp: dict) -> StructuredOutputLLMInterface: ) output = StructuredOutputLLMInterface( - **additional_kwargs, # TODO: clarify how additional_kwargs is used - diff bw BaseChatOpenAI usage and here + parsed = resp["choices"][0]["message"]["parsed"], candidates=[(_["message"]["content"] or "") for _ in resp["choices"]], content=resp["choices"][0]["message"]["content"] or "", total_tokens=resp["usage"]["total_tokens"], @@ -369,6 +364,7 @@ def prepare_output(self, resp: dict) -> StructuredOutputLLMInterface: AIMessage(content=(_["message"]["content"]) or "") for _ in resp["choices"] ], + additional_kwargs=additional_kwargs, logprobs=logprobs, ) diff --git a/libs/kotaemon/test_structured_output.ipynb b/libs/kotaemon/test_structured_output.ipynb deleted file mode 100644 index 065db8be5..000000000 --- a/libs/kotaemon/test_structured_output.ipynb +++ /dev/null @@ -1,160 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "hello world\n" - ] - } - ], - "source": [ - "print('hello world')" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "from kotaemon.llms import StructuredOutputChatOpenAI\n", - "# from libs.kotaemon.kotaemon.llms import StructuredOutputChatOpenAI" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import os\n", - "from dotenv import load_dotenv\n", - "load_dotenv()" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "from pydantic import BaseModel\n", - "\n", - "\n", - "class StructuredAnswer(BaseModel):\n", - " answer: str\n", - "\n", - "structured_llm = StructuredOutputChatOpenAI(\n", - " base_url='https://api.openai.com/v1',\n", - " model = 'gpt-4o-mini',\n", - " temperature= 1,\n", - " api_key = os.environ.get('OPENAI_API_KEY'),\n", - " response_schema=StructuredAnswer\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "Completions.parse() got an unexpected keyword argument 'stream'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstructured_llm\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mHello how are you?\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/base.py:1097\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1092\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcontext\u001b[38;5;241m.\u001b[39mclear(\n\u001b[1;32m 1093\u001b[0m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 1094\u001b[0m context\u001b[38;5;241m=\u001b[39m\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfl\u001b[38;5;241m.\u001b[39mflow_qualidx\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m|published_params\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 1095\u001b[0m )\n\u001b[1;32m 1096\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m-> 1097\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 1098\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 1099\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_variablex()\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/base.py:1088\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1086\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1087\u001b[0m func \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_middleware \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_middleware \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_runx\n\u001b[0;32m-> 1088\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfl\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexec\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1090\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfl\u001b[38;5;241m.\u001b[39mprefix: \u001b[38;5;66;03m# only root node has prefix as empty\u001b[39;00m\n\u001b[1;32m 1091\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig\u001b[38;5;241m.\u001b[39mparams_publish:\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/backends/base.py:151\u001b[0m, in \u001b[0;36mBackend.exec\u001b[0;34m(self, run, args, kwargs)\u001b[0m\n\u001b[1;32m 149\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mexec\u001b[39m(\u001b[38;5;28mself\u001b[39m, run, args, kwargs):\n\u001b[1;32m 150\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Execute the pipeline's run\"\"\"\u001b[39;00m\n\u001b[0;32m--> 151\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/middleware.py:144\u001b[0m, in \u001b[0;36mTrackProgressMiddleware.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 143\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mlog_progress(abs_pathx, \u001b[38;5;28minput\u001b[39m\u001b[38;5;241m=\u001b[39m_input, output\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, error\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mstr\u001b[39m(e))\n\u001b[0;32m--> 144\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 146\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\n\u001b[1;32m 147\u001b[0m inspect\u001b[38;5;241m.\u001b[39misgenerator(_output)\n\u001b[1;32m 148\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m inspect\u001b[38;5;241m.\u001b[39misasyncgen(_output)\n\u001b[1;32m 149\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m inspect\u001b[38;5;241m.\u001b[39miscoroutine(_output)\n\u001b[1;32m 150\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m inspect\u001b[38;5;241m.\u001b[39misawaitable(_output)\n\u001b[1;32m 151\u001b[0m ):\n\u001b[1;32m 152\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/middleware.py:141\u001b[0m, in \u001b[0;36mTrackProgressMiddleware.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 139\u001b[0m _input \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124margs\u001b[39m\u001b[38;5;124m\"\u001b[39m: args, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mkwargs\u001b[39m\u001b[38;5;124m\"\u001b[39m: kwargs}\n\u001b[1;32m 140\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 141\u001b[0m _output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnext_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 143\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mlog_progress(abs_pathx, \u001b[38;5;28minput\u001b[39m\u001b[38;5;241m=\u001b[39m_input, output\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, error\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mstr\u001b[39m(e))\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/middleware.py:117\u001b[0m, in \u001b[0;36mSkipComponentMiddleware.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mcontext\u001b[38;5;241m.\u001b[39mset(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgood_to_run\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m, context\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mfl\u001b[38;5;241m.\u001b[39mflow_qualidx)\n\u001b[1;32m 116\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mlog_progress(_ff_name, status\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 117\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnext_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/development/kotaemon/venv/lib/python3.10/site-packages/theflow/base.py:1017\u001b[0m, in \u001b[0;36mFunction._runx\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1015\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Subclass to handle pre- and post- run\"\"\"\u001b[39;00m\n\u001b[1;32m 1016\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfl\u001b[38;5;241m.\u001b[39min_run \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m-> 1017\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/development/kotaemon/libs/kotaemon/kotaemon/llms/base.py:25\u001b[0m, in \u001b[0;36mBaseLLM.run\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrun\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m---> 25\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/development/kotaemon/libs/kotaemon/kotaemon/llms/chats/openai.py:209\u001b[0m, in \u001b[0;36mBaseChatOpenAI.invoke\u001b[0;34m(self, messages, *args, **kwargs)\u001b[0m\n\u001b[1;32m 207\u001b[0m client \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprepare_client(async_version\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[1;32m 208\u001b[0m input_messages \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprepare_message(messages)\n\u001b[0;32m--> 209\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mopenai_response\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 210\u001b[0m \u001b[43m \u001b[49m\u001b[43mclient\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmessages\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minput_messages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[1;32m 211\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mdict()\n\u001b[1;32m 212\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprepare_output(resp)\n", - "File \u001b[0;32m~/development/kotaemon/libs/kotaemon/kotaemon/llms/chats/openai.py:385\u001b[0m, in \u001b[0;36mStructuredOutputChatOpenAI.openai_response\u001b[0;34m(self, client, **kwargs)\u001b[0m\n\u001b[1;32m 379\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Get the openai response\"\"\"\u001b[39;00m\n\u001b[1;32m 380\u001b[0m params \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 381\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[1;32m 382\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresponse_format\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mresponse_schema,\n\u001b[1;32m 383\u001b[0m }\n\u001b[0;32m--> 385\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbeta\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mchat\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcompletions\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[0;31mTypeError\u001b[0m: Completions.parse() got an unexpected keyword argument 'stream'" - ] - } - ], - "source": [ - "structured_llm('Hello how are you?')" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: pip in /Users/benjamindykstra/development/kotaemon/venv/lib/python3.10/site-packages (24.2)\n", - "Collecting pip\n", - " Downloading pip-24.3.1-py3-none-any.whl.metadata (3.7 kB)\n", - "Downloading pip-24.3.1-py3-none-any.whl (1.8 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m26.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hInstalling collected packages: pip\n", - " Attempting uninstall: pip\n", - " Found existing installation: pip 24.2\n", - " Uninstalling pip-24.2:\n", - " Successfully uninstalled pip-24.2\n", - "Successfully installed pip-24.3.1\n" - ] - } - ], - "source": [ - "!pip install --upgrade pip" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "venv", - "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.14" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -}