OkGoDoIt / OpenAI-API-dotnet

An unofficial C#/.NET SDK for accessing the OpenAI GPT-3 API
https://www.nuget.org/packages/OpenAI/
Other
1.84k stars 427 forks source link

Add Function calling #146

Open techjb opened 1 year ago

techjb commented 1 year ago

OpenAI has recently added Functions calling. Would be amazing to have it implemented on this library.

hansjm10 commented 1 year ago

I started looking into this and had some quick success with setting it up with NJsonSchema. Not sure if Newtonsoft provides anything similar, but I've got a working fork I scrambled together now if you want to test it out.

henkin commented 1 year ago

I was working towards doing something like this manually ("You can call me as you would a SQL API and I will respond with the data you need to answer the query".) It would be really cool is to actually take it a step further.. and have it call back into an actual function. ie:

decimal GetTodaysTemperatureInCelcius(string zipCode) { return 23.4; }
var results = await api.Chat.CreateChatCompletionAsync(new ChatRequest()
      {
          Model = Model.ChatGPTTurbo0613,
          Temperature = 0.2,
          MaxTokens = 2000,
          Messages = Messages
      },
      GetTodaysTemperatureInCelcius
);

Then, if ChatGPT comes back with a function call, CreateChatCompletionAsync could use DynamicInvoke on the function(s) you pass in - passing params to it from ChatGPT.

Then it could then transparently call ChatGPT with the data returned from calling GetTodaysTemperatureInCelcius, and return the results of that response as results.

Too crazy? I honestly think that this particular feature (being able to handle functions in a convenient and robust way) is going to make/break the libraries/frameworks that interact with ChatGPT.

techjb commented 1 year ago

Yes, you can share the fork, I will try to contribute.

chrish-slingshot commented 1 year ago

Also interested in getting this working. Feel free to share and I'll help out where I can.

bluewilliams commented 1 year ago

following and will contribute as needed

hansjm10 commented 1 year ago

Do we want to implement a basic json schema using JTokens or use an outside library? I don't think the OpenAI functions aren't structured incredibly complex based off of their examples.

https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb

chrish-slingshot commented 1 year ago

@hansjm10 You were missing a line in the Chat Request constructor - you need to add:

this.Functions = basedOn.Functions;

on line 151.

I'm constructing my functions like this:

var functions = new List<Functions>();
                functions.Add(new Functions
                {
                    Name = "generate_image",
                    Description = "Generate an image using Stable Diffusion",
                    Parameters = JObject.Parse(@"{
    ""type"": ""object"",
    ""properties"": {
        ""prompt"": {
            ""type"": ""string"",
            ""description"": ""The text prompt to use which describes the contents of the image""
        },
        ""style"": {
            ""type"": ""string"",
            ""enum"": [ ""anime"", ""mixed"", ""realistic"" ]
        }
    },
    ""required"": [ ""prompt"", ""style"" ]
}")
                });

                var conversation = Client.Chat.CreateConversation(new ChatRequest { Model = "gpt-3.5-turbo-16k" });
                conversation.RequestParameters.Functions = functions;
hansjm10 commented 1 year ago

@chrish-slingshot Great got it working now using CreateConversation and test is passing.

I'd like to get this to work using CreateChatCompletionAsync but still getting weird null reference errors. I think it has to do with how the ChatRequest is getting deserialized, unfortunately stepping through it the response looks totally fine and just errors out after CreateChatCompletionAsync is awaited.

techjb commented 1 year ago

@hansjm10 looks pretty good