{"id":556,"date":"2023-08-01T12:01:00","date_gmt":"2023-08-01T12:01:00","guid":{"rendered":"https:\/\/yer.ac\/blog\/?p=556"},"modified":"2023-08-02T07:40:51","modified_gmt":"2023-08-02T07:40:51","slug":"using-openai-function-calling","status":"publish","type":"post","link":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/","title":{"rendered":"Using OpenAI Function Calling to have agents interact with your own API"},"content":{"rendered":"\n<p>As of June 2023, function calling was added to the OpenAI API when using the \/v1\/chat\/completions endpoint in GPT4 &amp; GPT3.5 turbo. Function calling is the ability for developers to describe functions to the model, make calls out to external APIs and infer from input if a function call needs to be made, and if all the requirements for the call have been met (prompting for additional information if required).<\/p>\n\n\n\n<p>Examples could include asking an agent to send an email, query a database, connect to an API or simply respond a certain way to particular queries.<\/p>\n\n\n\n<p>In this post I am aiming to have a GPT agent intepret text, infer if we need to make an API call  and finally executing custom code before returning a message to the user.<\/p>\n\n\n\n<p> To simplify the process I will be using the <a href=\"https:\/\/github.com\/jakecyr\/openai-function-calling\/\">openai-function-calling from Jake Cyr<\/a>, which facilitates the generation of JSON schema dictionaries, simplifying the implementation of custom functions.<\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-background-color has-background has-small-font-size\">For transparancy: This is more a mental note of what I was doing in case I come back to this later. My openAI knowledge is still developing and my Python knowledge is&#8230;. questionable.  Don&#8217;t take what I say here as a guaranteed tutorial !<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pre-Requisites<\/h2>\n\n\n\n<p>I am assuming an envirionment already set up for Python development, access to the OpenAI API, (including setting your API keys up) and ideally access to GPT-4.<\/p>\n\n\n\n<p>I am using the following packages, installed with <em>pip<\/em>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>openai<\/strong><\/li>\n\n\n\n<li><strong>openai_function_calling<\/strong><\/li>\n\n\n\n<li><strong>typing<\/strong> <\/li>\n\n\n\n<li><strong>json<\/strong><\/li>\n<\/ul>\n\n\n\n<p>So our imports look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>import openai\nfrom typing import Callable\nfrom openai_function_calling import Function, Parameter, FunctionDict\nimport requests\nimport json<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Instructing the model on your function<\/h2>\n\n\n\n<p>We start by defining the function itself (as in the action you want to take) &#8211; Just a placeholder for the moment.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>def create_new_system_user(username: str, password: str, firstName: str, surname: str) -&gt; str:\n    # Actions here, for now return\n    return \"User Created\"<\/code><\/pre>\n\n\n\n<p>Now, using the openai-function-calling library, we define an OpenAI &#8220;Function,&#8221; where we specify the function we want to call, its description, constraints, and any follow-ups the agent should consider. We also provide an array of parameters required for the function:<\/p>\n\n\n\n<p>Prompt engineering is fairly important here and being verbose is encouraged. I found that without instructing it to only act if the user was explitly implying they wanted to create a user it would often attempt to call the API incorrectly. <\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-background-color has-background has-small-font-size\"><strong>Note<\/strong>: I did have a lot of issues with the above when using the GPT-3.5-turbo model. Whilst function calling is supported it <em>really<\/em> struggled to ask for missing parameters or determine if the API should be called when ambiguous language was used. For example when I asked it to &#8220;create sausages using blah and blah&#8221; it still tried to call the user create API. GPT-4 did not have this issue.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>create_new_system_user_function = Function(\n    \"create_new_system_user\",\n    \"When explicitly asked to create a new user, and you are given all the required paramters. A user will be created within the system. Do not take action if the prompt does not explicitly ask to create a new user. If you do not have the required parameters, ask the user for them.\",\n    &#91;\n        Parameter(\"username\", \"string\", \"The username of the new user.\"),\n        Parameter(\"password\", \"string\", \"The password of the new user.\"),   \n        Parameter(\"firstName\", \"string\", \"The password of the new user.\"),         \n        Parameter(\"surname\", \"string\", \"The password of the new user.\"),         \n    ])<\/code><\/pre>\n\n\n\n<p>Finally we want to expose the FunctionDict which is essentially a JSON schema for the Function we defined.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>create_new_system_user_function_dict: FunctionDict = create_new_system_user_function.to_json_schema()<\/code><\/pre>\n\n\n\n<p>At this point you could run the Python file with a <code>print(create_new_system_user_function_dict)<\/code> at the end and see the JSON definition it creates, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>{'name': 'create_new_system_user', 'description': 'When explicitly asked to create a new user, and you are given all the required paramters. A user will be created within the system. Do not take action if the prompt does not explicitly ask to create a new user. If you do not have the required parameters, ask the user for them.', 'parameters': {'type': 'object', 'properties': {'username': {'type': 'string', 'description': 'The username of the new user.'}, 'password': {'type': 'string', 'description': 'The password of the new user.'}, 'firstName': {'type': 'string', 'description': 'The password of the new user.'}, 'surname': {'type': 'string', 'description': 'The password of the new user.'}}}}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Wiring up a basic chat loop<\/h2>\n\n\n\n<p>Now we can just add some standard boilerplate code for calling the Completions API on a while loop (Warning: I didn&#8217;t bother putting an exit condition in for this!). This code will simply make an array of <strong>messages<\/strong> which we will use to store the input as we go so the agent remembers context (as the message array is sent each time), and then have a while loop which will simply execute infefinitely and keep taking input from the user.. If you do not have access to GPT-4 you can change your model name here -i.e. GPT-3.5-turbo-0630<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>\nmessages: list&#91;dict&#91;str, str]] = &#91;\n    {\n        \"role\": \"system\", \n        \"content\": \"You are a helpful assistant.\"\n    } \n]\ndef DoChat():\n    while True:\n        message = input(\"User: \")\n        messages.append({\"role\": \"user\", \"content\": message})\n        response = openai.ChatCompletion.create(\n            model=\"gpt-4\",\n            messages=messages,\n            functions= &#91;create_new_system_user_function_dict],\n            function_call=\"auto\",\n            temperature=0.0,\n        )\n        response_message = response&#91;\"choices\"]&#91;0]&#91;\"message\"]\n        print(response_message)       \n\n\nDoChat()<\/code><\/pre>\n\n\n\n<p>Running this now won&#8217;t do much however, and the agent will continuously ask for more information.<\/p>\n\n\n\n<p>Now we need to see if the message has been intepreted as a function call, then have the agent execute the relevant function, before responding to the user. This can be achievved by adding the following code after we set the <code>response_message<\/code> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>if(\"function_call\" in response_message):\n            ## Call the function\n            available_functions: dict&#91;str, Callable] = {\n                \"create_new_system_user\": create_new_system_user\n            }\n            function_name = response_message&#91;\"function_call\"]&#91;\"name\"]\n            function_args = json.loads(response_message&#91;\"function_call\"]&#91;\"arguments\"])\n            function_to_call: Callable = available_functions&#91;function_name]\n            function_response= function_to_call(**function_args)\n            print(f\"{function_response}\")\n            messages.append({\"role\": \"assistant\", \"content\": function_response})<\/code><\/pre>\n\n\n\n<p>Now if we run the code with a prompt like <code>I want to make a new user<\/code> it will prompt for more information, and when it thinks it has met all the variables, execute the function at which point we see the print statement in the <code>create_new_system_user<\/code> method. <\/p>\n\n\n\n<p>Finally, we just need to edit the code within the <code>create_new_system_user<\/code> method to call out to our API and then return an appropriate string &#8211; Which I have omitted here as its system specific.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The final code<\/h2>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>import openai\nfrom typing import Callable\nfrom openai_function_calling import Function, Parameter, FunctionDict\nimport json\n\n\ndef create_new_system_user(username: str, password: str, firstName: str, surname: str) -&gt; str:\n   # Make an API call (omitted for this example)\n   # Handle response as success or false\n   # Return an appropriate message to the user\n   # For now just return a placeholder message\n   return \"User has been created\"\n\ncreate_new_system_user_function = Function(\n    \"create_new_system_user\",\n    \"When explicitly asked to create a new user, and you are given all the required paramters. A user will be created within the system. Do not take action if the prompt does not explicitly ask to create a new user. If you do not have the required parameters, ask the user for them.\",\n    &#91;\n        Parameter(\"username\", \"string\", \"The username of the new user.\"),\n        Parameter(\"password\", \"string\", \"The password of the new user.\"),   \n        Parameter(\"firstName\", \"string\", \"The password of the new user.\"),         \n        Parameter(\"surname\", \"string\", \"The password of the new user.\"),         \n    ])\n\ncreate_new_system_user_function_dict: FunctionDict = create_new_system_user_function.to_json_schema()\n\n\nmessages: list&#91;dict&#91;str, str]] = &#91;\n    {\n        \"role\": \"system\", \n        \"content\": \"You are a helpful assistant.\"\n    } \n]\ndef DoChat():\n    while True:\n        message = input(\"User: \")\n        messages.append({\"role\": \"user\", \"content\": message})\n        response = openai.ChatCompletion.create(\n            model=\"gpt-4\",\n            messages=messages,\n            functions= &#91;create_new_system_user_function_dict],\n            function_call=\"auto\",\n            temperature=0.0,\n        )\n        response_message = response&#91;\"choices\"]&#91;0]&#91;\"message\"]\n        print(response_message)\n        if(\"function_call\" in response_message):\n            ## Call the function\n            available_functions: dict&#91;str, Callable] = {\n                \"create_new_system_user\": create_new_system_user\n            }\n            function_name = response_message&#91;\"function_call\"]&#91;\"name\"]\n            function_args = json.loads(response_message&#91;\"function_call\"]&#91;\"arguments\"])\n            function_to_call: Callable = available_functions&#91;function_name]\n            function_response= function_to_call(**function_args)\n            print(f\"{function_response}\")\n            messages.append({\"role\": \"assistant\", \"content\": function_response}) \n\n\nDoChat()<\/code><\/pre>\n\n\n\n<p class=\"has-vivid-cyan-blue-background-color has-background has-small-font-size\">Note: Sometimes odd things happen. Occasionally it would think it had met all the criteria and attempt to call my API with a missing param. Still early days, or perhaps more error checking&#8230; I did say this wasn&#8217;t a robust tutorial \ud83d\ude42 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>As of June 2023, function calling was added to the OpenAI API when using the \/v1\/chat\/completions endpoint in GPT4 &amp; GPT3.5 turbo. Function calling is the ability for developers to describe functions to the model, make calls out to external APIs and infer from input if a function call needs to be made, and if &hellip;<\/p>\n","protected":false},"author":1,"featured_media":567,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[45],"tags":[48,49,46,47],"class_list":["post-556","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-openai","tag-function-calling","tag-gpt","tag-openai","tag-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Using OpenAI Function Calling to have agents interact with your own API - yer.ac | Adventures of a developer, and other things.<\/title>\n<meta name=\"description\" content=\"Using Open AI Function Calling to call your own API full tutorial. GPT4 Natural Langage processing.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using OpenAI Function Calling to have agents interact with your own API - yer.ac | Adventures of a developer, and other things.\" \/>\n<meta property=\"og:description\" content=\"Using Open AI Function Calling to call your own API full tutorial. GPT4 Natural Langage processing.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/\" \/>\n<meta property=\"og:site_name\" content=\"yer.ac | Adventures of a developer, and other things.\" \/>\n<meta property=\"article:published_time\" content=\"2023-08-01T12:01:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-02T07:40:51+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1300\" \/>\n\t<meta property=\"og:image:height\" content=\"953\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"yer.ac\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"yer.ac\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/\"},\"author\":{\"name\":\"yer.ac\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\"},\"headline\":\"Using OpenAI Function Calling to have agents interact with your own API\",\"datePublished\":\"2023-08-01T12:01:00+00:00\",\"dateModified\":\"2023-08-02T07:40:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/\"},\"wordCount\":767,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\"},\"image\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1\",\"keywords\":[\"function-calling\",\"GPT\",\"openai\",\"python\"],\"articleSection\":[\"OpenAI\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/\",\"url\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/\",\"name\":\"Using OpenAI Function Calling to have agents interact with your own API - yer.ac | Adventures of a developer, and other things.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1\",\"datePublished\":\"2023-08-01T12:01:00+00:00\",\"dateModified\":\"2023-08-02T07:40:51+00:00\",\"description\":\"Using Open AI Function Calling to call your own API full tutorial. GPT4 Natural Langage processing.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1\",\"width\":1300,\"height\":953,\"caption\":\"Free ai generated art image\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2023\\\/08\\\/01\\\/using-openai-function-calling\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/yer.ac\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using OpenAI Function Calling to have agents interact with your own API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/yer.ac\\\/blog\\\/\",\"name\":\"yer.ac | Adventures of a developer, and other things.\",\"description\":\"Blog to keep track of things I am upto\",\"publisher\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/yer.ac\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\",\"name\":\"yer.ac\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\",\"caption\":\"yer.ac\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using OpenAI Function Calling to have agents interact with your own API - yer.ac | Adventures of a developer, and other things.","description":"Using Open AI Function Calling to call your own API full tutorial. GPT4 Natural Langage processing.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/","og_locale":"en_US","og_type":"article","og_title":"Using OpenAI Function Calling to have agents interact with your own API - yer.ac | Adventures of a developer, and other things.","og_description":"Using Open AI Function Calling to call your own API full tutorial. GPT4 Natural Langage processing.","og_url":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/","og_site_name":"yer.ac | Adventures of a developer, and other things.","article_published_time":"2023-08-01T12:01:00+00:00","article_modified_time":"2023-08-02T07:40:51+00:00","og_image":[{"width":1300,"height":953,"url":"http:\/\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg","type":"image\/jpeg"}],"author":"yer.ac","twitter_card":"summary_large_image","twitter_misc":{"Written by":"yer.ac","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#article","isPartOf":{"@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/"},"author":{"name":"yer.ac","@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d"},"headline":"Using OpenAI Function Calling to have agents interact with your own API","datePublished":"2023-08-01T12:01:00+00:00","dateModified":"2023-08-02T07:40:51+00:00","mainEntityOfPage":{"@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/"},"wordCount":767,"commentCount":0,"publisher":{"@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d"},"image":{"@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1","keywords":["function-calling","GPT","openai","python"],"articleSection":["OpenAI"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/","url":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/","name":"Using OpenAI Function Calling to have agents interact with your own API - yer.ac | Adventures of a developer, and other things.","isPartOf":{"@id":"https:\/\/yer.ac\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#primaryimage"},"image":{"@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1","datePublished":"2023-08-01T12:01:00+00:00","dateModified":"2023-08-02T07:40:51+00:00","description":"Using Open AI Function Calling to call your own API full tutorial. GPT4 Natural Langage processing.","breadcrumb":{"@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#primaryimage","url":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1","contentUrl":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1","width":1300,"height":953,"caption":"Free ai generated art image"},{"@type":"BreadcrumbList","@id":"https:\/\/yer.ac\/blog\/2023\/08\/01\/using-openai-function-calling\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/yer.ac\/blog\/"},{"@type":"ListItem","position":2,"name":"Using OpenAI Function Calling to have agents interact with your own API"}]},{"@type":"WebSite","@id":"https:\/\/yer.ac\/blog\/#website","url":"https:\/\/yer.ac\/blog\/","name":"yer.ac | Adventures of a developer, and other things.","description":"Blog to keep track of things I am upto","publisher":{"@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/yer.ac\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d","name":"yer.ac","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg","caption":"yer.ac"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2023\/08\/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvcHg1NDU5OTgtaW1hZ2Uta3d2eHB3ZHYuanBn.jpg?fit=1300%2C953&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/paP5IW-8Y","jetpack-related-posts":[{"id":112,"url":"https:\/\/yer.ac\/blog\/2019\/05\/29\/remote-nlog-logging-with-azure-functions-part-one\/","url_meta":{"origin":556,"position":0},"title":"Remote NLOG logging with Azure Functions (Part one).","author":"yer.ac","date":"May 29, 2019","format":false,"excerpt":"Part of a journey I was on today to learn about Azure Functions and Cosmos DB. The final code for the Azure Functions element can be found on https:\/\/github.com\/Wabbbit\/AzLog Part one: Setup, Creating my first function, forwarding NLOG events and deploying to Azure within VS Code.Part two: persisting the incoming\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/yer.ac\/blog\/category\/development\/azure\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/05\/image-4.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":151,"url":"https:\/\/yer.ac\/blog\/2019\/05\/29\/remote-nlog-logging-with-azure-functions-part-two-persisting-data-into-azure-cosmos-db\/","url_meta":{"origin":556,"position":1},"title":"Remote NLOG logging with Azure Functions (Part two) &#8211; Persisting data into Azure Cosmos DB.","author":"yer.ac","date":"May 29, 2019","format":false,"excerpt":"Last time, I got a very basic C# Azure Function hooked up to accept a request from an NLOG web service target. This time, I will be attempting to persist(insert) the incoming log information into an Azure Cosmos database container, direct from my Azure Function in VS Code. Disclaimer: This\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/yer.ac\/blog\/category\/development\/azure\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/05\/image-12.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/05\/image-12.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/05\/image-12.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/05\/image-12.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/05\/image-12.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":576,"url":"https:\/\/yer.ac\/blog\/2025\/08\/18\/vibing-in-kiro-to-create-a-self-serve-portainer-wrapper\/","url_meta":{"origin":556,"position":2},"title":"Vibing in Kiro to create a self-serve Portainer wrapper.","author":"yer.ac","date":"August 18, 2025","format":false,"excerpt":"On a Friday afternoon with half an hour to spare, I tested Kiro, Amazon\u2019s new agentic IDE, against a real-world problem: giving my team a simple way to start and stop Docker services in Portainer. With nothing more than a rough prompt, a PowerShell script, and a few \u201cTrust command\u201d\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/yer.ac\/blog\/category\/development\/ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":285,"url":"https:\/\/yer.ac\/blog\/2019\/07\/31\/setting-up-a-self-hosted-build-agent-for-azure-devops\/","url_meta":{"origin":556,"position":3},"title":"Setting up a self-hosted build agent for Azure DevOps","author":"yer.ac","date":"July 31, 2019","format":false,"excerpt":"Azure DevOps has brilliant build pipeline options and as easy as it is to get set up with their hosted build agents, it can get quite costly rather quick. In this post I cover off setting up a self-hosted build agent for use with Azure. This post won't cover setting\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/yer.ac\/blog\/category\/development\/azure\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/07\/image.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":599,"url":"https:\/\/yer.ac\/blog\/2026\/01\/23\/from-acceptance-criteria-to-playwright-tests-with-mcp\/","url_meta":{"origin":556,"position":4},"title":"From Acceptance Criteria to Playwright Tests with MCP","author":"yer.ac","date":"January 23, 2026","format":false,"excerpt":"Modern UI test tooling has quietly raised the bar for who can participate. Playwright is powerful, but it assumes comfort with TypeScript, selectors, repo structure, and terminal use. That gap often collapses testing back onto developers, creating pressure to almost validate their own work. This proof of concept explores using\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/yer.ac\/blog\/category\/development\/ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":69,"url":"https:\/\/yer.ac\/blog\/2019\/04\/08\/attempting-to-use-mocha-chai-to-unit-test-es6\/","url_meta":{"origin":556,"position":5},"title":"Attempting to use Mocha &#038; Chai to unit test ES6.","author":"yer.ac","date":"April 8, 2019","format":false,"excerpt":"In this post I will cover using Mocha (JS test framework) and Chai (For BDD syntax) to unit test ES6 Javascript in VS Code. I started working on a small side project, for no reason other than to play with ES6+. It's a(nother) relatively simple toast library written in as\u2026","rel":"","context":"In &quot;Development&quot;","block_context":{"text":"Development","link":"https:\/\/yer.ac\/blog\/category\/development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts\/556","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/comments?post=556"}],"version-history":[{"count":12,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts\/556\/revisions"}],"predecessor-version":[{"id":570,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts\/556\/revisions\/570"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/media\/567"}],"wp:attachment":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/media?parent=556"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/categories?post=556"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/tags?post=556"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}