fix function call error

pull/351/head
Elvis Saravia 9 months ago
parent e459a21211
commit f5a64f9a12

@ -2,42 +2,18 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"outputs": [],
"source": [
"import os\n",
"import openai\n",
"import json\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Set the OpenAI API Key"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"load_dotenv()\n",
"\n",
"# set openai api key\n",
"openai.api_key = os.environ['OPENAI_API_KEY']"
]
},
@ -50,17 +26,18 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_completion(messages, model=\"gpt-3.5-turbo-1106\", temperature=0, max_tokens=300, tools=None):\n",
"def get_completion(messages, model=\"gpt-3.5-turbo-1106\", temperature=0, max_tokens=300, tools=None, tool_choice=None):\n",
" response = openai.chat.completions.create(\n",
" model=model,\n",
" messages=messages,\n",
" temperature=temperature,\n",
" max_tokens=max_tokens,\n",
" tools=tools\n",
" tools=tools,\n",
" tool_choice=tool_choice\n",
" )\n",
" return response.choices[0].message"
]
@ -74,7 +51,7 @@
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@ -103,7 +80,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@ -134,7 +111,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
@ -150,14 +127,14 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_zDFJY7MgSkWAvu8h2cFTvdVm', function=Function(arguments='{\"location\":\"London\",\"unit\":\"celsius\"}', name='get_current_weather'), type='function')])\n"
"ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_ADST8mP0bkzu12qibeywdtQ7', function=Function(arguments='{\"location\":\"London\",\"unit\":\"celsius\"}', name='get_current_weather'), type='function')])\n"
]
}
],
@ -166,68 +143,335 @@
"print(response)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"response.tool_calls[0].function.arguments"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now capture the arguments:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"args = json.loads(response.tool_calls[0].function.arguments)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'{\"location\":\"London\",\"unit\":\"celsius\"}'"
"'{\"location\": \"London\", \"temperature\": \"50\", \"unit\": \"celsius\"}'"
]
},
"execution_count": 27,
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response.tool_calls[0].function.arguments"
"get_current_weather(**args)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now capture the arguments:"
"### Controlling Function Calling Behavior"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's say we were interested in designing this `function_calling` functionality in the context of an LLM-powered conversational agent. Your solution should then know what function to call or if it needs to be called at all. Let's try a simple example of a greeting message:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"args = json.loads(response.tool_calls[0].function.arguments)"
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": \"Hello! How are you?\",\n",
" }\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 35,
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'{\"location\": \"London\", \"temperature\": \"50\", \"unit\": \"celsius\"}'"
"ChatCompletionMessage(content=\"Hello! I'm here and ready to assist you. How can I help you today?\", role='assistant', function_call=None, tool_calls=None)"
]
},
"execution_count": 35,
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_current_weather(**args)"
"get_completion(messages, tools=tools)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can specify the behavior you want from function calling, which is desired to control the behavior of your system. By default, the model decide on its own whether to call a function and which function to call. This is achieved by setting `tool_choice: \"auto\"` which is the default setting. "
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content=\"Hello! I'm here and ready to assist you. How can I help you today?\", role='assistant', function_call=None, tool_calls=None)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_completion(messages, tools=tools, tool_choice=\"auto\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Setting `tool_choice: \"none\"` forces the model to not use any of the functions provided. "
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content=\"Hello! I'm here and ready to assist you. How can I help you today?\", role='assistant', function_call=None, tool_calls=None)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_completion(messages, tools=tools, tool_choice=\"none\")"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content='I will check the current weather in London for you.', role='assistant', function_call=None, tool_calls=None)"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": \"What's the weather like in London?\",\n",
" }\n",
"]\n",
"get_completion(messages, tools=tools, tool_choice=\"none\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also force the model to choose a function if that's the behavior you want in your application. Example:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_NzHx0V4zDnoCzvgaASGaUmCp', function=Function(arguments='{\"location\":\"London\",\"unit\":\"celsius\"}', name='get_current_weather'), type='function')])"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": \"What's the weather like in London?\",\n",
" }\n",
"]\n",
"get_completion(messages, tools=tools, tool_choice={\"type\": \"function\", \"function\": {\"name\": \"get_current_weather\"}})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The OpenAI APIs also support parallel function calling that can call multiple functions in one turn. "
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_BZo3k606xCW8fnIPlLdJVpRo', function=Function(arguments='{\"location\": \"London\", \"unit\": \"celsius\"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_rx3uTL4l3PQztPzca04t1Ecu', function=Function(arguments='{\"location\": \"Belmopan\", \"unit\": \"celsius\"}', name='get_current_weather'), type='function')])"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": \"What's the weather like in London and Belmopan in the coming days?\",\n",
" }\n",
"]\n",
"get_completion(messages, tools=tools)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can see in the response above that the response contains information from the function calls for the two locations queried. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Function Calling Response as Model Feedback\n",
"\n",
"You might also be interested in developing an agent that passes back the result obtained after calling your APIs with the inputs generated from function calling. Let's look at an example next:\n"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"messages = []\n",
"messages.append({\"role\": \"user\", \"content\": \"What's the weather like in Boston!\"})\n",
"assistant_message = get_completion(messages, tools=tools, tool_choice=\"auto\")\n",
"assistant_message = json.loads(assistant_message.model_dump_json())\n",
"assistant_message[\"content\"] = str(assistant_message[\"tool_calls\"][0][\"function\"])\n",
"\n",
"#a temporary patch but this should be handled differently\n",
"# remove \"function_call\" from assistant message\n",
"del assistant_message[\"function_call\"]"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"messages.append(assistant_message)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We then append the results of the `get_current_weather` function and pass it back to the model using a `tool` role."
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"# get the weather information to pass back to the model\n",
"weather = get_current_weather(messages[1][\"tool_calls\"][0][\"function\"][\"arguments\"])\n",
"\n",
"messages.append({\"role\": \"tool\",\n",
" \"tool_call_id\": assistant_message[\"tool_calls\"][0][\"id\"],\n",
" \"name\": assistant_message[\"tool_calls\"][0][\"function\"][\"name\"],\n",
" \"content\": weather})"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": []
"source": [
"final_response = get_completion(messages, tools=tools)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content='The current weather in Boston, MA is 50°F.', role='assistant', function_call=None, tool_calls=None)"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"final_response"
]
}
],
"metadata": {

Loading…
Cancel
Save