Skip to content

.Net: Adds support for Tool calls to the Amazon Bedrock connector #11922

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

glorious-beard
Copy link
Contributor

@glorious-beard glorious-beard commented May 6, 2025

Motivation and Context

  1. Why is this change required?
    This change enables Semantic Kernel uses access to the tool call APIs in Amazon Bedrock, allowing models like Claude to use tools.

  2. What problem does it solve?
    It fixes the lack of tool calling in Amazon Bedrock and brings it closer to parity with OpenAI connectors.

  3. What scenario does it contribute to?
    Tool calls

  4. If it fixes an open issue, please link to the issue here.

Description

This piggy backs on the tool metadata generators in FunctionCallingUtilities and PlanningUtilities to allow annotated kernel functions to be used as tools in Amazon Bedrock.

Contribution Checklist

Copy link
Contributor Author

@glorious-beard glorious-beard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this PR is on top of #11919. When/if that PR get merged, this PR should be rebased.

@glorious-beard
Copy link
Contributor Author

@RogerBarreto - didn't realize this work was already underway (this is just a PR of code already in use from my own fork).
Happy to abandon if this isn't needed.

@subhaviv
Copy link

subhaviv commented May 8, 2025

Hi there, Any ETA for these changes to be merged? Thanks!

1 similar comment
@Debanita29
Copy link

Hi there, Any ETA for these changes to be merged? Thanks!

@padate
Copy link

padate commented May 9, 2025

Looking to leverage the changes , any ETA for merging ?

@markwallace-microsoft markwallace-microsoft added .NET Issue or Pull requests regarding .NET code kernel Issues or pull requests impacting the core kernel kernel.core labels May 9, 2025
@github-actions github-actions bot changed the title Adds support for Tool calls to the Amazon Bedrock connector .Net: Adds support for Tool calls to the Amazon Bedrock connector May 9, 2025
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't something that you modified in this MR but should this line be leveraging your new convert method?
https://github.com/microsoft/semantic-kernel/pull/11922/files#diff-3e02636a8860c28c1525778de8b3d59a03a7f23b0c2a2fc06ae8c343334fd1e3R198

i.e. Instead of this:

    private static ChatMessageContentItemCollection CreateChatMessageContentItemCollection(List<ContentBlock> contentBlocks)
    {
        var itemCollection = new ChatMessageContentItemCollection();
        foreach (var contentBlock in contentBlocks)
        {
            itemCollection.Add(new TextContent(contentBlock.Text));
        }
        return itemCollection;
    }

To this:

    private static ChatMessageContentItemCollection CreateChatMessageContentItemCollection(List<ContentBlock> contentBlocks)
    {
        var itemCollection = new ChatMessageContentItemCollection();
        foreach (var contentBlock in contentBlocks)
        {
            itemCollection.Add(BedrockClientUtilities.ConvertContentBlock(contentBlock));
        }

        return itemCollection;
    }

yield return content;
break;

case ContentBlockStopEvent e:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is dependent on the model but with Claude 3.7 I am seeing multiple "blocks" coming back from the request stream:
image

I believe this is the similar to how Claude 3.7 returns the message content in 2 items in the non-streaming request?
image

// If we are calling a tool, we need to process the tool call

// Step 1. Create a function call message
var inputJson = string.Concat(toolContents.Select(t => t.Arguments ?? string.Empty));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something doesn't feel right here. It could be because of the model or some change on the AWS API but my function call response doesn't have arguments and has the tool name, id, etc already populated:
image

This seems like we would just need to convert it to a ChatMessageContent.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this would be more inline with what works for my model:

            // Step 1. Create a function call message
            var inputJson = string.Concat(toolContents.Select(t => t.Arguments ?? string.Empty));
            var toolInput = string.IsNullOrEmpty(inputJson) ? new Document()
                : JsonSerializer.Deserialize<Document>(inputJson);

            var toolContent = toolContents.FirstOrDefault();
            var toolUseBlock = new ToolUseBlock()
            {
                Name = toolName,
                ToolUseId = toolId,
                Input = toolInput,
            };

            var functionCallContent = (FunctionCallContent)BedrockClientUtilities.ConvertContentBlock(new ContentBlock
            {
                ToolUse = toolUseBlock,
            });
            var toolMessage = new ChatMessageContent(AuthorRole.Tool, [functionCallContent]);

            var originalLength = workingHistory.Count;

            // Step 2. Process the function call
            // ...

@crickman crickman requested a review from TaoChenOSU June 3, 2025 16:01
@crickman crickman moved this to Sprint: In Review in Semantic Kernel Jun 3, 2025
@RogerBarreto
Copy link
Member

RogerBarreto commented Jun 11, 2025

@glorious-beard Thanks for the amazing contribution.

As far as I know, we do have already support for IChatClient from Amazon Bedrock extensions package, in theory this client should allow tool calling to work out of the box with Semantic Kernel.

i.e.:

var kernel = Kernel.CreateBuilder().AddBedrockChatClient("your-model").Build()

// Same implementation as before...

@MustafaJamal
Copy link

@glorious-beard Thanks for the amazing contribution.

As far as I know, we do have already support for IChatClient from Amazon Bedrock extensions package, in theory this client should allow tool calling to work out of the box with Semantic Kernel.

i.e.:

var kernel = Kernel.CreateBuilder().AddBedrockChatClient("your-model").Build()

// Same implementation as before...

Hi,

Will it not work if using:

var builder = Kernel.CreateBuilder() .AddBedrockChatCompletionService(modelId, bedrockClient);

I am currently using:

Microsoft.SemanticKernel.Connectors.Amazon v1.57.0-alpha
Microsoft.SemanticKernel v1.57.0

Waiting for response.

Thanks!
Mustafa

@davidames
Copy link

Mustafa

Hi @MustafaJamal - you def need to use the M.E.AI connector instead of the old connector (above). Using M.E.AI I can use Vision Images, tool calling, etc, etc.

Here is a really basic (and verbose!) example of creating a Kernel with a Chat Completion Service that shows the steps

[Experimental("SKEXP0070")]
    private Kernel CreateBedrockKernel()
    {
        var bedRockConfig = GetService<AwsBedRockConfig>();
        var builder = Kernel.CreateBuilder();
        var bedrockRuntimeClient = new AmazonBedrockRuntimeClient(new BasicAWSCredentials(bedRockConfig.AwsAccessKeyId, bedRockConfig.AwsSecretAccessKey), RegionEndpoint.GetBySystemName(bedRockConfig.Region));
        var chatClient = bedrockRuntimeClient.AsIChatClient();
        var chatCompletionService = chatClient.AsChatCompletionService();
        
        builder.Services.AddSingleton(chatCompletionService);
        var kernel = builder.Build();

        return kernel;
    }

@MustafaJamal
Copy link

MustafaJamal commented Jun 17, 2025

Mustafa

Hi @MustafaJamal - you def need to use the M.E.AI connector instead of the old connector (above). Using M.E.AI I can use Vision Images, tool calling, etc, etc.

Here is a really basic (and verbose!) example of creating a Kernel with a Chat Completion Service that shows the steps

[Experimental("SKEXP0070")]
    private Kernel CreateBedrockKernel()
    {
        var bedRockConfig = GetService<AwsBedRockConfig>();
        var builder = Kernel.CreateBuilder();
        var bedrockRuntimeClient = new AmazonBedrockRuntimeClient(new BasicAWSCredentials(bedRockConfig.AwsAccessKeyId, bedRockConfig.AwsSecretAccessKey), RegionEndpoint.GetBySystemName(bedRockConfig.Region));
        var chatClient = bedrockRuntimeClient.AsIChatClient();
        var chatCompletionService = chatClient.AsChatCompletionService();
        
        builder.Services.AddSingleton(chatCompletionService);
        var kernel = builder.Build();

        return kernel;
    }

Hi @davidames ,

Thanks for response, I tried it too, but 2 types of exception are appearing now:


  1. The model returned the following errors: Malformed input request: #: extraneous key [max_tokens_to_sample] is not permitted, please reformat your input and try again.

Call stack:

at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionStream(IRequestContext requestContext, IWebResponseData httpErrorResponse, HttpErrorResponseException exception, Stream responseStream)
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.d__2.MoveNext()
at Amazon.Runtime.Internal.ExceptionHandler1.<HandleAsync>d__6.MoveNext() at Amazon.Runtime.Internal.ErrorHandler.<ProcessExceptionAsync>d__8.MoveNext() at Amazon.Runtime.Internal.ErrorHandler.<InvokeAsync>d__51.MoveNext()
at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() at Amazon.Runtime.Internal.Signer.<InvokeAsync>d__11.MoveNext()
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.d__21.MoveNext() at Amazon.Runtime.Internal.EndpointDiscoveryHandler.<InvokeAsync>d__21.MoveNext()
at Amazon.Runtime.Internal.RetryHandler.d__101.MoveNext() at Amazon.Runtime.Internal.RetryHandler.<InvokeAsync>d__101.MoveNext()
at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() at Amazon.Runtime.Internal.BaseAuthResolverHandler.<InvokeAsync>d__21.MoveNext()
at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__51.MoveNext()
at Amazon.Runtime.Internal.MetricsHandler.d__1`1.MoveNext()
at Amazon.BedrockRuntime.BedrockChatClient.d__6.MoveNext()
at Microsoft.SemanticKernel.ChatCompletion.ChatClientChatCompletionService.d__5.MoveNext()

  1. Amazon.BedrockRuntime.Model.ValidationException: 'The json schema definition at toolConfig.tools.28.toolSpec.inputSchema is invalid. Fix the following errors and try again: $.properties: null found, object expected'

Call stack:

at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionStream(IRequestContext requestContext, IWebResponseData httpErrorResponse, HttpErrorResponseException exception, Stream responseStream)
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.d__2.MoveNext()
at Amazon.Runtime.Internal.ExceptionHandler1.<HandleAsync>d__6.MoveNext() at Amazon.Runtime.Internal.ErrorHandler.<ProcessExceptionAsync>d__8.MoveNext() at Amazon.Runtime.Internal.ErrorHandler.<InvokeAsync>d__51.MoveNext()
at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() at Amazon.Runtime.Internal.Signer.<InvokeAsync>d__11.MoveNext()
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.d__21.MoveNext() at Amazon.Runtime.Internal.EndpointDiscoveryHandler.<InvokeAsync>d__21.MoveNext()
at Amazon.Runtime.Internal.RetryHandler.d__101.MoveNext() at Amazon.Runtime.Internal.RetryHandler.<InvokeAsync>d__101.MoveNext()
at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() at Amazon.Runtime.Internal.BaseAuthResolverHandler.<InvokeAsync>d__21.MoveNext()
at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__51.MoveNext()
at Amazon.Runtime.Internal.MetricsHandler.d__1`1.MoveNext()
at Amazon.BedrockRuntime.BedrockChatClient.d__7.MoveNext()
at Amazon.BedrockRuntime.BedrockChatClient.d__7.System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult(Int16 token)
at Microsoft.SemanticKernel.ChatCompletion.ChatClientChatCompletionService.d__6.MoveNext()
at Microsoft.SemanticKernel.ChatCompletion.ChatClientChatCompletionService.d__6.MoveNext()
at Microsoft.SemanticKernel.ChatCompletion.ChatClientChatCompletionService.d__6.System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult(Int16 token)
at MR.CoPilot.Server.Middlewares.SemanticKernel.SKChatRepository.d__27.MoveNext() in F:\del\Repos\Codebase\Middlewares\SemanticKernel\SKChatRepository.cs:line 443


Note that I tried with or without MaxTokensToSample in AmazonClaudeExecutionSettings. Second, I am using KernelFunction(using attributes) as plugins and none of them is without parameters and those functions are working fine with Azure OpenAI and OpenAI.

Waiting for response.

Thanks,
Mustafa

@davidames
Copy link

davidames commented Jun 17, 2025

Hi @MustafaJamal - function calling is working well for me using M.E.AI - but there was a lot of fiddling around to get it to work, especially around nuget packages - the versions absolutely matter!

My versions are
Microsoft.SemanticKernel 1.56
AWSSdk.BedrockRuntime 4.0.0.7
AWSSdk.Extensions.Bedrock.MEAI 4.0.1.1 <= - This was really importing, SK implicitly references and old version
Microsoft.Extensions.AI 9.6.0

Here is my working spike code - it does manual function calling (as our main solution does too) - our prod code uses [KernelFunction] and that works too!

I hope it helps!


[Fact]
     [Experimental("SKEXP0001")]
     public async Task RunStreamingChatCompletionApiWithManualFunctionCallingAsync()
    {
        Kernel kernel = CreateBedrockKernel();
        var bedrockConfig = GetService<AwsBedRockConfig>();
        kernel.ImportPluginFromFunctions("HelperFunctions",
        [
            kernel.CreateFunctionFromMethod(() => new List<string> { "Squirrel Steals Show", "Dog Wins Lottery" }, "GetLatestNewsTitles", "Retrieves latest news titles."),
        ]);

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


        OpenAIPromptExecutionSettings settings = new()
        {
            FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false),
            ModelId = bedrockConfig.ClaudeModelId,
            MaxTokens = 1000
        };

        
        ChatHistory chatHistory = [];
        chatHistory.AddUserMessage("Get latest news titles.");

        while (true)
        {
            AuthorRole? authorRole = null;
            var fccBuilder = new FunctionCallContentBuilder();

            try
            {
           
                await foreach (var streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync(
                                   chatHistory, settings, kernel))
                {
                    if (streamingContent.Content is not null)
                    {
                        Logger.Information(streamingContent.Content);
                    
                    }

                    authorRole ??= streamingContent.Role;
                    fccBuilder.Append(streamingContent);
                }

            }
            catch (Exception e)
            {
                Logger.Error(e, "Error during streaming chat completion");
               
            }
            
            var functionCalls = fccBuilder.Build();
            if (!functionCalls.Any())
            {
                break;
            }

            var fcContent = new ChatMessageContent(role: authorRole ?? default, content: null);
           
            foreach (var functionCall in functionCalls)
            {
                fcContent.Items.Add(functionCall);

                var functionResult = await functionCall.InvokeAsync(kernel);

                chatHistory.Add(functionResult.ToChatMessage());
            }
        }
    }

@MustafaJamal
Copy link

MustafaJamal commented Jun 18, 2025

Hi @MustafaJamal - function calling is working well for me using M.E.AI - but there was a lot of fiddling around to get it to work, especially around nuget packages - the versions absolutely matter!

My versions are Microsoft.SemanticKernel 1.56 AWSSdk.BedrockRuntime 4.0.0.7 AWSSdk.Extensions.Bedrock.MEAI 4.0.1.1 <= - This was really importing, SK implicitly references and old version Microsoft.Extensions.AI 9.6.0

Here is my working spike code - it does manual function calling (as our main solution does too) - our prod code uses [KernelFunction] and that works too!

I hope it helps!


[Fact]
     [Experimental("SKEXP0001")]
     public async Task RunStreamingChatCompletionApiWithManualFunctionCallingAsync()
    {
        Kernel kernel = CreateBedrockKernel();
        var bedrockConfig = GetService<AwsBedRockConfig>();
        kernel.ImportPluginFromFunctions("HelperFunctions",
        [
            kernel.CreateFunctionFromMethod(() => new List<string> { "Squirrel Steals Show", "Dog Wins Lottery" }, "GetLatestNewsTitles", "Retrieves latest news titles."),
        ]);

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


        OpenAIPromptExecutionSettings settings = new()
        {
            FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false),
            ModelId = bedrockConfig.ClaudeModelId,
            MaxTokens = 1000
        };

        
        ChatHistory chatHistory = [];
        chatHistory.AddUserMessage("Get latest news titles.");

        while (true)
        {
            AuthorRole? authorRole = null;
            var fccBuilder = new FunctionCallContentBuilder();

            try
            {
           
                await foreach (var streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync(
                                   chatHistory, settings, kernel))
                {
                    if (streamingContent.Content is not null)
                    {
                        Logger.Information(streamingContent.Content);
                    
                    }

                    authorRole ??= streamingContent.Role;
                    fccBuilder.Append(streamingContent);
                }

            }
            catch (Exception e)
            {
                Logger.Error(e, "Error during streaming chat completion");
               
            }
            
            var functionCalls = fccBuilder.Build();
            if (!functionCalls.Any())
            {
                break;
            }

            var fcContent = new ChatMessageContent(role: authorRole ?? default, content: null);
           
            foreach (var functionCall in functionCalls)
            {
                fcContent.Items.Add(functionCall);

                var functionResult = await functionCall.InvokeAsync(kernel);

                chatHistory.Add(functionResult.ToChatMessage());
            }
        }
    }

Hi @davidames,

Many thanks for response. I found that I was using AmazonClaudeExecutionSettings instead of AnthropicPromptExecutionSettings, so it worked for me now and now no exceptions are appearing. But now no functions are being called although assistant has function information here are details:

promptExecutionSettings = new AnthropicPromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(), Temperature = 0.5, ModelId = modelId // modelId = us.anthropic.claude-3-5-sonnet-20240620-v1:0 };

When I asked assistant:

what functions or tool call are available

It answered me right:

SKWorkItemSkill_CreateWorkItem
SKWorkItemSkill_UpdateWorkItem
SKWorkItemSkill_PatchWorkItem
SKWorkItemSkill_DeleteWorkItem
SKWorkItemSkill_LinkWorkItems
SKWorkItemSkill_AddCommentToWorkItem
SKWorkItemSkill_DeleteWorkItemLink
SKWorkItemSkill_GetCurrentWorkItem
SKWorkItemSkill_GetCurrentWorkItems
SKQuerySkill_CreateQuery
SKQuerySkill_UpdateQuery
SKQuerySkill_DeleteQuery
SKQuerySkill_GetQueryType
SKQuerySkill_GetCurrentQuery
SKDataSkill_GetWorkItem
SKDataSkill_GetLinkedWorkItems
SKDataSkill_GetWorkItems
SKDataSkill_GetWorkItemsByIds
SKDataSkill_GetWorkItemsByType
SKDataSkill_GetWorkItemsByQueryId
SKDataSkill_GetWorkItemsByQueryString
SKDataSkill_GetWorkItemTypes
SKDataSkill_GetWorkItemTypeDefinition
SKDataSkill_GetRelationTypes
SKDataSkill_SearchWorkItems
SKDataSkill_GetUsers
SKDataSkill_GetProjects
SKDataSkill_GetQueries
SKDataSkill_GetBacklogWorkItems
SKDataSkill_GetCurrentSprint
SKDataSkill_GenerateMermaidDiagram
SKDataSkill_ConvertMermaidToImage
SKDataSkill_ConvertHtmlToImage
SKDataSkill_GetDownloadLinkForFileContent
SKPythonSkill_ListPythonLibraries
SKPythonSkill_InstallPythonLibrary
SKPythonSkill_RunPythonCode

Also when I asked that:

Create Epic work item for User Management, generate title and description by yourself

it answered this(although it waited for 2-3 seconds after sending message) but did not do any function call:

**
Certainly, I'll create an Epic work item for User Management with a generated title and description right away.

Thinking: Generating title and description for User Management Epic

Creating: Preparing to create new Epic work item

Now, I'll use the SKWorkItemSkill_CreateWorkItem function to create this Epic:
**

My Nuget API versions as same as yours.

Also I checked StreamingChatMessageContent does receive function call related data, but function doesn't call:

{"Content":null,"Items":[{"CallId":"tooluse_bTgNyH1HQauYzRHFj5D5Wg","Name":"SKWorkItemSkill_CreateWorkItem","Arguments":"{\r\n  \"workItemType\": \"Epic\",\r\n  \"title\": \"Implement Comprehensive User Management System\",\r\n  \"description\": \"\\u003Cdiv\\u003E\\n\\u003Ch2\\u003EEpic: Implement Comprehensive User Management System\\u003C/h2\\u003E\\n\\n\\u003Cp\\u003EThis epic encompasses the development and implementation of a robust user management system to enhance our application\\u0027s security, user experience, and administrative capabilities.\\u003C/p\\u003E\\n\\n\\u003Ch3\\u003EObjectives:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EStreamline user registration and onboarding processes\\u003C/li\\u003E\\n    \\u003Cli\\u003EEnhance authentication and authorization mechanisms\\u003C/li\\u003E\\n    \\u003Cli\\u003EImplement role-based access control (RBAC)\\u003C/li\\u003E\\n    \\u003Cli\\u003EDevelop user profile management features\\u003C/li\\u003E\\n    \\u003Cli\\u003ECreate administrative tools for user oversight and management\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Ch3\\u003EKey Features:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EUser registration with email verification\\u003C/li\\u003E\\n    \\u003Cli\\u003ESecure login system with multi-factor authentication\\u003C/li\\u003E\\n    \\u003Cli\\u003EPassword reset and account recovery mechanisms\\u003C/li\\u003E\\n    \\u003Cli\\u003EUser profile creation and editing\\u003C/li\\u003E\\n    \\u003Cli\\u003ERole and permission management\\u003C/li\\u003E\\n    \\u003Cli\\u003EUser activity tracking and reporting\\u003C/li\\u003E\\n    \\u003Cli\\u003EAccount deactivation and deletion processes\\u003C/li\\u003E\\n    \\u003Cli\\u003EIntegration with existing systems and databases\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Ch3\\u003EExpected Outcomes:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EImproved security and data protection\\u003C/li\\u003E\\n    \\u003Cli\\u003EEnhanced user satisfaction and engagement\\u003C/li\\u003E\\n    \\u003Cli\\u003EReduced administrative overhead\\u003C/li\\u003E\\n    \\u003Cli\\u003EScalable user management infrastructure\\u003C/li\\u003E\\n    \\u003Cli\\u003ECompliance with data protection regulations\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Cp\\u003EThis epic will serve as the foundation for all user-related functionalities in our application, ensuring a secure, efficient, and user-friendly experience.\\u003C/p\\u003E\\n\\u003C/div\\u003E\"\r\n}","FunctionCallIndex":0,"RequestIndex":0,"ChoiceIndex":0,"InnerContent":null,"ModelId":null,"Metadata":null}],"AuthorName":null,"Role":{"Label":"assistant"},"Encoding":{"BodyName":"utf-8","EncodingName":"Unicode (UTF-8)","HeaderName":"utf-8","WebName":"utf-8","WindowsCodePage":1200,"IsBrowserDisplay":true,"IsBrowserSave":true,"IsMailNewsDisplay":true,"IsMailNewsSave":true,"IsSingleByte":false,"EncoderFallback":{"DefaultString":"?","MaxCharCount":1},"DecoderFallback":{"DefaultString":"?","MaxCharCount":1},"IsReadOnly":true,"CodePage":65001},"ChoiceIndex":0,"InnerContent":{"ContentBlockIndex":1},"ModelId":null,"Metadata":null}

Waiting for response.

Thanks,
Mustafa

@davidames
Copy link

Hi @MustafaJamal - function calling is working well for me using M.E.AI - but there was a lot of fiddling around to get it to work, especially around nuget packages - the versions absolutely matter!
My versions are Microsoft.SemanticKernel 1.56 AWSSdk.BedrockRuntime 4.0.0.7 AWSSdk.Extensions.Bedrock.MEAI 4.0.1.1 <= - This was really importing, SK implicitly references and old version Microsoft.Extensions.AI 9.6.0
Here is my working spike code - it does manual function calling (as our main solution does too) - our prod code uses [KernelFunction] and that works too!
I hope it helps!


[Fact]
     [Experimental("SKEXP0001")]
     public async Task RunStreamingChatCompletionApiWithManualFunctionCallingAsync()
    {
        Kernel kernel = CreateBedrockKernel();
        var bedrockConfig = GetService<AwsBedRockConfig>();
        kernel.ImportPluginFromFunctions("HelperFunctions",
        [
            kernel.CreateFunctionFromMethod(() => new List<string> { "Squirrel Steals Show", "Dog Wins Lottery" }, "GetLatestNewsTitles", "Retrieves latest news titles."),
        ]);

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


        OpenAIPromptExecutionSettings settings = new()
        {
            FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false),
            ModelId = bedrockConfig.ClaudeModelId,
            MaxTokens = 1000
        };

        
        ChatHistory chatHistory = [];
        chatHistory.AddUserMessage("Get latest news titles.");

        while (true)
        {
            AuthorRole? authorRole = null;
            var fccBuilder = new FunctionCallContentBuilder();

            try
            {
           
                await foreach (var streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync(
                                   chatHistory, settings, kernel))
                {
                    if (streamingContent.Content is not null)
                    {
                        Logger.Information(streamingContent.Content);
                    
                    }

                    authorRole ??= streamingContent.Role;
                    fccBuilder.Append(streamingContent);
                }

            }
            catch (Exception e)
            {
                Logger.Error(e, "Error during streaming chat completion");
               
            }
            
            var functionCalls = fccBuilder.Build();
            if (!functionCalls.Any())
            {
                break;
            }

            var fcContent = new ChatMessageContent(role: authorRole ?? default, content: null);
           
            foreach (var functionCall in functionCalls)
            {
                fcContent.Items.Add(functionCall);

                var functionResult = await functionCall.InvokeAsync(kernel);

                chatHistory.Add(functionResult.ToChatMessage());
            }
        }
    }

Hi @davidames,

Many thanks for response. I found that I was using AmazonClaudeExecutionSettings instead of AnthropicPromptExecutionSettings, so it worked for me now and now no exceptions are appearing. But now no functions are being called although assistant has function information here are details:

promptExecutionSettings = new AnthropicPromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(), Temperature = 0.5, ModelId = modelId // modelId = us.anthropic.claude-3-5-sonnet-20240620-v1:0 };

When I asked assistant:

what functions or tool call are available

It answered me right:

SKWorkItemSkill_CreateWorkItem SKWorkItemSkill_UpdateWorkItem SKWorkItemSkill_PatchWorkItem SKWorkItemSkill_DeleteWorkItem SKWorkItemSkill_LinkWorkItems SKWorkItemSkill_AddCommentToWorkItem SKWorkItemSkill_DeleteWorkItemLink SKWorkItemSkill_GetCurrentWorkItem SKWorkItemSkill_GetCurrentWorkItems SKQuerySkill_CreateQuery SKQuerySkill_UpdateQuery SKQuerySkill_DeleteQuery SKQuerySkill_GetQueryType SKQuerySkill_GetCurrentQuery SKDataSkill_GetWorkItem SKDataSkill_GetLinkedWorkItems SKDataSkill_GetWorkItems SKDataSkill_GetWorkItemsByIds SKDataSkill_GetWorkItemsByType SKDataSkill_GetWorkItemsByQueryId SKDataSkill_GetWorkItemsByQueryString SKDataSkill_GetWorkItemTypes SKDataSkill_GetWorkItemTypeDefinition SKDataSkill_GetRelationTypes SKDataSkill_SearchWorkItems SKDataSkill_GetUsers SKDataSkill_GetProjects SKDataSkill_GetQueries SKDataSkill_GetBacklogWorkItems SKDataSkill_GetCurrentSprint SKDataSkill_GenerateMermaidDiagram SKDataSkill_ConvertMermaidToImage SKDataSkill_ConvertHtmlToImage SKDataSkill_GetDownloadLinkForFileContent SKPythonSkill_ListPythonLibraries SKPythonSkill_InstallPythonLibrary SKPythonSkill_RunPythonCode

Also when I asked that:

Create Epic work item for User Management, generate title and description by yourself

it answered this(although it waited for 2-3 seconds after sending message) but did not do any function call:

** Certainly, I'll create an Epic work item for User Management with a generated title and description right away.

Thinking: Generating title and description for User Management Epic

Creating: Preparing to create new Epic work item

Now, I'll use the SKWorkItemSkill_CreateWorkItem function to create this Epic: **

My Nuget API versions as same as yours.

Also I checked StreamingChatMessageContent does receive function call related data, but function doesn't call:

{"Content":null,"Items":[{"CallId":"tooluse_bTgNyH1HQauYzRHFj5D5Wg","Name":"SKWorkItemSkill_CreateWorkItem","Arguments":"{\r\n  \"workItemType\": \"Epic\",\r\n  \"title\": \"Implement Comprehensive User Management System\",\r\n  \"description\": \"\\u003Cdiv\\u003E\\n\\u003Ch2\\u003EEpic: Implement Comprehensive User Management System\\u003C/h2\\u003E\\n\\n\\u003Cp\\u003EThis epic encompasses the development and implementation of a robust user management system to enhance our application\\u0027s security, user experience, and administrative capabilities.\\u003C/p\\u003E\\n\\n\\u003Ch3\\u003EObjectives:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EStreamline user registration and onboarding processes\\u003C/li\\u003E\\n    \\u003Cli\\u003EEnhance authentication and authorization mechanisms\\u003C/li\\u003E\\n    \\u003Cli\\u003EImplement role-based access control (RBAC)\\u003C/li\\u003E\\n    \\u003Cli\\u003EDevelop user profile management features\\u003C/li\\u003E\\n    \\u003Cli\\u003ECreate administrative tools for user oversight and management\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Ch3\\u003EKey Features:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EUser registration with email verification\\u003C/li\\u003E\\n    \\u003Cli\\u003ESecure login system with multi-factor authentication\\u003C/li\\u003E\\n    \\u003Cli\\u003EPassword reset and account recovery mechanisms\\u003C/li\\u003E\\n    \\u003Cli\\u003EUser profile creation and editing\\u003C/li\\u003E\\n    \\u003Cli\\u003ERole and permission management\\u003C/li\\u003E\\n    \\u003Cli\\u003EUser activity tracking and reporting\\u003C/li\\u003E\\n    \\u003Cli\\u003EAccount deactivation and deletion processes\\u003C/li\\u003E\\n    \\u003Cli\\u003EIntegration with existing systems and databases\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Ch3\\u003EExpected Outcomes:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EImproved security and data protection\\u003C/li\\u003E\\n    \\u003Cli\\u003EEnhanced user satisfaction and engagement\\u003C/li\\u003E\\n    \\u003Cli\\u003EReduced administrative overhead\\u003C/li\\u003E\\n    \\u003Cli\\u003EScalable user management infrastructure\\u003C/li\\u003E\\n    \\u003Cli\\u003ECompliance with data protection regulations\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Cp\\u003EThis epic will serve as the foundation for all user-related functionalities in our application, ensuring a secure, efficient, and user-friendly experience.\\u003C/p\\u003E\\n\\u003C/div\\u003E\"\r\n}","FunctionCallIndex":0,"RequestIndex":0,"ChoiceIndex":0,"InnerContent":null,"ModelId":null,"Metadata":null}],"AuthorName":null,"Role":{"Label":"assistant"},"Encoding":{"BodyName":"utf-8","EncodingName":"Unicode (UTF-8)","HeaderName":"utf-8","WebName":"utf-8","WindowsCodePage":1200,"IsBrowserDisplay":true,"IsBrowserSave":true,"IsMailNewsDisplay":true,"IsMailNewsSave":true,"IsSingleByte":false,"EncoderFallback":{"DefaultString":"?","MaxCharCount":1},"DecoderFallback":{"DefaultString":"?","MaxCharCount":1},"IsReadOnly":true,"CodePage":65001},"ChoiceIndex":0,"InnerContent":{"ContentBlockIndex":1},"ModelId":null,"Metadata":null}

Waiting for response.

Thanks, Mustafa

Hi @MustafaJamal - I really don't know - given this conversation has progressed well beyond the scope of the original PR, it's probably time to raise a new issue or discussion.

@MustafaJamal
Copy link

Hi @MustafaJamal - function calling is working well for me using M.E.AI - but there was a lot of fiddling around to get it to work, especially around nuget packages - the versions absolutely matter!
My versions are Microsoft.SemanticKernel 1.56 AWSSdk.BedrockRuntime 4.0.0.7 AWSSdk.Extensions.Bedrock.MEAI 4.0.1.1 <= - This was really importing, SK implicitly references and old version Microsoft.Extensions.AI 9.6.0
Here is my working spike code - it does manual function calling (as our main solution does too) - our prod code uses [KernelFunction] and that works too!
I hope it helps!


[Fact]
     [Experimental("SKEXP0001")]
     public async Task RunStreamingChatCompletionApiWithManualFunctionCallingAsync()
    {
        Kernel kernel = CreateBedrockKernel();
        var bedrockConfig = GetService<AwsBedRockConfig>();
        kernel.ImportPluginFromFunctions("HelperFunctions",
        [
            kernel.CreateFunctionFromMethod(() => new List<string> { "Squirrel Steals Show", "Dog Wins Lottery" }, "GetLatestNewsTitles", "Retrieves latest news titles."),
        ]);

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


        OpenAIPromptExecutionSettings settings = new()
        {
            FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false),
            ModelId = bedrockConfig.ClaudeModelId,
            MaxTokens = 1000
        };

        
        ChatHistory chatHistory = [];
        chatHistory.AddUserMessage("Get latest news titles.");

        while (true)
        {
            AuthorRole? authorRole = null;
            var fccBuilder = new FunctionCallContentBuilder();

            try
            {
           
                await foreach (var streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync(
                                   chatHistory, settings, kernel))
                {
                    if (streamingContent.Content is not null)
                    {
                        Logger.Information(streamingContent.Content);
                    
                    }

                    authorRole ??= streamingContent.Role;
                    fccBuilder.Append(streamingContent);
                }

            }
            catch (Exception e)
            {
                Logger.Error(e, "Error during streaming chat completion");
               
            }
            
            var functionCalls = fccBuilder.Build();
            if (!functionCalls.Any())
            {
                break;
            }

            var fcContent = new ChatMessageContent(role: authorRole ?? default, content: null);
           
            foreach (var functionCall in functionCalls)
            {
                fcContent.Items.Add(functionCall);

                var functionResult = await functionCall.InvokeAsync(kernel);

                chatHistory.Add(functionResult.ToChatMessage());
            }
        }
    }

Hi @davidames,
Many thanks for response. I found that I was using AmazonClaudeExecutionSettings instead of AnthropicPromptExecutionSettings, so it worked for me now and now no exceptions are appearing. But now no functions are being called although assistant has function information here are details:
promptExecutionSettings = new AnthropicPromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(), Temperature = 0.5, ModelId = modelId // modelId = us.anthropic.claude-3-5-sonnet-20240620-v1:0 };
When I asked assistant:
what functions or tool call are available
It answered me right:
SKWorkItemSkill_CreateWorkItem SKWorkItemSkill_UpdateWorkItem SKWorkItemSkill_PatchWorkItem SKWorkItemSkill_DeleteWorkItem SKWorkItemSkill_LinkWorkItems SKWorkItemSkill_AddCommentToWorkItem SKWorkItemSkill_DeleteWorkItemLink SKWorkItemSkill_GetCurrentWorkItem SKWorkItemSkill_GetCurrentWorkItems SKQuerySkill_CreateQuery SKQuerySkill_UpdateQuery SKQuerySkill_DeleteQuery SKQuerySkill_GetQueryType SKQuerySkill_GetCurrentQuery SKDataSkill_GetWorkItem SKDataSkill_GetLinkedWorkItems SKDataSkill_GetWorkItems SKDataSkill_GetWorkItemsByIds SKDataSkill_GetWorkItemsByType SKDataSkill_GetWorkItemsByQueryId SKDataSkill_GetWorkItemsByQueryString SKDataSkill_GetWorkItemTypes SKDataSkill_GetWorkItemTypeDefinition SKDataSkill_GetRelationTypes SKDataSkill_SearchWorkItems SKDataSkill_GetUsers SKDataSkill_GetProjects SKDataSkill_GetQueries SKDataSkill_GetBacklogWorkItems SKDataSkill_GetCurrentSprint SKDataSkill_GenerateMermaidDiagram SKDataSkill_ConvertMermaidToImage SKDataSkill_ConvertHtmlToImage SKDataSkill_GetDownloadLinkForFileContent SKPythonSkill_ListPythonLibraries SKPythonSkill_InstallPythonLibrary SKPythonSkill_RunPythonCode
Also when I asked that:
Create Epic work item for User Management, generate title and description by yourself
it answered this(although it waited for 2-3 seconds after sending message) but did not do any function call:
** Certainly, I'll create an Epic work item for User Management with a generated title and description right away.
Thinking: Generating title and description for User Management Epic
Creating: Preparing to create new Epic work item
Now, I'll use the SKWorkItemSkill_CreateWorkItem function to create this Epic: **
My Nuget API versions as same as yours.
Also I checked StreamingChatMessageContent does receive function call related data, but function doesn't call:

{"Content":null,"Items":[{"CallId":"tooluse_bTgNyH1HQauYzRHFj5D5Wg","Name":"SKWorkItemSkill_CreateWorkItem","Arguments":"{\r\n  \"workItemType\": \"Epic\",\r\n  \"title\": \"Implement Comprehensive User Management System\",\r\n  \"description\": \"\\u003Cdiv\\u003E\\n\\u003Ch2\\u003EEpic: Implement Comprehensive User Management System\\u003C/h2\\u003E\\n\\n\\u003Cp\\u003EThis epic encompasses the development and implementation of a robust user management system to enhance our application\\u0027s security, user experience, and administrative capabilities.\\u003C/p\\u003E\\n\\n\\u003Ch3\\u003EObjectives:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EStreamline user registration and onboarding processes\\u003C/li\\u003E\\n    \\u003Cli\\u003EEnhance authentication and authorization mechanisms\\u003C/li\\u003E\\n    \\u003Cli\\u003EImplement role-based access control (RBAC)\\u003C/li\\u003E\\n    \\u003Cli\\u003EDevelop user profile management features\\u003C/li\\u003E\\n    \\u003Cli\\u003ECreate administrative tools for user oversight and management\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Ch3\\u003EKey Features:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EUser registration with email verification\\u003C/li\\u003E\\n    \\u003Cli\\u003ESecure login system with multi-factor authentication\\u003C/li\\u003E\\n    \\u003Cli\\u003EPassword reset and account recovery mechanisms\\u003C/li\\u003E\\n    \\u003Cli\\u003EUser profile creation and editing\\u003C/li\\u003E\\n    \\u003Cli\\u003ERole and permission management\\u003C/li\\u003E\\n    \\u003Cli\\u003EUser activity tracking and reporting\\u003C/li\\u003E\\n    \\u003Cli\\u003EAccount deactivation and deletion processes\\u003C/li\\u003E\\n    \\u003Cli\\u003EIntegration with existing systems and databases\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Ch3\\u003EExpected Outcomes:\\u003C/h3\\u003E\\n\\u003Cul\\u003E\\n    \\u003Cli\\u003EImproved security and data protection\\u003C/li\\u003E\\n    \\u003Cli\\u003EEnhanced user satisfaction and engagement\\u003C/li\\u003E\\n    \\u003Cli\\u003EReduced administrative overhead\\u003C/li\\u003E\\n    \\u003Cli\\u003EScalable user management infrastructure\\u003C/li\\u003E\\n    \\u003Cli\\u003ECompliance with data protection regulations\\u003C/li\\u003E\\n\\u003C/ul\\u003E\\n\\n\\u003Cp\\u003EThis epic will serve as the foundation for all user-related functionalities in our application, ensuring a secure, efficient, and user-friendly experience.\\u003C/p\\u003E\\n\\u003C/div\\u003E\"\r\n}","FunctionCallIndex":0,"RequestIndex":0,"ChoiceIndex":0,"InnerContent":null,"ModelId":null,"Metadata":null}],"AuthorName":null,"Role":{"Label":"assistant"},"Encoding":{"BodyName":"utf-8","EncodingName":"Unicode (UTF-8)","HeaderName":"utf-8","WebName":"utf-8","WindowsCodePage":1200,"IsBrowserDisplay":true,"IsBrowserSave":true,"IsMailNewsDisplay":true,"IsMailNewsSave":true,"IsSingleByte":false,"EncoderFallback":{"DefaultString":"?","MaxCharCount":1},"DecoderFallback":{"DefaultString":"?","MaxCharCount":1},"IsReadOnly":true,"CodePage":65001},"ChoiceIndex":0,"InnerContent":{"ContentBlockIndex":1},"ModelId":null,"Metadata":null}

Waiting for response.
Thanks, Mustafa

Hi @MustafaJamal - I really don't know - given this conversation has progressed well beyond the scope of the original PR, it's probably time to raise a new issue or discussion.

Hello @davidames,

Many thanks for your help, and yes you are right this discussion is taking long time so I have posted an issue with all the details:

#12531

Thanks for valuable help :)

Cheers,
Mustafa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kernel.core kernel Issues or pull requests impacting the core kernel .NET Issue or Pull requests regarding .NET code
Projects
Status: Sprint: In Review
9 participants