Custom functions allow you to extend the capabilities of your Assistant by defining specific actions that the Assistant can perform. Here's how to create custom functions using the FunctionCall class. You can create a FunctionCall instance by specifying the function's name, description, and an optional delegate that will execute the function. There are two methods for creating a FunctionCall instance:
1. Without Parameters Schema
If you need a FunctionCall that returns response in Text (string) format, use the following method to create a FunctionCall instance with the specified name, description, and delegate.
// Creating functionCall without parameters schemavar functionCall =FunctionCall.Create("MyFunction","This is a sample function",newMyFunctionDelegate());
2. With Parameters Schema
To create a FunctionCall that returns a Run with custom object argument(T), define your custom argument class with properties with JsonSchemaAttribute. Only string and enum types are supported.
usingGlitch9.IO.Json.Schema;// Define your custom return class with JsonSchemaAttributes.publicclassGetCurrentTemperatureArgument{ // Example string property: Define properties according to the expected API response structure. [JsonSchema("location", Description ="The city and state, e.g., San Francisco, CA.", required:true)]publicstring Location { get; set; } // Example enum property: If your response includes fields that can be categorized into enums, // define an enum and use it as the type for such properties. [JsonSchema("unit", Description = "The temperature unit to use. Infer this from the user's location.", required: false)]
publicTemperatureUnit Unit { get; set; } // Properties without JsonSchemaAttribute won't be included in Parameters Schema. [JsonProperty("temperature")]publicstring Temperature { get; set; }}// Example enum to represent a category or type of response.// "enum": ["Celsius", "Fahrenheit"],publicenumTemperatureUnit{ Celsius, Fahrenheit}
Then use the following method create a FunctionCall instance with the specified name, description, and delegate. The parameters for the function are generated based on the specified type T.
// Creating functionCall with parameters schemavar functionCall = FunctionCall.Create<GetCurrentTemperatureArgument>("get_current_temperature", "Get the current temperature for a specific location.", new MyFunctionDelegate());
3. Extending the Function Delegate
A function delegate is a class that extends the FunctionDelegate class. This delegate will delegate submit tool outputs to run when OpenAI AssistantsAPI returns a Run with RunStatus.RequiresAction.
usingCysharp.Threading.Tasks;usingGlitch9.AIDevelopmentKit;publicclassGetCurrentTemperatureDelegate<GetCurrentTemperatureArgument> :FunctionDelegate{ // Example dummy function hard coded to return the same weather // In production, this could be your backend API or an external API public override async UniTask<GetCurrentTemperatureArgument> ExecuteInternal(GetCurrentTemperatureArgument argument)
{ if (argument.Location.ToLowerCase().Contains("tokyo")) {argument.Temperature="10";argument.Unit=TemperatureUnit.Celsius;return argument; }elseif (argument.Location.ToLowerCase().Contains("san francisco")) {argument.Temperature="72";argument.Unit=TemperatureUnit.Fahrenheit;return argument; }elseif (argument.Location.ToLowerCase().Contains("paris")) {argument.Temperature="22";argument.Unit=TemperatureUnit.Fahrenheit;return argument; } else { argument.Temperature ="unknown";return argument; } }}
If no function delegate is provided to a FunctionCall and the AssistantsAPI returns a Run with RunStatus.RequiresAction, AssistantsAPIv2 will wait until required outputs are submitted with AssistantsAPIv2.SubmitToolOutput.