Skip to content

[AI] FunctionCallContent is not included in StreamingChatCompletionUpdate when KeepFunctionCallingMessages enabled #5909

@Gigabyte0x1337

Description

@Gigabyte0x1337

Description

When using Microsoft.Extensions.AI with function calling and streaming, the FunctionCallContent is not included, even with KeepFunctionCallingMessages enabled.

The reason I need this is to notify my front-end that a function call is busy. Of course, I could implement the whole thing myself, but what's the point of having it if it doesn't serve this purpose?

Reproduction Steps

Minimal example code to repreduce this.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
	  <OutputType>Exe</OutputType>
	  <TargetFramework>net9.0</TargetFramework>
	  <ImplicitUsings>enable</ImplicitUsings>
	  <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.AI" Version="9.1.0-preview.1.25064.3" />
    <PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.1.0-preview.1.25064.3" />
    <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.1.0-preview.1.25064.3" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.2" />
  </ItemGroup>

</Project>
var chatClient = new ChatClientBuilder(new OpenAIChatClient(new OpenAIClient(openAiKey), "gpt-4o"))
    .UseFunctionInvocation(null, client =>
    {
        client.KeepFunctionCallingMessages = true;
        client.RetryOnError = true;
        client.ConcurrentInvocation = true;
    })
    .Build();


var messageStream = chatClient.CompleteStreamingAsync([
    new ChatMessage(ChatRole.System, [new TextContent("You are a helpful assistant")]),
    new ChatMessage(ChatRole.User,
    [
        new TextContent(
            "Hello, can you call the test function, try `test` as input. Follow the instruction solve the riddle! No need for confirmation do it yourself!")
    ])
], new ChatOptions()
{
    Tools = [AIFunctionFactory.Create((string? password) => password != "The Goat" ? 
        "Call me again with `The Goat` and see what happens next!" : 
        "Pass this along will you, 'The goat has been milked'!", "test_function", "This is function to test function calling.")]
});


await foreach (var messageUpdate in messageStream)
{
    foreach (var messageUpdateContent in messageUpdate.Contents)
    {
        if (messageUpdateContent is TextContent textContent)
        {
            Console.Write(textContent.Text);
        }
        else if (messageUpdateContent is UsageContent usageContent)
        {
            // Ignore usage
        }
        else
        {
            if (Console.GetCursorPosition().Left != 0)
            {
                Console.WriteLine();
            }

            Console.WriteLine(
                $"MessageUpdate {messageUpdateContent.GetType().Name} {messageUpdate.GetMessageId()}, {messageUpdate.GetParentMessageId()} Text: {messageUpdate.Text}");
        }
    }
}

// Output: "The goat has been milked"!

Expected behavior

MessageUpdate with FunctionCallContent when KeepFunctionCallingMessages is enabled.

Actual behavior

FunctionCallContent, FunctionResultContent is not included in the updates

Regression?

No response

Known Workarounds

No response

Configuration

.net 9

Other information

No response

Metadata

Metadata

Assignees

Labels

area-aiMicrosoft.Extensions.AI libraries

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions