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

[Feature request] Tool support #19

Closed
sibbl opened this issue Apr 5, 2024 · 10 comments
Closed

[Feature request] Tool support #19

sibbl opened this issue Apr 5, 2024 · 10 comments

Comments

@sibbl
Copy link

sibbl commented Apr 5, 2024

Since Anthropic just released the public beta of tools yesterday, I'd be happy to see support in this library. See Anthropic docs: https://docs.anthropic.com/claude/docs/tool-use

I could imagine some similar C# support for functions like in the OpenAI-DotNet package where C# functions can be used for the request and which can also be invoked from the result, so that you hardly have to deal with fiddling around with JSON schema in C#.

What do you think?

@tghamm
Copy link
Owner

tghamm commented Apr 5, 2024

On it! 🙂

@nganju98
Copy link
Contributor

nganju98 commented Apr 5, 2024

Seconded. Thanks for making this great library!

@tghamm
Copy link
Owner

tghamm commented Apr 9, 2024

WIP, should have something that tests out pretty well in a few more days, thoughts?

[Function("This function returns the weather for a given location")]
public static async Task<string> GetWeather([FunctionParameter("Location of the weather", true)]string location)
{
    return "72 degrees and sunny";
}


[TestMethod]
public async Task TestBasicTool()
{
    var client = new AnthropicClient();
    var messages = new List<Message>
    {
        new Message()
        {
            Role = RoleType.User,
            Content = "What is the weather in San Francisco, CA?"
        }
    };
    var tools = Common.Tool.GetAllAvailableTools(includeDefaults: false, forceUpdate: true, clearCache: true);

    var parameters = new MessageParameters()
    {
        Messages = messages,
        MaxTokens = 2048,
        Model = AnthropicModels.Claude3Sonnet,
        Stream = false,
        Temperature = 1.0m,
    };
    var res = await client.Messages.GetClaudeMessageAsync(parameters, tools.ToList());
    
    messages.Add(res.Content.AsAssistantMessage());

    foreach (var toolCall in res.ToolCalls)
    {
        var response = await toolCall.InvokeAsync<string>();
        
        messages.Add(new Message(toolCall, response));
    }

    var finalResult = await client.Messages.GetClaudeMessageAsync(parameters);

    Assert.IsTrue(finalResult.FirstMessage.Text.Contains("72 degrees and sunny"));
}

@nganju98
Copy link
Contributor

nganju98 commented Apr 9, 2024

Looks good! Cool that you can pull it straight from real methods. Just wanted to make sure that I can also just generate Tool objects from scratch? I need to roll my own tools in some cases. For example:
Tool tool = new Tool("functionName", new List<Parameter> {new Parameter("paramDescription", true)});

Also can the tools collection just be a member of the MessageParameters? I think that's how others do it. Is there a reason it's separate from all the other parameters?

@tghamm
Copy link
Owner

tghamm commented Apr 9, 2024

Yeah, that'll be an option as well, something similar to:

var tools = new List<Tool>
{
    Tool.GetOrCreateTool(objectInstance, "TheNameOfTheMethodToCall"),
    Tool.FromFunc("a_custom_name_for_your_function", ()=> { /* Some logic to run */ })
};

This was mostly my first crack at wiring up the internals to abstract away all the JSON manipulation.

@tghamm
Copy link
Owner

tghamm commented Apr 11, 2024

Tool support has been added, along with some other changes to keep pace with Anthropic. Hope it helps, and feel free to raise any issues - did the best I could - wanted to get something out there relatively quick for everyone.

@tghamm tghamm closed this as completed Apr 11, 2024
@sibbl
Copy link
Author

sibbl commented Apr 11, 2024

Awesome, thanks for the quick addition!

@nganju98
Copy link
Contributor

Amazing, will try it out today!

@sibbl
Copy link
Author

sibbl commented Apr 12, 2024

Some thoughts after giving it a try:

First, according to Anthropic's docs, they support JSON schema for the input_schema property:

Tools are specified in the tools top-level parameter of the API request. Each tool definition includes:

  • name: The name of the tool. Must match the regex ^[a-zA-Z0-9_-]{1,64}$.
  • description: A detailed plaintext description of what the tool does, when it should be used, and how it behaves.
  • input_schema: A JSON Schema object defining the expected parameters for the tool.

You created some classes yourself which is a very simple subset of the JSON schema. Was this an active decision not to go the same route as the OpenAI package I linked above, where they just went with JsonNode and its full flexibility and JSON Schema support?

Secondly, this also lead to the bug I've found and tracked in issue #24

Finally, ToolContentResult seems to be missing the is_error field as described in Anthropic's docs:

And here's an example of returning an error result:

{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
      "content": "ConnectionError: the weather service API is not available (HTTP 500)",
      "is_error": true
    }
  ]
}

I hope it's okay to send this feedback here and not directly open a new issue for each. I only decided to open a separate one for the bug in order to be able to track it.

@tghamm
Copy link
Owner

tghamm commented Apr 12, 2024

@sibbl Thanks for the feedback, it wasn't active (permanent) decision, it was just a function of the scale/time of getting something out to support an 80/20 scenario. Your feedback is super helpful, and I'll be actively working on a 3.1 milestone so that the library can better support the full JSON schema.

@tghamm tghamm mentioned this issue Apr 17, 2024
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

No branches or pull requests

3 participants