Package: openai_functools
openai-functoolsopenai-functoolsis a Python library designed to enhance the functionality of OpenAI's supported models for function calling,ref. the OpenAI official docs. This library focuses on generating the function metadata JSON automatically by wrapping existing Python functions in our decorator, or by registering them with our orchestrator. This removes the need for you to manually create and manage the JSON structures required for function calling in these models.Why openai-functoolsThe image below illustrates the reduction of code which needs to be manually written. The snippets in green are interchangeable with use of our library.?... So what is OpenAI Function Calling?OpenAI function calling provides a powerful mechanism to extend the capabilities of AI models, like gpt-3.5-turbo-0613 and gpt-4-0613. In an API call, these models can understand a set of functions described to them and generate JSON outputs that adhere to the defined function signatures.These modelsdon't actually perform the function calls- they merely generate the JSON data that you can use in your code to call these functions. This ability allows for a wide range of applications, such as creating chatbots that call external APIs, converting natural language into API calls, and extracting structured data from text.Typical openai functions flow:ref. the OpenAI official docs.InstallationThis package is hosted on PyPI and can be installed with pip:pipinstallopenai-functoolsAlternatively, you can clone this repository and install with Poetry:gitclonehttps://github.com/Jakob-98/openai-functools.gitcdopenai-functools
poetryinstallEnsure your environment variableOPENAI_API_KEYis set.UsageThis library is designed to streamline the usage of OpenAI's language models by simplifying the function metadata creation process. The following sections will walk you through a basic usage of openai-functools, including a traditional manual approach and our enhanced automatic approach using theopenai_functiondecorator.Manual ApproachTraditionally, you'd define a function, likeget_current_weather, and then manually create a JSON structure that describes this function. The structure includes the function name, description, and parameters it takes, as well as the types of these parameters.defget_current_weather(location,unit="fahrenheit"):weather_info={"location":location,"temperature":"72","unit":unit,"forecast":["sunny","windy"],}returnjson.dumps(weather_info)defrun_conversation():messages=[{"role":"user","content":"What's the weather like in London?"}]functions=[{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA",},"unit":{"type":"string","enum":["celsius","fahrenheit"]},},"required":["location"],},}]# Proceed with calling openai, invoking the function using the response, etc..Automated Approach using openai-functoolsTheopenai-functoolslibrary simplifies the process by automatically generating the necessary JSON structure. You just need to import our package and wrap your function with theopenai_functiondecorator. Here's how it works:importjsonfromopenai_functoolsimportopenai_function@openai_functiondefget_current_weather(location,unit="fahrenheit"):weather_info={"location":location,"temperature":"72","unit":unit,"forecast":["sunny","windy"],}returnjson.dumps(weather_info)defrun_conversation():messages=[{"role":"user","content":"What's the weather like in London?"}]functions=[get_current_weather.openai_metadata]As you can see, ouropenai_functiondecorator allows you to focus more on the logic of your function, while the tedious task of preparing function metadata is taken care of automatically.Using the OrchestratorThe orchestrator inopenai-functoolssimplifies the task of managing multiple registered functions and/or methods and automates the generation of OpenAI function descriptions. Below is a guide on how to use it.fromopenai_functoolsimportFunctionsOrchestratordefget_current_weather(location,unit="fahrenheit"):"""Get the current weather forecast in a given location"""# ... Implementation heredefget_weather_next_day(location,unit="fahrenheit"):"""Get the weather forecast for the next day in a given location"""# ... Implementation hereorchestrator=FunctionsOrchestrator()orchestrator.register_all([get_current_weather,get_weather_next_day])# ...Registering FunctionsFunctions can be registered using theregister_allorregistermethod as shown in the code snippet above.register_allaccepts a list of functions, whileregisteris used to register a single function.Registering InstancesAll methods of an instance can be registered using theregister_instances_allorregister_instancemethod and individual methods can be registered using regular function registration. An example of instance registration can be seen below.fromopenai_functoolsimportFunctionsOrchestratorclassWeatherService:defget_current_weather(location,unit="fahrenheit"):"""Get the current weather forecast in a given location"""# ... Implementation hereweatherService=WeatherService()orchestrator=FunctionsOrchestrator()# Register all methods of the classorchestrator.register_instance(weatherService)# Register individual methods of the classorchestrator.register_all([weatherService.get_current_weather])# ...Parallel function callingParallel function calling is a feature supported incertain models. Calling parallel functions is supported with the orchestrator. For this, useorchestrator.generate_tools_descriptions(). See theorchestrator parallel examplefor more details.Creating and Using Function DescriptionsFunction descriptions are automatically created based on the registered functions usingcreate_function_descriptionsmethod. These descriptions can then be passed to the OpenAIChatCompletion.createmethod.response=openai.ChatCompletion.create(model="gpt-3.5-turbo-0613",messages=[{"role":"user","content":"What's the weather like in Boston?"}],functions=orchestrator.create_function_descriptions(),function_call="auto",)Calling Functions Based on the OpenAI ResponseThecall_functionmethod is used to call a function based on the OpenAI response. It fetches the function call data from the response, finds the matching function from the registered functions, and calls it with the provided arguments.function_results=orchestrator.call_function(response)This process can be repeated for subsequent interactions with the OpenAI model, allowing easy use of multiple functions in a conversational context.response=openai.ChatCompletion.create(model="gpt-3.5-turbo-0613",messages=[{"role":"user","content":"What's the weather like in Boston tomorrow?"}],functions=orchestrator.create_function_descriptions(),function_call="auto",)function_results=orchestrator.call_function(response)Using docstrings to enhance metadataBy using docstrings in your functions, we are able to extract more information to fill in the descriptions of the function and its properties. This will automatically be added to the openai function metadata, and will help the model better understand the functions and parameters.Currently, only "reStructuredText" (reST) is supported by default, although this can be extended in the future (feel free to contribute!). Under the hood we make use ofdocstring parserto enable this.ExamplesSeveral examples can be found in theexamplesdirectory of this repository.TheMaintenance app usecaseis the recommended example to analyse, it shows the power of the library in a (spoofed) real-world setting.TheNaive approach exampleshows how to call openai-functions without use of the library.TheSimple exampleis similar to the naive approach, but makes use our decorator.TheOrchestrator exampleshows how one can use the orchestrator class.ContributingWe welcome contributions toopenai-functools! Please see ourcontributing guidefor more details.SupportFor support withopenai-functools, please open an issue on this GitHub repository. We will do our best to assist you.Licenseopenai-functoolsis licensed under the MIT license. See theLICENSEfile for details.