Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic support for functions #60

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

carlo-
Copy link

@carlo- carlo- commented Jun 18, 2023

Hi all! I've started working on adding support for functions. I have a rather rough implementation ready, so I wanted to check in here. Function calls from the models are inherently "unsafe", so this clashes a bit with the strict type safety of Swift; I think making this work in a neat way is an interesting challenge. What are your thoughts?

Here's how you'd define a function with my implementation (this example function can be used to search a database of recipes):

struct FindRecipeFunction: Chat.Function {
    
    struct Call: Chat.FunctionCallWithArguments {
        var name: String
        var arguments: Arguments
        
        struct Arguments: Codable {
            let query: String
        }
    }
    
    struct Parameters: Encodable {
        let type = "object"
        let properties = Props()
        let required = ["query"]
        
        struct Props: Encodable {
            let query = Query()
            
            struct Query: Encodable {
                let type = "string"
                let description = "A human readable query to use when searching for a recipe."
            }
        }
    }
    
    let name: String = "findRecipe"
    
    let description: String? = "The `findRecipe` API can be used to search through a database of recipes."
    
    let parameters: Parameters? = Parameters()
}

You would then send a chat request as usual, passing in the functions and the function "mode" (called "function_call" in the docs):

let chat = try await client.chats.create(
    model: Model.GPT4.gpt40613,
    messages: ...,
    functions: [FindRecipeFunction()],
    functionMode: .auto
)
let message = chat.choices[0].message

And then try to extract any function calls with type safety:

if case let .assistantWithCall(_, call) = message,
    let call = try? call.structured(as: FindRecipeFunction.Call.self) {
    
    let recipeQuery = call.arguments.query
    // ...
}

@ronaldmannak
Copy link
Collaborator

Could the type property in Parameters be an enum instead of string? I'm also wondering if you could make it less verbose by using generics for arguments and parameters, though I'm not sure how you would add the description in that case.

Also, what's the difference between assistantWithCall(content: String?, call: UnstructuredFunctionCall) and function I see in a switch statement?

@carlo-
Copy link
Author

carlo- commented Jul 25, 2023

Unfortunately I haven't had any time to come back to this, and looks like I won't be able to in the near future either, but feel free to edit any part of this PR 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants