/ examples / demos / pythonmodel_agent_with_uc_tools.ipynb
pythonmodel_agent_with_uc_tools.ipynb
  1  {
  2   "cells": [
  3    {
  4     "cell_type": "markdown",
  5     "id": "befb4f50-828c-487a-8922-7a57991fb9d6",
  6     "metadata": {},
  7     "source": [
  8      "# Build an agent using UC tools and PythonModel\n",
  9      "This notebook will guide you through how to utilize MLflow PythonModel with type hints and Unitycatalog functions as tools to build an agent.\n",
 10      "\n",
 11      "## Prerequisite\n",
 12      "\n",
 13      "Install required packages:\n",
 14      "```\n",
 15      "pip install mlflow==2.20.0 'unitycatalog-langchain[databricks]==0.1.1' langchain_openai==0.3.7\n",
 16      "```\n",
 17      "\n",
 18      "Follow the [instruction](https://docs.databricks.com/aws/en/dev-tools/cli/authentication#authentication-for-the-databricks-cli) to authenticate to your Databricks workspace. Alternatively, check the [UnityCatalog client guidance](https://docs.unitycatalog.io/ai/client/#using-the-client-for-agent-tool-calling) on how to use UnityCatalog Server."
 19     ]
 20    },
 21    {
 22     "cell_type": "code",
 23     "execution_count": null,
 24     "id": "9062290c-f511-4094-ae8b-7a779e24a712",
 25     "metadata": {},
 26     "outputs": [],
 27     "source": [
 28      "import mlflow\n",
 29      "\n",
 30      "# start the mlflow server with `mlflow server` first, then set the tracking uri\n",
 31      "mlflow.set_tracking_uri(\"http://127.0.0.1:5000\")"
 32     ]
 33    },
 34    {
 35     "cell_type": "code",
 36     "execution_count": null,
 37     "id": "f506b2e3-0de0-4663-a634-5042a26c4cca",
 38     "metadata": {},
 39     "outputs": [],
 40     "source": [
 41      "mlflow.langchain.autolog()"
 42     ]
 43    },
 44    {
 45     "cell_type": "markdown",
 46     "id": "936eaccf-045f-4b83-9f3c-76e351d5e731",
 47     "metadata": {},
 48     "source": [
 49      "## Create a model"
 50     ]
 51    },
 52    {
 53     "cell_type": "markdown",
 54     "id": "d2dc19af-33d9-431c-8b5f-243d7a908008",
 55     "metadata": {},
 56     "source": [
 57      "### Create tools"
 58     ]
 59    },
 60    {
 61     "cell_type": "code",
 62     "execution_count": null,
 63     "id": "89ad5db3-b895-40a3-b382-fcc28c21a4c2",
 64     "metadata": {},
 65     "outputs": [],
 66     "source": [
 67      "from unitycatalog.ai.core.base import set_uc_function_client\n",
 68      "from unitycatalog.ai.core.databricks import DatabricksFunctionClient\n",
 69      "\n",
 70      "client = DatabricksFunctionClient()\n",
 71      "\n",
 72      "# sets the default uc function client\n",
 73      "set_uc_function_client(client)"
 74     ]
 75    },
 76    {
 77     "cell_type": "code",
 78     "execution_count": null,
 79     "id": "2ec578f6-8c23-477d-93b0-d44abf85e4ff",
 80     "metadata": {},
 81     "outputs": [],
 82     "source": [
 83      "CATALOG = \"ml\"\n",
 84      "SCHEMA = \"serena_test\""
 85     ]
 86    },
 87    {
 88     "cell_type": "code",
 89     "execution_count": null,
 90     "id": "720a4c2e-5634-4e28-b64f-dfef2eabe9de",
 91     "metadata": {},
 92     "outputs": [],
 93     "source": [
 94      "# Define a python code execution function\n",
 95      "def execute_python_code(code: str) -> str:\n",
 96      "    \"\"\"\n",
 97      "    Executes the given python code and returns its stdout.\n",
 98      "    Remember the code should print the final result to stdout.\n",
 99      "\n",
100      "    Args:\n",
101      "      code: Python code to execute. Remember to print the final result to stdout.\n",
102      "    \"\"\"\n",
103      "    # clint comment is used to disable lint check, you could delete them\n",
104      "    import sys  # clint: disable=lazy-import\n",
105      "    from io import StringIO  # clint: disable=lazy-import\n",
106      "\n",
107      "    stdout = StringIO()\n",
108      "    sys.stdout = stdout\n",
109      "    exec(code)  # noqa: S102\n",
110      "    return stdout.getvalue()\n",
111      "\n",
112      "\n",
113      "function_info = client.create_python_function(\n",
114      "    func=execute_python_code, catalog=CATALOG, schema=SCHEMA, replace=True\n",
115      ")\n",
116      "python_execution_function_name = function_info.full_name"
117     ]
118    },
119    {
120     "cell_type": "code",
121     "execution_count": null,
122     "id": "68fa8619-3f4c-410c-bc01-46f064f1c767",
123     "metadata": {
124      "scrolled": true
125     },
126     "outputs": [
127      {
128       "data": {
129        "text/plain": [
130         "FunctionInfo(browse_only=None, catalog_name='ml', comment='translate the content to target language, currently only english <-> spanish translation is supported', created_at=1741264002930, created_by='serena.ruan@databricks.com', data_type=<ColumnTypeName.STRING: 'STRING'>, external_language=None, external_name=None, full_data_type='STRING', full_name='ml.serena_test.translate', function_id='015ff53c-cdf9-453b-8e19-9a2332ca7b9f', input_params=FunctionParameterInfos(parameters=[FunctionParameterInfo(name='content', type_text='string', type_name=<ColumnTypeName.STRING: 'STRING'>, position=0, comment='content to translate', parameter_default=None, parameter_mode=None, parameter_type=<FunctionParameterType.PARAM: 'PARAM'>, type_interval_type=None, type_json='{\"name\":\"content\",\"type\":\"string\",\"nullable\":true,\"metadata\":{\"comment\":\"content to translate\"}}', type_precision=0, type_scale=0), FunctionParameterInfo(name='language', type_text='string', type_name=<ColumnTypeName.STRING: 'STRING'>, position=1, comment='target language', parameter_default=None, parameter_mode=None, parameter_type=<FunctionParameterType.PARAM: 'PARAM'>, type_interval_type=None, type_json='{\"name\":\"language\",\"type\":\"string\",\"nullable\":true,\"metadata\":{\"comment\":\"target language\"}}', type_precision=0, type_scale=0)]), is_deterministic=False, is_null_call=None, metastore_id='19a85dee-54bc-43a2-87ab-023d0ec16013', name='translate', owner='serena.ruan@databricks.com', parameter_style=<FunctionInfoParameterStyle.S: 'S'>, properties='{\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.taskWaitTimeInSeconds\":\"1000\",\"sqlConfig.spark.sql.ansi.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.decimal.dataType.enabled\":\"true\",\"referredTempFunctionsNames\":\"[]\",\"sqlConfig.spark.sql.streaming.statefulOperator.stateRebalancing.enabled\":\"false\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.dynamicPoolSizeEnabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.debugLogEnabled\":\"true\",\"catalogAndNamespace.part.0\":\"main\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.remoteHttpClient.maxConnections\":\"2048\",\"sqlConfig.spark.sql.legacy.createHiveTableByDefault\":\"false\",\"sqlConfig.spark.sql.shuffleDependency.skipMigration.enabled\":\"true\",\"sqlConfig.spark.sql.streaming.stopTimeout\":\"15s\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.remoteHttpClient.timeoutInSeconds\":\"360\",\"referredTempViewNames\":\"[]\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.enabled\":\"true\",\"sqlConfig.spark.sql.legacy.codingErrorAction\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.scaleUpThresholdCurrentQpsIncreaseRatio\":\"0.0\",\"sqlConfig.spark.databricks.sql.functions.builtInHttpReq.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.scaleUpThresholdTotalQpsIncreaseRatio\":\"0.0\",\"catalogAndNamespace.part.1\":\"default\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.useDedicatedHttpClient\":\"true\",\"sqlConfig.spark.sql.readSideCharPadding\":\"true\",\"sqlConfig.spark.sql.defaultStorage.zstdCompressionByDefault.enabled\":\"true\",\"sqlConfig.spark.sql.variable.substitute\":\"false\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.threadKeepAliveTimeInSeconds\":\"600\",\"sqlConfig.spark.databricks.sql.expression.aiFunctions.repartition\":\"0\",\"sqlConfig.spark.databricks.sql.functions.aiForecast.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.useDynamicTaskQueueExecutor\":\"false\",\"sqlConfig.spark.sql.sources.default\":\"delta\",\"sqlConfig.spark.sql.hive.convertCTAS\":\"true\",\"sqlConfig.spark.sql.legacy.jdbc.doNotUseCalendar\":\"false\",\"sqlConfig.spark.databricks.sql.functions.vectorSearch.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.safe.inference.enabled\":\"true\",\"sqlConfig.spark.sql.scripting.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.batch.aiQuery.embedding.request.size\":\"4\",\"referredTempVariableNames\":\"[]\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.batch.execution.size\":\"2048\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.clusterSizeBasedGlobalParallelism.scaleFactor\":\"32.0\",\"sqlConfig.spark.databricks.sql.functions.aiGen.endpointName\":\"databricks-meta-llama-3-3-70b-instruct\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.embeddingsEndpointName\":\"databricks-gte-large-en\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.batchSession.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.maxPoolSize\":\"2048\",\"sqlConfig.spark.sql.sources.commitProtocolClass\":\"com.databricks.sql.transaction.directory.DirectoryAtomicCommitProtocol\",\"sqlConfig.spark.sql.functions.remoteHttpClient.retryOn400TimeoutError\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.purposeBuiltFunctions.batch.execution.enabled\":\"true\",\"catalogAndNamespace.numParts\":\"2\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.adaptiveThreadPool.scaleUpThresholdSuccessRatio\":\"0.95\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.modelEndpointTypeParsing.enabled\":\"true\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.batchInferenceApi.enabled\":\"true\",\"sqlConfig.spark.sql.stableDerivedColumnAlias.enabled\":\"true\",\"sqlConfig.spark.sql.parquet.compression.codec\":\"snappy\",\"sqlConfig.spark.databricks.sql.functions.aiFunctions.model.parameters.enabled\":\"true\",\"sqlConfig.spark.sql.streaming.stateStore.providerClass\":\"com.databricks.sql.streaming.state.RocksDBStateStoreProvider\",\"sqlConfig.spark.sql.disableErrorOnCredentialMismatch\":\"true\"}', return_params=None, routine_body=<FunctionInfoRoutineBody.SQL: 'SQL'>, routine_definition='(SELECT ai_translate(content, language))', routine_dependencies=None, schema_name='serena_test', security_type=<FunctionInfoSecurityType.DEFINER: 'DEFINER'>, specific_name='translate', sql_data_access=<FunctionInfoSqlDataAccess.CONTAINS_SQL: 'CONTAINS_SQL'>, sql_path=None, updated_at=1741264002930, updated_by='serena.ruan@databricks.com')"
131        ]
132       },
133       "execution_count": null,
134       "metadata": {},
135       "output_type": "execute_result"
136      }
137     ],
138     "source": [
139      "translate_function_name = f\"{CATALOG}.{SCHEMA}.translate\"\n",
140      "sql_body = f\"\"\"CREATE OR REPLACE FUNCTION {translate_function_name}(content STRING COMMENT 'content to translate', language STRING COMMENT 'target language')\n",
141      "RETURNS STRING\n",
142      "COMMENT 'translate the content to target language, currently only english <-> spanish translation is supported'\n",
143      "RETURN SELECT ai_translate(content, language)\n",
144      "\"\"\"\n",
145      "client.create_function(sql_function_body=sql_body)"
146     ]
147    },
148    {
149     "cell_type": "code",
150     "execution_count": null,
151     "id": "648d5ecb-cfee-46f0-933d-29e914f973be",
152     "metadata": {},
153     "outputs": [],
154     "source": [
155      "from unitycatalog.ai.langchain.toolkit import UCFunctionToolkit\n",
156      "\n",
157      "toolkit = UCFunctionToolkit(\n",
158      "    function_names=[\n",
159      "        python_execution_function_name,\n",
160      "        translate_function_name,\n",
161      "    ]\n",
162      ")\n",
163      "tools = toolkit.tools"
164     ]
165    },
166    {
167     "cell_type": "code",
168     "execution_count": null,
169     "id": "6e38f029-d54f-4736-a32a-f8a4417bd64a",
170     "metadata": {},
171     "outputs": [
172      {
173       "data": {
174        "text/plain": [
175         "[UnityCatalogTool(name='ml__serena_test__execute_python_code', description='Executes the given python code and returns its stdout. Remember the code should print the final result to stdout.', args_schema=<class 'unitycatalog.ai.core.utils.function_processing_utils.ml__serena_test__execute_python_code__params'>, func=<function UCFunctionToolkit.uc_function_to_langchain_tool.<locals>.func at 0x3152293f0>, uc_function_name='ml.serena_test.execute_python_code', client_config={'warehouse_id': None, 'profile': None}),\n",
176         " UnityCatalogTool(name='ml__serena_test__translate', description='translate the content to target language, currently only english <-> spanish translation is supported', args_schema=<class 'unitycatalog.ai.core.utils.function_processing_utils.ml__serena_test__translate__params'>, func=<function UCFunctionToolkit.uc_function_to_langchain_tool.<locals>.func at 0x315f21a20>, uc_function_name='ml.serena_test.translate', client_config={'warehouse_id': None, 'profile': None})]"
177        ]
178       },
179       "execution_count": null,
180       "metadata": {},
181       "output_type": "execute_result"
182      }
183     ],
184     "source": [
185      "tools"
186     ]
187    },
188    {
189     "cell_type": "markdown",
190     "id": "20b796d3-b098-48c9-b62d-f725acfad29f",
191     "metadata": {},
192     "source": [
193      "### Define langgraph model"
194     ]
195    },
196    {
197     "cell_type": "code",
198     "execution_count": null,
199     "id": "df803a03-d0c0-46cc-af71-8b5330562c9e",
200     "metadata": {},
201     "outputs": [],
202     "source": [
203      "from typing import Literal\n",
204      "\n",
205      "from langchain_openai.chat_models import ChatOpenAI\n",
206      "from langgraph.graph import END, START, MessagesState, StateGraph\n",
207      "from langgraph.prebuilt import ToolNode\n",
208      "\n",
209      "tool_node = ToolNode(tools)\n",
210      "model = ChatOpenAI(model=\"gpt-4o-mini\").bind_tools(tools)\n",
211      "\n",
212      "\n",
213      "# Define the function that determines whether to continue or not\n",
214      "def should_continue(state: MessagesState) -> Literal[\"tools\", END]:\n",
215      "    messages = state[\"messages\"]\n",
216      "    last_message = messages[-1]\n",
217      "    # If the LLM makes a tool call, then we route to the \"tools\" node\n",
218      "    if last_message.tool_calls:\n",
219      "        return \"tools\"\n",
220      "    # Otherwise, we stop (reply to the user)\n",
221      "    return END\n",
222      "\n",
223      "\n",
224      "# Define the function that calls the model\n",
225      "def call_model(state: MessagesState):\n",
226      "    messages = state[\"messages\"]\n",
227      "    response = model.invoke(messages)\n",
228      "    # We return a list, because this will get added to the existing list\n",
229      "    return {\"messages\": [response]}\n",
230      "\n",
231      "\n",
232      "# Define a new graph\n",
233      "workflow = StateGraph(MessagesState)\n",
234      "\n",
235      "# Define the two nodes we will cycle between\n",
236      "workflow.add_node(\"agent\", call_model)\n",
237      "workflow.add_node(\"tools\", tool_node)\n",
238      "\n",
239      "# Set the entrypoint as `agent`\n",
240      "# This means that this node is the first one called\n",
241      "workflow.add_edge(START, \"agent\")\n",
242      "\n",
243      "# We now add a conditional edge\n",
244      "workflow.add_conditional_edges(\n",
245      "    # First, we define the start node. We use `agent`.\n",
246      "    # This means these are the edges taken after the `agent` node is called.\n",
247      "    \"agent\",\n",
248      "    # Next, we pass in the function that will determine which node is called next.\n",
249      "    should_continue,\n",
250      ")\n",
251      "\n",
252      "# We now add a normal edge from `tools` to `agent`.\n",
253      "# This means that after `tools` is called, `agent` node is called next.\n",
254      "workflow.add_edge(\"tools\", \"agent\")\n",
255      "\n",
256      "app = workflow.compile()"
257     ]
258    },
259    {
260     "cell_type": "markdown",
261     "id": "538b0311-dd95-4c8d-bb82-d35ff41aeb4f",
262     "metadata": {},
263     "source": [
264      "### Test the model first"
265     ]
266    },
267    {
268     "cell_type": "code",
269     "execution_count": null,
270     "id": "99f3cc51-5aa0-4c52-b38d-67f7ef5951d8",
271     "metadata": {},
272     "outputs": [],
273     "source": [
274      "final_state = app.invoke(\n",
275      "    {\n",
276      "        \"messages\": [\n",
277      "            {\n",
278      "                \"role\": \"user\",\n",
279      "                \"content\": \"What is MLflow? Keep the response concise and reply in Chinese. Try using as many tools as possible\",\n",
280      "            }\n",
281      "        ]\n",
282      "    },\n",
283      ")\n",
284      "response = final_state[\"messages\"][-1].content"
285     ]
286    },
287    {
288     "cell_type": "markdown",
289     "id": "ad1ceb8d-8654-4a31-b3b6-72ca7358a939",
290     "metadata": {},
291     "source": [
292      "## Save the model as python file --> agent.py"
293     ]
294    },
295    {
296     "cell_type": "markdown",
297     "id": "d3ee60f5-fe89-4371-9747-f2c7ab8697e1",
298     "metadata": {},
299     "source": [
300      "## Log the model"
301     ]
302    },
303    {
304     "cell_type": "code",
305     "execution_count": null,
306     "id": "37a9b50c-43a8-4799-9f9e-32ed93a4de98",
307     "metadata": {},
308     "outputs": [
309      {
310       "name": "stderr",
311       "output_type": "stream",
312       "text": [
313        "2025/03/06 21:08:14 INFO mlflow.models.signature: Inferring model signature from type hints\n",
314        "2025/03/06 21:08:14 INFO mlflow.models.signature: Running the predict function to generate output based on input example\n",
315        "2025/03/06 21:08:52 INFO mlflow.models.model: Found the following environment variables used during model inference: [OPENAI_API_KEY]. Please check if you need to set them when deploying the model. To disable this message, set environment variable `MLFLOW_RECORD_ENV_VARS_IN_MODEL_LOGGING` to `false`.\n"
316       ]
317      },
318      {
319       "name": "stdout",
320       "output_type": "stream",
321       "text": [
322        "๐Ÿƒ View run angry-conch-727 at: http://127.0.0.1:5000/#/experiments/0/runs/30690b953587448597c77ca9b2cfa371\n",
323        "๐Ÿงช View experiment at: http://127.0.0.1:5000/#/experiments/0\n"
324       ]
325      }
326     ],
327     "source": [
328      "input_example = [{\"messages\": [{\"role\": \"user\", \"content\": \"What is DSPy?\"}]}]\n",
329      "\n",
330      "with mlflow.start_run():\n",
331      "    model_info = mlflow.pyfunc.log_model(\n",
332      "        name=\"model\",\n",
333      "        # Pass the path to the saved model file\n",
334      "        python_model=\"agent.py\",\n",
335      "        input_example=input_example,\n",
336      "    )"
337     ]
338    },
339    {
340     "cell_type": "markdown",
341     "id": "23c1a000-bc49-4831-bb12-5e58c026eee0",
342     "metadata": {},
343     "source": [
344      "## Load model as pyfunc and predict"
345     ]
346    },
347    {
348     "cell_type": "code",
349     "execution_count": null,
350     "id": "c0db5686-6e88-41c7-9794-434afd0f8a9f",
351     "metadata": {},
352     "outputs": [
353      {
354       "data": {
355        "text/plain": [
356         "'DSPy is a framework for building and deploying decision-making systems in Python. It is used primarily in the context of machine learning and data science to create systems that can make predictions or decisions based on input data. DSPy facilitates the definition of decision rules, decision trees, and other logical constructs, allowing data scientists and developers to implement complex decision-making logic in a structured and manageable way.\\n\\nKey features of DSPy may include:\\n\\n1. **Declarative Syntax**: Provides a way to define rules and conditions in a readable and maintainable manner.\\n2. **Integration with Machine Learning**: Supports the incorporation of predictive models to enhance decision-making processes.\\n3. **Scalability**: Built to handle large datasets and complex decision logic without significant performance bottlenecks.\\n4. **Modularity**: Allows for reusable components and functions, making it easier to manage and update decision systems.\\n\\nOverall, DSPy aims to simplify the process of creating and managing decision-making systems, making it more accessible for data practitioners.'"
357        ]
358       },
359       "execution_count": null,
360       "metadata": {},
361       "output_type": "execute_result"
362      }
363     ],
364     "source": [
365      "pyfunc_model = mlflow.pyfunc.load_model(model_info.model_uri)\n",
366      "pyfunc_model.predict(input_example)"
367     ]
368    },
369    {
370     "cell_type": "code",
371     "execution_count": null,
372     "id": "ec82ca5b-59ce-437c-bbe6-11aab8ebc6d2",
373     "metadata": {
374      "scrolled": true
375     },
376     "outputs": [
377      {
378       "data": {
379        "application/vnd.jupyter.widget-view+json": {
380         "model_id": "3a821cf96f9e4da7874645dbce12f0c5",
381         "version_major": 2,
382         "version_minor": 0
383        },
384        "text/plain": [
385         "Downloading artifacts:   0%|          | 0/9 [00:00<?, ?it/s]"
386        ]
387       },
388       "metadata": {},
389       "output_type": "display_data"
390      },
391      {
392       "name": "stderr",
393       "output_type": "stream",
394       "text": [
395        "2025/03/06 22:00:44 INFO mlflow.models.flavor_backend_registry: Selected backend for flavor 'python_function'\n",
396        "2025/03/06 22:00:44 INFO mlflow.utils.virtualenv: Creating a new environment in /tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da with python version 3.10.15 using uv\n",
397        "Using CPython 3.10.15 interpreter at: \u001b[36m/Users/serena.ruan/miniconda3/envs/test/bin/python\u001b[39m\n",
398        "Creating virtual environment at: \u001b[36m/tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da\u001b[39m\n",
399        "Activate with: \u001b[32msource /tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da/bin/activate\u001b[39m\n",
400        "2025/03/06 22:00:46 INFO mlflow.utils.virtualenv: Installing dependencies\n",
401        "\u001b[2mUsing Python 3.10.15 environment at /tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da\u001b[0m\n",
402        "\u001b[2mResolved \u001b[1m3 packages\u001b[0m \u001b[2min 1.40s\u001b[0m\u001b[0m\n",
403        "\u001b[2mPrepared \u001b[1m3 packages\u001b[0m \u001b[2min 4.53s\u001b[0m\u001b[0m\n",
404        "\u001b[2mInstalled \u001b[1m3 packages\u001b[0m \u001b[2min 34ms\u001b[0m\u001b[0m\n",
405        " \u001b[32m+\u001b[39m \u001b[1mpip\u001b[0m\u001b[2m==24.2\u001b[0m\n",
406        " \u001b[32m+\u001b[39m \u001b[1msetuptools\u001b[0m\u001b[2m==75.1.0\u001b[0m\n",
407        " \u001b[32m+\u001b[39m \u001b[1mwheel\u001b[0m\u001b[2m==0.44.0\u001b[0m\n",
408        "\u001b[2mUsing Python 3.10.15 environment at /tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da\u001b[0m\n",
409        "\u001b[2mResolved \u001b[1m142 packages\u001b[0m \u001b[2min 21.39s\u001b[0m\u001b[0m\n",
410        "\u001b[2mPrepared \u001b[1m141 packages\u001b[0m \u001b[2min 4m 06s\u001b[0m\u001b[0m\n",
411        "\u001b[2mInstalled \u001b[1m141 packages\u001b[0m \u001b[2min 994ms\u001b[0m\u001b[0m\n",
412        " \u001b[32m+\u001b[39m \u001b[1maiohappyeyeballs\u001b[0m\u001b[2m==2.5.0\u001b[0m\n",
413        " \u001b[32m+\u001b[39m \u001b[1maiohttp\u001b[0m\u001b[2m==3.11.13\u001b[0m\n",
414        " \u001b[32m+\u001b[39m \u001b[1maiohttp-retry\u001b[0m\u001b[2m==2.9.1\u001b[0m\n",
415        " \u001b[32m+\u001b[39m \u001b[1maiosignal\u001b[0m\u001b[2m==1.3.2\u001b[0m\n",
416        " \u001b[32m+\u001b[39m \u001b[1malembic\u001b[0m\u001b[2m==1.15.1\u001b[0m\n",
417        " \u001b[32m+\u001b[39m \u001b[1mannotated-types\u001b[0m\u001b[2m==0.7.0\u001b[0m\n",
418        " \u001b[32m+\u001b[39m \u001b[1manyio\u001b[0m\u001b[2m==4.8.0\u001b[0m\n",
419        " \u001b[32m+\u001b[39m \u001b[1masttokens\u001b[0m\u001b[2m==3.0.0\u001b[0m\n",
420        " \u001b[32m+\u001b[39m \u001b[1masync-timeout\u001b[0m\u001b[2m==4.0.3\u001b[0m\n",
421        " \u001b[32m+\u001b[39m \u001b[1masyncio\u001b[0m\u001b[2m==3.4.3\u001b[0m\n",
422        " \u001b[32m+\u001b[39m \u001b[1mattrs\u001b[0m\u001b[2m==25.1.0\u001b[0m\n",
423        " \u001b[32m+\u001b[39m \u001b[1mblinker\u001b[0m\u001b[2m==1.9.0\u001b[0m\n",
424        " \u001b[32m+\u001b[39m \u001b[1mcachetools\u001b[0m\u001b[2m==5.5.2\u001b[0m\n",
425        " \u001b[32m+\u001b[39m \u001b[1mcertifi\u001b[0m\u001b[2m==2025.1.31\u001b[0m\n",
426        " \u001b[32m+\u001b[39m \u001b[1mcharset-normalizer\u001b[0m\u001b[2m==3.4.1\u001b[0m\n",
427        " \u001b[32m+\u001b[39m \u001b[1mclick\u001b[0m\u001b[2m==8.1.8\u001b[0m\n",
428        " \u001b[32m+\u001b[39m \u001b[1mcloudpickle\u001b[0m\u001b[2m==3.1.0\u001b[0m\n",
429        " \u001b[32m+\u001b[39m \u001b[1mcontourpy\u001b[0m\u001b[2m==1.3.1\u001b[0m\n",
430        " \u001b[32m+\u001b[39m \u001b[1mcycler\u001b[0m\u001b[2m==0.12.1\u001b[0m\n",
431        " \u001b[32m+\u001b[39m \u001b[1mdatabricks-connect\u001b[0m\u001b[2m==15.1.0\u001b[0m\n",
432        " \u001b[32m+\u001b[39m \u001b[1mdatabricks-sdk\u001b[0m\u001b[2m==0.44.1\u001b[0m\n",
433        " \u001b[32m+\u001b[39m \u001b[1mdataclasses-json\u001b[0m\u001b[2m==0.6.7\u001b[0m\n",
434        " \u001b[32m+\u001b[39m \u001b[1mdecorator\u001b[0m\u001b[2m==5.2.1\u001b[0m\n",
435        " \u001b[32m+\u001b[39m \u001b[1mdeprecated\u001b[0m\u001b[2m==1.2.18\u001b[0m\n",
436        " \u001b[32m+\u001b[39m \u001b[1mdistro\u001b[0m\u001b[2m==1.9.0\u001b[0m\n",
437        " \u001b[32m+\u001b[39m \u001b[1mdocker\u001b[0m\u001b[2m==7.1.0\u001b[0m\n",
438        " \u001b[32m+\u001b[39m \u001b[1mexceptiongroup\u001b[0m\u001b[2m==1.2.2\u001b[0m\n",
439        " \u001b[32m+\u001b[39m \u001b[1mexecuting\u001b[0m\u001b[2m==2.2.0\u001b[0m\n",
440        " \u001b[32m+\u001b[39m \u001b[1mflask\u001b[0m\u001b[2m==3.1.0\u001b[0m\n",
441        " \u001b[32m+\u001b[39m \u001b[1mfonttools\u001b[0m\u001b[2m==4.56.0\u001b[0m\n",
442        " \u001b[32m+\u001b[39m \u001b[1mfrozenlist\u001b[0m\u001b[2m==1.5.0\u001b[0m\n",
443        " \u001b[32m+\u001b[39m \u001b[1mgitdb\u001b[0m\u001b[2m==4.0.12\u001b[0m\n",
444        " \u001b[32m+\u001b[39m \u001b[1mgitpython\u001b[0m\u001b[2m==3.1.44\u001b[0m\n",
445        " \u001b[32m+\u001b[39m \u001b[1mgoogle-auth\u001b[0m\u001b[2m==2.38.0\u001b[0m\n",
446        " \u001b[32m+\u001b[39m \u001b[1mgoogleapis-common-protos\u001b[0m\u001b[2m==1.69.0\u001b[0m\n",
447        " \u001b[32m+\u001b[39m \u001b[1mgraphene\u001b[0m\u001b[2m==3.4.3\u001b[0m\n",
448        " \u001b[32m+\u001b[39m \u001b[1mgraphql-core\u001b[0m\u001b[2m==3.2.6\u001b[0m\n",
449        " \u001b[32m+\u001b[39m \u001b[1mgraphql-relay\u001b[0m\u001b[2m==3.2.0\u001b[0m\n",
450        " \u001b[32m+\u001b[39m \u001b[1mgrpcio\u001b[0m\u001b[2m==1.71.0rc2\u001b[0m\n",
451        " \u001b[32m+\u001b[39m \u001b[1mgrpcio-status\u001b[0m\u001b[2m==1.71.0rc2\u001b[0m\n",
452        " \u001b[32m+\u001b[39m \u001b[1mgunicorn\u001b[0m\u001b[2m==23.0.0\u001b[0m\n",
453        " \u001b[32m+\u001b[39m \u001b[1mh11\u001b[0m\u001b[2m==0.14.0\u001b[0m\n",
454        " \u001b[32m+\u001b[39m \u001b[1mhttpcore\u001b[0m\u001b[2m==1.0.7\u001b[0m\n",
455        " \u001b[32m+\u001b[39m \u001b[1mhttpx\u001b[0m\u001b[2m==0.28.1\u001b[0m\n",
456        " \u001b[32m+\u001b[39m \u001b[1mhttpx-sse\u001b[0m\u001b[2m==0.4.0\u001b[0m\n",
457        " \u001b[32m+\u001b[39m \u001b[1midna\u001b[0m\u001b[2m==3.10\u001b[0m\n",
458        " \u001b[32m+\u001b[39m \u001b[1mimportlib-metadata\u001b[0m\u001b[2m==8.6.1\u001b[0m\n",
459        " \u001b[32m+\u001b[39m \u001b[1mipython\u001b[0m\u001b[2m==8.33.0\u001b[0m\n",
460        " \u001b[32m+\u001b[39m \u001b[1mitsdangerous\u001b[0m\u001b[2m==2.2.0\u001b[0m\n",
461        " \u001b[32m+\u001b[39m \u001b[1mjedi\u001b[0m\u001b[2m==0.19.2\u001b[0m\n",
462        " \u001b[32m+\u001b[39m \u001b[1mjinja2\u001b[0m\u001b[2m==3.1.6\u001b[0m\n",
463        " \u001b[32m+\u001b[39m \u001b[1mjiter\u001b[0m\u001b[2m==0.8.2\u001b[0m\n",
464        " \u001b[32m+\u001b[39m \u001b[1mjoblib\u001b[0m\u001b[2m==1.4.2\u001b[0m\n",
465        " \u001b[32m+\u001b[39m \u001b[1mjsonpatch\u001b[0m\u001b[2m==1.33\u001b[0m\n",
466        " \u001b[32m+\u001b[39m \u001b[1mjsonpointer\u001b[0m\u001b[2m==3.0.0\u001b[0m\n",
467        " \u001b[32m+\u001b[39m \u001b[1mkiwisolver\u001b[0m\u001b[2m==1.4.8\u001b[0m\n",
468        " \u001b[32m+\u001b[39m \u001b[1mlangchain\u001b[0m\u001b[2m==0.3.20\u001b[0m\n",
469        " \u001b[32m+\u001b[39m \u001b[1mlangchain-community\u001b[0m\u001b[2m==0.3.19\u001b[0m\n",
470        " \u001b[32m+\u001b[39m \u001b[1mlangchain-core\u001b[0m\u001b[2m==0.3.41\u001b[0m\n",
471        " \u001b[32m+\u001b[39m \u001b[1mlangchain-openai\u001b[0m\u001b[2m==0.3.7\u001b[0m\n",
472        " \u001b[32m+\u001b[39m \u001b[1mlangchain-text-splitters\u001b[0m\u001b[2m==0.3.6\u001b[0m\n",
473        " \u001b[32m+\u001b[39m \u001b[1mlanggraph\u001b[0m\u001b[2m==0.3.5\u001b[0m\n",
474        " \u001b[32m+\u001b[39m \u001b[1mlanggraph-checkpoint\u001b[0m\u001b[2m==2.0.16\u001b[0m\n",
475        " \u001b[32m+\u001b[39m \u001b[1mlanggraph-prebuilt\u001b[0m\u001b[2m==0.1.2\u001b[0m\n",
476        " \u001b[32m+\u001b[39m \u001b[1mlanggraph-sdk\u001b[0m\u001b[2m==0.1.53\u001b[0m\n",
477        " \u001b[32m+\u001b[39m \u001b[1mlangsmith\u001b[0m\u001b[2m==0.3.11\u001b[0m\n",
478        " \u001b[32m+\u001b[39m \u001b[1mmako\u001b[0m\u001b[2m==1.3.9\u001b[0m\n",
479        " \u001b[32m+\u001b[39m \u001b[1mmarkdown\u001b[0m\u001b[2m==3.7\u001b[0m\n",
480        " \u001b[32m+\u001b[39m \u001b[1mmarkdown-it-py\u001b[0m\u001b[2m==3.0.0\u001b[0m\n",
481        " \u001b[32m+\u001b[39m \u001b[1mmarkupsafe\u001b[0m\u001b[2m==3.0.2\u001b[0m\n",
482        " \u001b[32m+\u001b[39m \u001b[1mmarshmallow\u001b[0m\u001b[2m==3.26.1\u001b[0m\n",
483        " \u001b[32m+\u001b[39m \u001b[1mmatplotlib\u001b[0m\u001b[2m==3.10.1\u001b[0m\n",
484        " \u001b[32m+\u001b[39m \u001b[1mmatplotlib-inline\u001b[0m\u001b[2m==0.1.7\u001b[0m\n",
485        " \u001b[32m+\u001b[39m \u001b[1mmdurl\u001b[0m\u001b[2m==0.1.2\u001b[0m\n",
486        " \u001b[32m+\u001b[39m \u001b[1mmlflow\u001b[0m\u001b[2m==2.20.3\u001b[0m\n",
487        " \u001b[32m+\u001b[39m \u001b[1mmlflow-skinny\u001b[0m\u001b[2m==2.20.3\u001b[0m\n",
488        " \u001b[32m+\u001b[39m \u001b[1mmsgpack\u001b[0m\u001b[2m==1.1.0\u001b[0m\n",
489        " \u001b[32m+\u001b[39m \u001b[1mmultidict\u001b[0m\u001b[2m==6.1.0\u001b[0m\n",
490        " \u001b[32m+\u001b[39m \u001b[1mmypy-extensions\u001b[0m\u001b[2m==1.0.0\u001b[0m\n",
491        " \u001b[32m+\u001b[39m \u001b[1mnest-asyncio\u001b[0m\u001b[2m==1.6.0\u001b[0m\n",
492        " \u001b[32m+\u001b[39m \u001b[1mnumpy\u001b[0m\u001b[2m==1.26.4\u001b[0m\n",
493        " \u001b[32m+\u001b[39m \u001b[1mopenai\u001b[0m\u001b[2m==1.65.4\u001b[0m\n",
494        " \u001b[32m+\u001b[39m \u001b[1mopentelemetry-api\u001b[0m\u001b[2m==1.16.0\u001b[0m\n",
495        " \u001b[32m+\u001b[39m \u001b[1mopentelemetry-sdk\u001b[0m\u001b[2m==1.16.0\u001b[0m\n",
496        " \u001b[32m+\u001b[39m \u001b[1mopentelemetry-semantic-conventions\u001b[0m\u001b[2m==0.37b0\u001b[0m\n",
497        " \u001b[32m+\u001b[39m \u001b[1morjson\u001b[0m\u001b[2m==3.10.15\u001b[0m\n",
498        " \u001b[32m+\u001b[39m \u001b[1mpackaging\u001b[0m\u001b[2m==24.2\u001b[0m\n",
499        " \u001b[32m+\u001b[39m \u001b[1mpandas\u001b[0m\u001b[2m==1.5.3\u001b[0m\n",
500        " \u001b[32m+\u001b[39m \u001b[1mparso\u001b[0m\u001b[2m==0.8.4\u001b[0m\n",
501        " \u001b[32m+\u001b[39m \u001b[1mpexpect\u001b[0m\u001b[2m==4.9.0\u001b[0m\n",
502        " \u001b[32m+\u001b[39m \u001b[1mpillow\u001b[0m\u001b[2m==11.1.0\u001b[0m\n",
503        " \u001b[32m+\u001b[39m \u001b[1mprompt-toolkit\u001b[0m\u001b[2m==3.0.50\u001b[0m\n",
504        " \u001b[32m+\u001b[39m \u001b[1mpropcache\u001b[0m\u001b[2m==0.3.0\u001b[0m\n",
505        " \u001b[32m+\u001b[39m \u001b[1mprotobuf\u001b[0m\u001b[2m==5.29.3\u001b[0m\n",
506        " \u001b[32m+\u001b[39m \u001b[1mpsutil\u001b[0m\u001b[2m==6.1.0\u001b[0m\n",
507        " \u001b[32m+\u001b[39m \u001b[1mptyprocess\u001b[0m\u001b[2m==0.7.0\u001b[0m\n",
508        " \u001b[32m+\u001b[39m \u001b[1mpure-eval\u001b[0m\u001b[2m==0.2.3\u001b[0m\n",
509        " \u001b[32m+\u001b[39m \u001b[1mpy4j\u001b[0m\u001b[2m==0.10.9.7\u001b[0m\n",
510        " \u001b[32m+\u001b[39m \u001b[1mpyarrow\u001b[0m\u001b[2m==17.0.0\u001b[0m\n",
511        " \u001b[32m+\u001b[39m \u001b[1mpyasn1\u001b[0m\u001b[2m==0.6.1\u001b[0m\n",
512        " \u001b[32m+\u001b[39m \u001b[1mpyasn1-modules\u001b[0m\u001b[2m==0.4.1\u001b[0m\n",
513        " \u001b[32m+\u001b[39m \u001b[1mpydantic\u001b[0m\u001b[2m==2.11.0a2\u001b[0m\n",
514        " \u001b[32m+\u001b[39m \u001b[1mpydantic-core\u001b[0m\u001b[2m==2.29.0\u001b[0m\n",
515        " \u001b[32m+\u001b[39m \u001b[1mpydantic-settings\u001b[0m\u001b[2m==2.8.1\u001b[0m\n",
516        " \u001b[32m+\u001b[39m \u001b[1mpygments\u001b[0m\u001b[2m==2.19.1\u001b[0m\n",
517        " \u001b[32m+\u001b[39m \u001b[1mpyparsing\u001b[0m\u001b[2m==3.2.1\u001b[0m\n",
518        " \u001b[32m+\u001b[39m \u001b[1mpython-dateutil\u001b[0m\u001b[2m==2.9.0.post0\u001b[0m\n",
519        " \u001b[32m+\u001b[39m \u001b[1mpython-dotenv\u001b[0m\u001b[2m==1.0.1\u001b[0m\n",
520        " \u001b[32m+\u001b[39m \u001b[1mpytz\u001b[0m\u001b[2m==2025.1\u001b[0m\n",
521        " \u001b[32m+\u001b[39m \u001b[1mpyyaml\u001b[0m\u001b[2m==6.0.2\u001b[0m\n",
522        " \u001b[32m+\u001b[39m \u001b[1mregex\u001b[0m\u001b[2m==2024.11.6\u001b[0m\n",
523        " \u001b[32m+\u001b[39m \u001b[1mrequests\u001b[0m\u001b[2m==2.32.3\u001b[0m\n",
524        " \u001b[32m+\u001b[39m \u001b[1mrequests-toolbelt\u001b[0m\u001b[2m==1.0.0\u001b[0m\n",
525        " \u001b[32m+\u001b[39m \u001b[1mrich\u001b[0m\u001b[2m==13.9.3\u001b[0m\n",
526        " \u001b[32m+\u001b[39m \u001b[1mrsa\u001b[0m\u001b[2m==4.9\u001b[0m\n",
527        " \u001b[32m+\u001b[39m \u001b[1mscikit-learn\u001b[0m\u001b[2m==1.6.1\u001b[0m\n",
528        " \u001b[32m+\u001b[39m \u001b[1mscipy\u001b[0m\u001b[2m==1.14.1\u001b[0m\n",
529        " \u001b[32m+\u001b[39m \u001b[1msix\u001b[0m\u001b[2m==1.17.0\u001b[0m\n",
530        " \u001b[32m+\u001b[39m \u001b[1msmmap\u001b[0m\u001b[2m==5.0.2\u001b[0m\n",
531        " \u001b[32m+\u001b[39m \u001b[1msniffio\u001b[0m\u001b[2m==1.3.1\u001b[0m\n",
532        " \u001b[32m+\u001b[39m \u001b[1msqlalchemy\u001b[0m\u001b[2m==2.0.38\u001b[0m\n",
533        " \u001b[32m+\u001b[39m \u001b[1msqlparse\u001b[0m\u001b[2m==0.5.3\u001b[0m\n",
534        " \u001b[32m+\u001b[39m \u001b[1mstack-data\u001b[0m\u001b[2m==0.6.3\u001b[0m\n",
535        " \u001b[32m+\u001b[39m \u001b[1mtenacity\u001b[0m\u001b[2m==9.0.0\u001b[0m\n",
536        " \u001b[32m+\u001b[39m \u001b[1mthreadpoolctl\u001b[0m\u001b[2m==3.5.0\u001b[0m\n",
537        " \u001b[32m+\u001b[39m \u001b[1mtiktoken\u001b[0m\u001b[2m==0.9.0\u001b[0m\n",
538        " \u001b[32m+\u001b[39m \u001b[1mtornado\u001b[0m\u001b[2m==6.4.2\u001b[0m\n",
539        " \u001b[32m+\u001b[39m \u001b[1mtqdm\u001b[0m\u001b[2m==4.67.1\u001b[0m\n",
540        " \u001b[32m+\u001b[39m \u001b[1mtraitlets\u001b[0m\u001b[2m==5.14.3\u001b[0m\n",
541        " \u001b[32m+\u001b[39m \u001b[1mtyping-extensions\u001b[0m\u001b[2m==4.12.2\u001b[0m\n",
542        " \u001b[32m+\u001b[39m \u001b[1mtyping-inspect\u001b[0m\u001b[2m==0.9.0\u001b[0m\n",
543        " \u001b[32m+\u001b[39m \u001b[1munitycatalog-ai\u001b[0m\u001b[2m==0.2.0\u001b[0m\n",
544        " \u001b[32m+\u001b[39m \u001b[1munitycatalog-client\u001b[0m\u001b[2m==0.2.1\u001b[0m\n",
545        " \u001b[32m+\u001b[39m \u001b[1munitycatalog-langchain\u001b[0m\u001b[2m==0.1.0\u001b[0m\n",
546        " \u001b[32m+\u001b[39m \u001b[1murllib3\u001b[0m\u001b[2m==2.3.0\u001b[0m\n",
547        " \u001b[32m+\u001b[39m \u001b[1mwcwidth\u001b[0m\u001b[2m==0.2.13\u001b[0m\n",
548        " \u001b[32m+\u001b[39m \u001b[1mwerkzeug\u001b[0m\u001b[2m==3.1.3\u001b[0m\n",
549        " \u001b[32m+\u001b[39m \u001b[1mwrapt\u001b[0m\u001b[2m==1.17.2\u001b[0m\n",
550        " \u001b[32m+\u001b[39m \u001b[1myarl\u001b[0m\u001b[2m==1.18.3\u001b[0m\n",
551        " \u001b[32m+\u001b[39m \u001b[1mzipp\u001b[0m\u001b[2m==3.21.0\u001b[0m\n",
552        " \u001b[32m+\u001b[39m \u001b[1mzstandard\u001b[0m\u001b[2m==0.23.0\u001b[0m\n",
553        "2025/03/06 22:05:21 WARNING mlflow.utils.databricks_utils: Missing required environment variable `SPARK_LOCAL_REMOTE` or `SPARK_REMOTE`. These are necessary to initialize the WorkspaceClient with serverless compute in a subprocess in Databricks for UC function execution. Setting the value to 'true'.\n",
554        "2025/03/06 22:05:21 INFO mlflow.utils.environment: === Running command '['bash', '-c', 'source /tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da/bin/activate && python -c \"\"']'\n",
555        "2025/03/06 22:05:21 WARNING mlflow.utils.databricks_utils: Missing required environment variable `SPARK_LOCAL_REMOTE` or `SPARK_REMOTE`. These are necessary to initialize the WorkspaceClient with serverless compute in a subprocess in Databricks for UC function execution. Setting the value to 'true'.\n",
556        "2025/03/06 22:05:21 INFO mlflow.utils.environment: === Running command '['bash', '-c', 'source /tmp/virtualenv_envs/mlflow-fff8396596a3739547c1db4c7f6f29e166a523da/bin/activate && python /Users/serena.ruan/miniconda3/envs/test/lib/python3.10/site-packages/mlflow/pyfunc/_mlflow_pyfunc_backend_predict.py --model-uri file:///Users/serena.ruan/Documents/test/mlruns/0/30690b953587448597c77ca9b2cfa371/artifacts/model --content-type json --input-path /var/folders/9g/psrbbvm92t712cy09d7_00d00000gp/T/tmp4ki9mgbc/input.json']'\n",
557        "/Users/serena.ruan/Documents/test/mlruns/0/30690b953587448597c77ca9b2cfa371/artifacts/model/agent.py:11: LangChainDeprecationWarning: As of langchain-core 0.3.0, LangChain uses pydantic v2 internally. The langchain_core.pydantic_v1 module was a compatibility shim for pydantic v1, and should no longer be used. Please update the code to import from Pydantic directly.\n",
558        "\n",
559        "For example, replace imports like: `from langchain_core.pydantic_v1 import BaseModel`\n",
560        "with: `from pydantic import BaseModel`\n",
561        "or the v1 compatibility namespace if you are working in a code base that has not been fully upgraded to pydantic 2 yet. \tfrom pydantic.v1 import BaseModel\n",
562        "\n",
563        "  from unitycatalog.ai.langchain.toolkit import UCFunctionToolkit\n"
564       ]
565      },
566      {
567       "name": "stdout",
568       "output_type": "stream",
569       "text": [
570        "{\"predictions\": \"The Spanish word for \\\"hello\\\" is \\\"hola\\\".\"}"
571       ]
572      }
573     ],
574     "source": [
575      "mlflow.models.predict(\n",
576      "    model_uri=model_info.model_uri,\n",
577      "    input_data=[{\"messages\": [{\"role\": \"user\", \"content\": \"What's Spanish for hello?\"}]}],\n",
578      "    env_manager=\"uv\",\n",
579      ")"
580     ]
581    }
582   ],
583   "metadata": {
584    "kernelspec": {
585     "display_name": "Python 3 (ipykernel)",
586     "language": "python",
587     "name": "python3"
588    },
589    "language_info": {
590     "codemirror_mode": {
591      "name": "ipython",
592      "version": 3
593     },
594     "file_extension": ".py",
595     "mimetype": "text/x-python",
596     "name": "python",
597     "nbconvert_exporter": "python",
598     "pygments_lexer": "ipython3",
599     "version": "3.10.15"
600    }
601   },
602   "nbformat": 4,
603   "nbformat_minor": 5
604  }