1

I'm trying to follow Microsoft's example for calling a native plugin, albeit in a LinqPad script.

The Pluging I've added to my script is identical to the example here.

When I call it "directly" using the following code, it works just fine:

double resultDirect = await kernel.InvokeAsync<double>(
    nameof(Plugins.MathPlugin), nameof(Plugins.MathPlugin.Sqrt),
    new()
    {
        {"number1", 12 },
    })!;

resultDirect.Dump();

However...when following the example Allow the AI to automatically call your function then the following line throws an exception:

await foreach (var content in result)

I get a Microsoft.SemanticKernel.HttpOperatonException thrown:

Unrecognized request arguments supplied: tool_choice, tools Status: 400 (model_error)

Content:
{
  "error": {
    "message": "Unrecognized request arguments supplied: tool_choice, tools",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  }
}

I'm consuming the following NuGet packages:

  • Microsft.SemanticKernel 1.1.0

  • Microsft.SemanticKernel.Plugins.Core(pre) 1.1.0-alpha

  • Microsft.SemanticKernel.Planners.Handlebars(pre) 1.1.0-preview

1
  • what model are you using? This error was returned from your AI service. Most likely the model you were using does not support Function_calling or Tools Commented Jan 19, 2024 at 22:46

1 Answer 1

1

The "tools" and "tool_choice" are relative new addition to OpenAI api which might not be avaliable in the model you were using. Try a later version model and it should work.

To confirm, I tested with the exact same version of NuGet packages and followed the same code example. Only difference was that I was using Azure OpenAI GPT-3.5-turbo-1106 and GPT-4-1106-Preview as AI service. Both worked well.

Here is the Polyglot notebook code:

#r "nuget: Microsoft.SemanticKernel, 1.1.0"
#r "nuget: Microsoft.SemanticKernel.Core, 1.1.0-alpha"
#r "nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.1.0-preview"

using System.ComponentModel;
using Microsoft.SemanticKernel;

public class MathPlugin
{
    [KernelFunction, Description("Take the square root of a number")]
    public static double Sqrt(
        [Description("The number to take a square root of")] double number1
    )
    {
        return Math.Sqrt(number1);
    }

    [KernelFunction, Description("Add two numbers")]
    public static double Add(
        [Description("The first number to add")] double number1,
        [Description("The second number to add")] double number2
    )
    {
        return number1 + number2;
    }

    [KernelFunction, Description("Subtract two numbers")]
    public static double Subtract(
        [Description("The first number to subtract from")] double number1,
        [Description("The second number to subtract away")] double number2
    )
    {
        return number1 - number2;
    }

    [KernelFunction, Description("Multiply two numbers. When increasing by a percentage, don't forget to add 1 to the percentage.")]
    public static double Multiply(
        [Description("The first number to multiply")] double number1,
        [Description("The second number to multiply")] double number2
    )
    {
        return number1 * number2;
    }

    [KernelFunction, Description("Divide two numbers")]
    public static double Divide(
        [Description("The first number to divide from")] double number1,
        [Description("The second number to divide by")] double number2
    )
    {
        return number1 / number2;
    }

    [KernelFunction, Description("Raise a number to a power")]
    public static double Power(
        [Description("The number to raise")] double number1,
        [Description("The power to raise the number to")] double number2
    )
    {
        return Math.Pow(number1, number2);
    }

    [KernelFunction, Description("Take the log of a number")]
    public static double Log(
        [Description("The number to take the log of")] double number1,
        [Description("The base of the log")] double number2
    )
    {
        return Math.Log(number1, number2);
    }

    [KernelFunction, Description("Round a number to the target number of decimal places")]
    public static double Round(
        [Description("The number to round")] double number1,
        [Description("The number of decimal places to round to")] double number2
    )
    {
        return Math.Round(number1, (int)number2);
    }

    [KernelFunction, Description("Take the absolute value of a number")]
    public static double Abs(
        [Description("The number to take the absolute value of")] double number1
    )
    {
        return Math.Abs(number1);
    }

    [KernelFunction, Description("Take the floor of a number")]
    public static double Floor(
        [Description("The number to take the floor of")] double number1
    )
    {
        return Math.Floor(number1);
    }

    [KernelFunction, Description("Take the ceiling of a number")]
    public static double Ceiling(
        [Description("The number to take the ceiling of")] double number1
    )
    {
        return Math.Ceiling(number1);
    }

    [KernelFunction, Description("Take the sine of a number")]
    public static double Sin(
        [Description("The number to take the sine of")] double number1
    )
    {
        return Math.Sin(number1);
    }

    [KernelFunction, Description("Take the cosine of a number")]
    public static double Cos(
        [Description("The number to take the cosine of")] double number1
    )
    {
        return Math.Cos(number1);
    }

    [KernelFunction, Description("Take the tangent of a number")]
    public static double Tan(
        [Description("The number to take the tangent of")] double number1
    )
    {
        return Math.Tan(number1);
    }

    [KernelFunction, Description("Take the arcsine of a number")]
    public static double Asin(
        [Description("The number to take the arcsine of")] double number1
    )
    {
        return Math.Asin(number1);
    }

    [KernelFunction, Description("Take the arccosine of a number")]
    public static double Acos(
        [Description("The number to take the arccosine of")] double number1
    )
    {
        return Math.Acos(number1);
    }

    [KernelFunction, Description("Take the arctangent of a number")]
    public static double Atan(
        [Description("The number to take the arctangent of")] double number1
    )
    {
        return Math.Atan(number1);
    }
}

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

// Create chat history
ChatHistory history = [];
// Create kernel
var builder = Kernel.CreateBuilder();
// Add a text or chat completion service using either:
builder.Services.AddAzureOpenAIChatCompletion(
    "gpt-35-turbo",                   // Azure OpenAI *Deployment Name*
    "https://mydeplyment.openai.azure.com",    // Azure OpenAI *Endpoint*
    "<Your-Azure-OpenAI-API-Key>",          // Azure OpenAI *Key*
    serviceId: "Azure_gpt_4"  
);
// builder.Services.AddAzureOpenAITextGeneration()
// builder.Services.AddOpenAIChatCompletion()
// builder.Services.AddOpenAITextGeneration()

builder.Plugins.AddFromType<MathPlugin>();
var kernel = builder.Build();

IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

// Start the conversation
// while (true)
// {
    // Get user input
    // Console.Write("User > ");
    // history.AddUserMessage(Console.ReadLine()!);
    history.AddUserMessage("Take the square root of 12");
    // Enable auto function calling
    OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
    {
        ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
    };

    // Get the response from the AI
    var result = chatCompletionService.GetStreamingChatMessageContentsAsync(
        history,
        executionSettings: openAIPromptExecutionSettings,
        kernel: kernel);

    // Stream the results
    string fullMessage = "";
    var first = true;
    await foreach (var content in result)
    {
        if (content.Role.HasValue && first)
        {
            Console.Write("Assistant > ");
            first = false;
        }
        Console.Write(content.Content);
        fullMessage += content.Content;
    }
// }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.