Compare commits

...

10 Commits

Author SHA1 Message Date
  XiaoYun Zhang 3148bcebf2 update oai and aoai package version 1 year ago
  XiaoYun Zhang e5810a3920 Merge branch 'LittleLittleCloud-patch-1' of https://github.com/microsoft/autogen into LittleLittleCloud-patch-1 1 year ago
  XiaoYun Zhang 297c1f08fa fix aot tests 1 year ago
  Xiaoyun Zhang cdaa9b00ad
Update dotnet-build.yml 1 year ago
  XiaoYun Zhang d834d257b5 fix formatting 1 year ago
  XiaoYun Zhang 1ffb7dc935 fix whitespace 1 year ago
  XiaoYun Zhang 32c0605a7a fix IDE warning 1 year ago
  Xiaoyun Zhang 0245ab7321
Update rollForward to latestFeature in global.json 1 year ago
  Xiaoyun Zhang f20d326942
Update dotnet-build.yml 1 year ago
  Xiaoyun Zhang 1d4f31041c
.NET update global.json to use 9.0.100 1 year ago
29 changed files with 445 additions and 208 deletions
Split View
  1. +12
    -0
      .github/workflows/dotnet-build.yml
  2. +1
    -1
      dotnet/.tools/test-aot-compatibility.ps1
  3. +16
    -13
      dotnet/Directory.Packages.props
  4. +2
    -2
      dotnet/global.json
  5. +1
    -3
      dotnet/samples/AgentChat/AutoGen.OpenAI.Sample/Tool_Call_With_Ollama_And_LiteLLM.cs
  6. +1
    -1
      dotnet/samples/AgentChat/AutoGen.WebAPI.Sample/Program.cs
  7. +39
    -50
      dotnet/src/AutoGen.Core/Function/FunctionAttribute.cs
  8. +2
    -2
      dotnet/src/AutoGen.Core/Middleware/FunctionCallMiddleware.cs
  9. +3
    -2
      dotnet/src/AutoGen.SemanticKernel/SemanticKernelChatCompletionAgent.cs
  10. +4
    -5
      dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/ChatAgent.cs
  11. +6
    -6
      dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/MessageHandling.cs
  12. +10
    -10
      dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Messages.cs
  13. +4
    -4
      dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Tasks.cs
  14. +5
    -5
      dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Termination.cs
  15. +6
    -68
      dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Tools.cs
  16. +1
    -1
      dotnet/src/Microsoft.AutoGen/AgentChat/GroupChat/GroupChatBase.cs
  17. +2
    -2
      dotnet/src/Microsoft.AutoGen/AgentChat/GroupChat/GroupChatHandlerRouter.cs
  18. +2
    -2
      dotnet/src/Microsoft.AutoGen/AgentChat/GroupChat/OutputCollectorAgent.cs
  19. +4
    -4
      dotnet/src/Microsoft.AutoGen/Agents/AIAgent/InferenceAgent.cs
  20. +3
    -2
      dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcMessageRouter.cs
  21. +4
    -4
      dotnet/src/Microsoft.AutoGen/Core/ResultSink.cs
  22. +16
    -16
      dotnet/src/Microsoft.AutoGen/Extensions/MEAI/ServiceCollectionChatCompletionExtensions.cs
  23. +1
    -1
      dotnet/src/Microsoft.AutoGen/RuntimeGateway.Grpc/Services/Grpc/GrpcGateway.cs
  24. +1
    -1
      dotnet/test/AutoGen.AotCompatibility.Tests/AutoGen.AotCompatibility.Tests.csproj
  25. +36
    -0
      dotnet/test/AutoGen.OpenAI.Tests/ApprovalTests/OpenAIMessageTests.BasicMessageTest.approved.txt
  26. +260
    -0
      dotnet/test/AutoGen.OpenAI.Tests/ApprovalTests/OpenAIMessageTests.BasicMessageTest.received.txt
  27. +1
    -1
      dotnet/test/AutoGen.Tests/Function/FunctionTests.cs
  28. +1
    -1
      dotnet/test/AutoGen.Tests/MiddlewareTest.cs
  29. +1
    -1
      dotnet/test/Microsoft.AutoGen.Core.Grpc.Tests/TestGrpcWorkerConnection.cs

+ 12
- 0
.github/workflows/dotnet-build.yml View File

@@ -81,6 +81,10 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Restore dependencies
run: dotnet restore -bl
- name: Format check
@@ -207,6 +211,10 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: publish AOT testApp, assert static analysis warning count, and run the app
shell: pwsh
@@ -249,6 +257,10 @@ jobs:
with:
dotnet-version: '8.0.x'
global-json-file: dotnet/global.json
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install dev certs
run: dotnet --version && dotnet dev-certs https --trust
- name: Restore dependencies


+ 1
- 1
dotnet/.tools/test-aot-compatibility.ps1 View File

@@ -15,7 +15,7 @@ foreach ($line in $($publishOutput -split "`r`n"))
}
}

pushd $rootDirectory/artifacts/bin/AutoGen.AotCompatibility.Tests/release
pushd $rootDirectory/artifacts/bin/AutoGen.AotCompatibility.Tests/release/native

Write-Host "Executing test App..."
./AutoGen.AotCompatibility.Tests


+ 16
- 13
dotnet/Directory.Packages.props View File

@@ -2,10 +2,12 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<MicrosoftSemanticKernelVersion>1.22.0</MicrosoftSemanticKernelVersion>
<MicrosoftSemanticKernelExperimentalVersion>1.22.0-alpha</MicrosoftSemanticKernelExperimentalVersion>
<MicrosoftExtensionsAIVersion>9.0.0-preview.9.24525.1</MicrosoftExtensionsAIVersion>
<MicrosoftSemanticKernelStableVersion>1.45.0</MicrosoftSemanticKernelStableVersion>
<MicrosoftSemanticKernelPreviewVersion>$(MicrosoftSemanticKernelStableVersion)-preview</MicrosoftSemanticKernelPreviewVersion>
<MicrosoftSemanticKernelAlphaVersion>$(MicrosoftSemanticKernelStableVersion)-alpha</MicrosoftSemanticKernelAlphaVersion>
<MicrosoftExtensionsAIVersion>9.3.0-preview.1.25161.3</MicrosoftExtensionsAIVersion>
<MicrosoftExtensionConfiguration>9.0.0</MicrosoftExtensionConfiguration>
<MicrosoftExtensionDependencyInjection>9.0.0</MicrosoftExtensionDependencyInjection>
<MicrosoftExtensionDependencyInjection>9.0.3</MicrosoftExtensionDependencyInjection>
<MicrosoftExtensionLogging>9.0.0</MicrosoftExtensionLogging>
<MicrosoftExtensionOptions>9.0.0</MicrosoftExtensionOptions>
<MicrosoftOrleans>9.0.1</MicrosoftOrleans>
@@ -18,7 +20,7 @@
<PackageVersion Include="Aspire.Hosting" Version="9.0.0" />
<PackageVersion Include="Aspire.Hosting.Python" Version="9.0.0" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="9.0.0" />
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="8.0.1-preview.8.24267.1" />
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="9.0.0-preview.5.24551.3" />
<PackageVersion Include="Aspire.Hosting.AppHost" Version="9.0.0" />
<PackageVersion Include="Aspire.Hosting.Azure.ApplicationInsights" Version="9.0.0" />
<PackageVersion Include="Aspire.Hosting.Azure.CognitiveServices" Version="9.0.0" />
@@ -27,9 +29,10 @@
<PackageVersion Include="Aspire.Hosting.Qdrant" Version="9.0.0" />
<PackageVersion Include="Aspire.Hosting.Redis" Version="8.2.0" />
<PackageVersion Include="AspNetCore.Authentication.ApiKey" Version="8.0.1" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.1.0-beta.2" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.2.0-beta.4" />
<PackageVersion Include="Azure.AI.Inference" Version="1.0.0-beta.1" />
<PackageVersion Include="Azure.Data.Tables" Version="12.9.1" />
<PackageVersion Include="Azure.Core" Version="1.44.1" />
<PackageVersion Include="Azure.Identity" Version="1.13.1" />
<PackageVersion Include="Azure.ResourceManager.ContainerInstance" Version="1.2.1" />
<PackageVersion Include="Azure.Storage.Files.Shares" Version="12.21.0" />
@@ -100,18 +103,18 @@
<PackageVersion Include="Microsoft.Orleans.Streaming.EventHubs" Version="$(MicrosoftOrleans)" />
<PackageVersion Include="Microsoft.Orleans.TestingHost" Version="9.0.1" />
<PackageVersion Include="Microsoft.PowerShell.SDK" Version="7.5.0" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.29.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Agents.Core" Version="$(MicrosoftSemanticKernelExperimentalVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureOpenAI" Version="1.29.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Qdrant" Version="$(MicrosoftSemanticKernelExperimentalVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Plugins.Memory" Version="$(MicrosoftSemanticKernelExperimentalVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Plugins.Web" Version="$(MicrosoftSemanticKernelExperimentalVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="$(MicrosoftSemanticKernelStableVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Agents.Core" Version="$(MicrosoftSemanticKernelStableVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureOpenAI" Version="$(MicrosoftSemanticKernelStableVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Qdrant" Version="$(MicrosoftSemanticKernelPreviewVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Plugins.Memory" Version="$(MicrosoftSemanticKernelAlphaVersion)" />
<PackageVersion Include="Microsoft.SemanticKernel.Plugins.Web" Version="$(MicrosoftSemanticKernelAlphaVersion)" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Octokit" Version="13.0.1" />
<PackageVersion Include="Octokit.Webhooks.AspNetCore" Version="2.4.1" />
<PackageVersion Include="OpenAI" Version="2.1.0-beta.2" />
<PackageVersion Include="OpenAI" Version="2.2.0-beta.4" />
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.10.0" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.10.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryInstrumentation)" />
@@ -127,7 +130,7 @@
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.2.1" />
<PackageVersion Include="System.IO.Packaging" Version="9.0.0" />
<PackageVersion Include="System.Memory.Data" Version="9.0.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.3" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.console" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />


+ 2
- 2
dotnet/global.json View File

@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.401",
"rollForward": "latestMinor"
"version": "9.0.100",
"rollForward": "latestFeature"
}
}

+ 1
- 3
dotnet/samples/AgentChat/AutoGen.OpenAI.Sample/Tool_Call_With_Ollama_And_LiteLLM.cs View File

@@ -42,8 +42,6 @@ public class Tool_Call_With_Ollama_And_LiteLLM
});
#endregion Create_tools
#region Create_Agent
var liteLLMUrl = "http://localhost:4000";

// api-key is not required for local server
// so you can use any string here
var openAIClient = new OpenAIClient(new ApiKeyCredential("api-key"), new OpenAIClientOptions
@@ -59,7 +57,7 @@ public class Tool_Call_With_Ollama_And_LiteLLM
.RegisterMiddleware(functionMiddleware)
.RegisterPrintMessage();

var reply = await agent.SendAsync("what's the weather in new york");
await agent.SendAsync("what's the weather in new york");
#endregion Create_Agent
}
}

+ 1
- 1
dotnet/samples/AgentChat/AutoGen.WebAPI.Sample/Program.cs View File

@@ -40,6 +40,6 @@ public class DummyAgent : IStreamingAgent
foreach (var c in reply)
{
yield return new TextMessageUpdate(Role.Assistant, c.ToString(), this.Name);
};
}
}
}

+ 39
- 50
dotnet/src/AutoGen.Core/Function/FunctionAttribute.cs View File

@@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.AI;

@@ -69,36 +71,48 @@ public class FunctionContract
/// </summary>
public string? ReturnDescription { get; set; }

public static implicit operator FunctionContract(AIFunctionMetadata metadata)
public static implicit operator FunctionContract(AIFunction function)
{
return new FunctionContract
var openapiScheme = function.JsonSchema;
var parameters = new List<FunctionParameterContract>();
string[] isRequiredProperties = [];
if (openapiScheme.TryGetProperty("required", out var requiredElement))
{
Namespace = metadata.AdditionalProperties.ContainsKey(NamespaceKey) ? metadata.AdditionalProperties[NamespaceKey] as string : null,
ClassName = metadata.AdditionalProperties.ContainsKey(ClassNameKey) ? metadata.AdditionalProperties[ClassNameKey] as string : null,
Name = metadata.Name,
Description = metadata.Description,
Parameters = metadata.Parameters?.Select(p => (FunctionParameterContract)p).ToList(),
ReturnType = metadata.ReturnParameter.ParameterType,
ReturnDescription = metadata.ReturnParameter.Description,
};
}
isRequiredProperties = requiredElement.Deserialize<string[]>() ?? [];
}

public static implicit operator AIFunctionMetadata(FunctionContract contract)
{
return new AIFunctionMetadata(contract.Name)
var parameterList = function.UnderlyingMethod?.GetParameters() ?? Array.Empty<ParameterInfo>();

if (openapiScheme.TryGetProperty("properties", out var propertiesElement))
{
Description = contract.Description,
ReturnParameter = new AIFunctionReturnParameterMetadata()
var properties = propertiesElement.Deserialize<Dictionary<string, JsonElement>>() ?? new Dictionary<string, JsonElement>();
foreach (var property in properties)
{
Description = contract.ReturnDescription,
ParameterType = contract.ReturnType,
},
AdditionalProperties = new Dictionary<string, object?>
{
[NamespaceKey] = contract.Namespace,
[ClassNameKey] = contract.ClassName,
},
Parameters = [.. contract.Parameters?.Select(p => (AIFunctionParameterMetadata)p)!],
var parameterType = parameterList.FirstOrDefault(p => p.Name == property.Key)?.ParameterType;
var parameter = new FunctionParameterContract
{
Name = property.Key,
ParameterType = parameterType, // TODO: Need to get the type from the schema
IsRequired = isRequiredProperties.Contains(property.Key),
};
if (property.Value.TryGetProperty("description", out var descriptionElement))
{
parameter.Description = descriptionElement.GetString();
}
if (property.Value.TryGetProperty("default", out var defaultValueElement))
{
parameter.DefaultValue = defaultValueElement.Deserialize<object>();
}
parameters.Add(parameter);
}
}
return new FunctionContract
{
Namespace = function.AdditionalProperties.ContainsKey(NamespaceKey) ? function.AdditionalProperties[NamespaceKey] as string : null,
ClassName = function.AdditionalProperties.ContainsKey(ClassNameKey) ? function.AdditionalProperties[ClassNameKey] as string : null,
Name = function.Name,
Description = function.Description,
Parameters = parameters,
};
}
}
@@ -132,29 +146,4 @@ public class FunctionParameterContract
/// The default value of the parameter.
/// </summary>
public object? DefaultValue { get; set; }

// convert to/from FunctionParameterMetadata
public static implicit operator FunctionParameterContract(AIFunctionParameterMetadata metadata)
{
return new FunctionParameterContract
{
Name = metadata.Name,
Description = metadata.Description,
ParameterType = metadata.ParameterType,
IsRequired = metadata.IsRequired,
DefaultValue = metadata.DefaultValue,
};
}

public static implicit operator AIFunctionParameterMetadata(FunctionParameterContract contract)
{
return new AIFunctionParameterMetadata(contract.Name!)
{
DefaultValue = contract.DefaultValue,
Description = contract.Description,
IsRequired = contract.IsRequired,
ParameterType = contract.ParameterType,
HasDefaultValue = contract.DefaultValue != null,
};
}
}

+ 2
- 2
dotnet/src/AutoGen.Core/Middleware/FunctionCallMiddleware.cs View File

@@ -53,9 +53,9 @@ public class FunctionCallMiddleware : IStreamingMiddleware
public FunctionCallMiddleware(IEnumerable<AIFunction> functions, string? name = null)
{
this.Name = name ?? nameof(FunctionCallMiddleware);
this.functions = functions.Select(f => (FunctionContract)f.Metadata).ToArray();
this.functions = functions.Select(f => (FunctionContract)f).ToArray();

this.functionMap = functions.Select(f => (f.Metadata.Name, this.AIToolInvokeWrapper(f.InvokeAsync))).ToDictionary(f => f.Name, f => f.Item2);
this.functionMap = functions.Select(f => (f.Name, this.AIToolInvokeWrapper(f.InvokeAsync))).ToDictionary(f => f.Name, f => f.Item2);
}

public string? Name { get; }


+ 3
- 2
dotnet/src/AutoGen.SemanticKernel/SemanticKernelChatCompletionAgent.cs View File

@@ -26,8 +26,9 @@ public class SemanticKernelChatCompletionAgent : IAgent
public async Task<IMessage> GenerateReplyAsync(IEnumerable<IMessage> messages, GenerateReplyOptions? options = null,
CancellationToken cancellationToken = default)
{
ChatMessageContent[] reply = await _chatCompletionAgent
.InvokeAsync(BuildChatHistory(messages), cancellationToken: cancellationToken)
var agentThread = new ChatHistoryAgentThread(BuildChatHistory(messages));
var reply = await _chatCompletionAgent
.InvokeAsync(agentThread, cancellationToken: cancellationToken)
.ToArrayAsync(cancellationToken: cancellationToken);

return reply.Length > 1


+ 4
- 5
dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/ChatAgent.cs View File

@@ -170,24 +170,23 @@ public interface IChatAgent :
/// <summary>
/// The name of the agent. This is used by team to uniquely identify the agent.It should be unique within the team.
/// </summary>
AgentName Name { get; }
public AgentName Name { get; }

/// <summary>
/// The description of the agent. This is used by team to make decisions about which agents to use.The description
/// should describe the agent's capabilities and how to interact with it.
/// </summary>
string Description { get; }
public string Description { get; }

/// <summary>
/// The types of messages that the agent produces.
/// </summary>
IEnumerable<Type> ProducedMessageTypes { get; } // TODO: Is there a way to make this part of the type somehow?
// Annotations, or IProduce<>? Do we ever actually access this?
public IEnumerable<Type> ProducedMessageTypes { get; } // TODO: Is there a way to make this part of the type somehow? Annotations, or IProduce<>? Do we ever actually access this?

/// <summary>
/// Reset the agent to its initialization state.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
ValueTask ResetAsync(CancellationToken cancellationToken);
public ValueTask ResetAsync(CancellationToken cancellationToken);
}

+ 6
- 6
dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/MessageHandling.cs View File

@@ -5,22 +5,22 @@ namespace Microsoft.AutoGen.AgentChat.Abstractions;

public interface IHandleChat<in TIn>
{
ValueTask HandleAsync(TIn item)
public ValueTask HandleAsync(TIn item)
{
return this.HandleAsync(item, CancellationToken.None);
}

ValueTask HandleAsync(TIn item, CancellationToken cancellationToken);
public ValueTask HandleAsync(TIn item, CancellationToken cancellationToken);
}

public interface IHandleChat<in TIn, TOut> // TODO: Map this to IHandle<> somehow?
{
ValueTask<TOut> HandleAsync(TIn item)
public ValueTask<TOut> HandleAsync(TIn item)
{
return this.HandleAsync(item, CancellationToken.None);
}

ValueTask<TOut> HandleAsync(TIn item, CancellationToken cancellationToken);
public ValueTask<TOut> HandleAsync(TIn item, CancellationToken cancellationToken);
}

public interface IHandleDefault : IHandleChat<object>
@@ -29,10 +29,10 @@ public interface IHandleDefault : IHandleChat<object>

public interface IHandleStream<in TIn, TOut>
{
IAsyncEnumerable<TOut> StreamAsync(TIn item)
public IAsyncEnumerable<TOut> StreamAsync(TIn item)
{
return this.StreamAsync(item, CancellationToken.None);
}

IAsyncEnumerable<TOut> StreamAsync(TIn item, CancellationToken cancellationToken);
public IAsyncEnumerable<TOut> StreamAsync(TIn item, CancellationToken cancellationToken);
}

+ 10
- 10
dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Messages.cs View File

@@ -116,7 +116,7 @@ public struct MultiModalData
/// <param name="item">The <see cref="AIContent"/> to wrap.</param>
/// <returns>A <see cref="MultiModalData"/> instance wrapping the <paramref name="item"/>.</returns>
/// <exception cref="ArgumentException">
/// Thrown if the <paramref name="item"/> is not a <see cref="TextContent"/> or <see cref="ImageContent"/>.
/// Thrown if the <paramref name="item"/> is not a <see cref="TextContent"/> or <see cref="DataContent"/>.
/// </exception>
public static MultiModalData CheckTypeAndCreate(AIContent item)
{
@@ -124,7 +124,7 @@ public struct MultiModalData
{
return new MultiModalData(text);
}
else if (item is ImageContent image)
else if (item is DataContent image)
{
return new MultiModalData(image);
}
@@ -155,10 +155,10 @@ public struct MultiModalData
}

/// <summary>
/// Initializes a new instance of the <see cref="MultiModalData"/> with an <see cref="ImageContent"/>.
/// Initializes a new instance of the <see cref="MultiModalData"/> with an <see cref="DataContent"/>.
/// </summary>
/// <param name="image">The image to wrap.</param>
public MultiModalData(ImageContent image)
public MultiModalData(DataContent image)
{
ContentType = Type.Image;
AIContent = image;
@@ -246,12 +246,12 @@ public class MultiModalMessage : ChatMessage, IList<AIContent>
}

/// <summary>
/// Adds a range of <see cref="ImageContent"/> to the message.
/// Adds a range of <see cref="DataContent"/> to the message.
/// </summary>
/// <param name="images">The items to add.</param>
public void AddRange(IEnumerable<ImageContent> images)
public void AddRange(IEnumerable<DataContent> images)
{
foreach (ImageContent image in images)
foreach (DataContent image in images)
{
this.Add(image);
}
@@ -279,7 +279,7 @@ public class MultiModalMessage : ChatMessage, IList<AIContent>
/// Adds a <see cref="TextContent"/> to the message.
/// </summary>
/// <param name="image">The image to add.</param>
public void Add(ImageContent image)
public void Add(DataContent image)
{
this.Content.Add(new(image));
}
@@ -366,7 +366,7 @@ public class MultiModalMessage : ChatMessage, IList<AIContent>
}

/// <inheritdoc cref="IList{ImageContent}.Insert(int, ImageContent)"/>
public void Insert(int index, ImageContent image)
public void Insert(int index, DataContent image)
{
this.Content.Insert(index, new(image));
}
@@ -597,7 +597,7 @@ public static class CompletionChatMessageExtensions
{
contentBuilder.AppendLine(textContent.Text);
}
else if (content is ImageContent)
else if (content is DataContent)
{
contentBuilder.AppendLine("[Image]");
}


+ 4
- 4
dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Tasks.cs View File

@@ -59,7 +59,7 @@ public interface ITaskRunner
/// <param name="task">The task definition in text form.</param>
/// <param name="cancellationToken"></param>
/// <returns>The result of running the task.</returns>
async ValueTask<TaskResult> RunAsync(string task, CancellationToken cancellationToken = default) =>
public async ValueTask<TaskResult> RunAsync(string task, CancellationToken cancellationToken = default) =>
await this.RunAsync(ToMessage(task)!, cancellationToken);

/// <summary>
@@ -73,7 +73,7 @@ public interface ITaskRunner
/// <param name="cancellationToken"></param>
/// <returns>The result of running the task.</returns>
/// <exception cref="InvalidOperationException">If no response is generated.</exception>
async ValueTask<TaskResult> RunAsync(ChatMessage task, CancellationToken cancellationToken = default)
public async ValueTask<TaskResult> RunAsync(ChatMessage task, CancellationToken cancellationToken = default)
{
await foreach (TaskFrame frame in this.StreamAsync(task, cancellationToken))
{
@@ -98,7 +98,7 @@ public interface ITaskRunner
/// <param name="cancellationToken"></param>
/// <returns>A stream of <see cref="TaskFrame"/> containing internal messages and intermediate results followed by
/// the final <see cref="TaskResult"/></returns>
IAsyncEnumerable<TaskFrame> StreamAsync(string task, CancellationToken cancellationToken = default) =>
public IAsyncEnumerable<TaskFrame> StreamAsync(string task, CancellationToken cancellationToken = default) =>
this.StreamAsync(ToMessage(task), cancellationToken);

/// <summary>
@@ -113,5 +113,5 @@ public interface ITaskRunner
/// <param name="cancellationToken"></param>
/// <returns>A stream of <see cref="TaskFrame"/> containing internal messages and intermediate results followed by
/// the final <see cref="TaskResult"/></returns>
IAsyncEnumerable<TaskFrame> StreamAsync(ChatMessage? task, CancellationToken cancellationToken = default);
public IAsyncEnumerable<TaskFrame> StreamAsync(ChatMessage? task, CancellationToken cancellationToken = default);
}

+ 5
- 5
dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Termination.cs View File

@@ -19,7 +19,7 @@ public interface ITerminationCondition
/// <summary>
/// Checks if the termination condition has been reached
/// </summary>
bool IsTerminated { get; }
public bool IsTerminated { get; }

/// <summary>
/// Check if the conversation should be terminated based on the messages received
@@ -30,19 +30,19 @@ public interface ITerminationCondition
/// <returns>A <see cref="StopMessage"/> if the conversation should be terminated, or <c>null</c>
/// otherwise.</returns>
/// <exception cref="TerminatedException">If the termination condition has already been reached.</exception>
ValueTask<StopMessage?> CheckAndUpdateAsync(IList<AgentMessage> messages);
public ValueTask<StopMessage?> CheckAndUpdateAsync(IList<AgentMessage> messages);

/// <summary>
/// Resets the termination condition.
/// </summary>
void Reset();
public void Reset();

/// <summary>
/// Combine this termination condition with another using a logical OR.
/// </summary>
/// <param name="other">Another termination condition.</param>
/// <returns>The combined termination condition, with appropriate short-circuiting.</returns>
ITerminationCondition Or(ITerminationCondition other)
public ITerminationCondition Or(ITerminationCondition other)
{
return new CombinerCondition(CombinerCondition.Or, this, other);
}
@@ -52,7 +52,7 @@ public interface ITerminationCondition
/// </summary>
/// <param name="other">Another termination condition.</param>
/// <returns>The combined termination condition, with appropriate short-circuiting.</returns>
ITerminationCondition And(ITerminationCondition other)
public ITerminationCondition And(ITerminationCondition other)
{
return new CombinerCondition(CombinerCondition.And, this, other);
}


+ 6
- 68
dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Tools.cs View File

@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Tools.cs

using System.ComponentModel;
using System.Reflection;
using Microsoft.Extensions.AI;

@@ -10,37 +9,6 @@ namespace Microsoft.AutoGen.AgentChat.Abstractions;
// TODO: This likely should live as a "Component" in an Agent-building ClassLib?
// It seems like it could have applicability beyond AgentChat.

public static class ReflectionExtensions
{
public static AIFunctionParameterMetadata ToAIFunctionMetadata(this ParameterInfo pi)
{
return new AIFunctionParameterMetadata(pi.Name!)
{
Description = pi.GetCustomAttribute<DescriptionAttribute>()?.Description,

ParameterType = pi.ParameterType,

HasDefaultValue = pi.HasDefaultValue,
IsRequired = !pi.HasDefaultValue,
DefaultValue = pi.DefaultValue,

// Schema = JSONSchema of type
};
}

public static AIFunctionReturnParameterMetadata ToAIFunctionReturnMetadata(this ParameterInfo rpi)
{
return new AIFunctionReturnParameterMetadata
{
Description = rpi.GetCustomAttribute<DescriptionAttribute>()?.Description,

ParameterType = rpi.ParameterType

//Schema = JSONSchema of type
};
}
}

public class ParameterSchema(string name, Type type, bool isRequired = false, object? defaultValue = default)
{
public string Name { get; } = name;
@@ -54,15 +22,6 @@ public class ParameterSchema(string name, Type type, bool isRequired = false, ob
Type parameterType = parameterInfo.ParameterType;
return ParameterSchema<object>.Create(parameterType, parameterInfo.Name!, parameterInfo.HasDefaultValue, parameterInfo.DefaultValue);
}

public static implicit operator ParameterSchema(AIFunctionParameterMetadata parameterMetadata)
{
Type parameterType = parameterMetadata.ParameterType!; // TODO: Deal with missing ParameterTypes
return ParameterSchema<object>.Create(parameterType,
parameterMetadata.Name,
parameterMetadata.IsRequired,
parameterMetadata.DefaultValue);
}
}

// TODO: Can this be obviated by AIFunctionParameter?
@@ -82,11 +41,10 @@ public class ParameterSchema<T>(string name, bool isRequired = false, T? default
/// </summary>
public interface ITool
{
string Name { get; }
string Description { get; }
public string Name { get; }
public string Description { get; }

public IEnumerable<ParameterSchema> Parameters { get; }
public Type ReturnType { get; }

// TODO: State serialization

@@ -136,18 +94,15 @@ public class AIFunctionTool(AIFunction aiFunction) : ITool
public AIFunction AIFunction { get; } = aiFunction;

/// <inheritdoc cref="ITool.Name" />
public string Name => this.AIFunction.Metadata.Name;
public string Name => this.AIFunction.Name;

/// <inheritdoc cref="ITool.Description" />
public string Description => this.AIFunction.Metadata.Description;
public string Description => this.AIFunction.Description;

/// <inheritdoc cref="ITool.Parameters" />
public IEnumerable<ParameterSchema> Parameters => from rawParameter in this.AIFunction.Metadata.Parameters
public IEnumerable<ParameterSchema> Parameters => from rawParameter in this.AIFunction.UnderlyingMethod!.GetParameters()
select (ParameterSchema)rawParameter;

/// <inheritdoc cref="ITool.ReturnType" />
public Type ReturnType => this.AIFunction.Metadata.ReturnParameter.ParameterType!; // TODO: Deal with missing return types

/// <inheritdoc cref="ITool.ExecuteAsync" />
public Task<object> ExecuteAsync(IEnumerable<object> parameters, CancellationToken cancellationToken = default)
=> this.ExecuteAsync(parameters, cancellationToken);
@@ -164,23 +119,6 @@ public class CallableTool(string name, string description, Delegate callable)
{
internal static AIFunction CreateAIFunction(string name, string description, Delegate callable)
{
MethodInfo methodInfo = callable.Method;

IEnumerable<AIFunctionParameterMetadata> parameters =
from parameterInfo in methodInfo.GetParameters()
select parameterInfo.ToAIFunctionMetadata();

AIFunctionReturnParameterMetadata returnParameter = methodInfo.ReturnParameter.ToAIFunctionReturnMetadata();

AIFunctionFactoryCreateOptions createOptions = new()
{
Name = name,
Description = description,
Parameters = parameters.ToList(),
ReturnParameter = returnParameter,
// SerializerOptions = TODO: How do we maintain consistency with Python?
};

return AIFunctionFactory.Create(callable, createOptions);
return AIFunctionFactory.Create(callable, name: name, description: description);
}
}

+ 1
- 1
dotnet/src/Microsoft.AutoGen/AgentChat/GroupChat/GroupChatBase.cs View File

@@ -114,7 +114,7 @@ public abstract class GroupChatBase<TManager> : ITeam where TManager : GroupChat
if (Activator.CreateInstance(typeof(TManager), options) is TManager result)
{
return result;
};
}
}
catch (TargetInvocationException tie)
{


+ 2
- 2
dotnet/src/Microsoft.AutoGen/AgentChat/GroupChat/GroupChatHandlerRouter.cs View File

@@ -11,8 +11,8 @@ internal delegate ValueTask MessagePublishServicer(GroupChatEventBase event_, st

internal interface IGroupChatHandler : IHandle<GroupChatStart>, IHandle<GroupChatAgentResponse>, IHandle<object>
{
void AttachMessagePublishServicer(MessagePublishServicer? servicer = null);
void DetachMessagePublishServicer() => this.AttachMessagePublishServicer(null);
public void AttachMessagePublishServicer(MessagePublishServicer? servicer = null);
public void DetachMessagePublishServicer() => this.AttachMessagePublishServicer(null);
}

internal sealed class GroupChatHandlerRouter<TManager> : HostableAgentAdapter,


+ 2
- 2
dotnet/src/Microsoft.AutoGen/AgentChat/GroupChat/OutputCollectorAgent.cs View File

@@ -11,8 +11,8 @@ namespace Microsoft.AutoGen.AgentChat.Abstractions;

internal interface IOutputCollectionSink
{
void CollectMessage(AgentMessage message);
void Terminate(StopMessage message);
public void CollectMessage(AgentMessage message);
public void Terminate(StopMessage message);
}

internal sealed class OutputSink : IOutputCollectionSink


+ 4
- 4
dotnet/src/Microsoft.AutoGen/Agents/AIAgent/InferenceAgent.cs View File

@@ -26,19 +26,19 @@ public abstract class InferenceAgent<T>(
{
protected IChatClient ChatClient { get; } = client;
private ILogger<InferenceAgent<T>>? Logger => _logger as ILogger<InferenceAgent<T>>;
private Task<ChatCompletion> CompleteAsync(
private Task<ChatResponse> CompleteAsync(
IList<ChatMessage> chatMessages,
ChatOptions? options = null,
CancellationToken cancellationToken = default)
{
return ChatClient.CompleteAsync(chatMessages, options, cancellationToken);
return ChatClient.GetResponseAsync(chatMessages, options, cancellationToken);
}
private IAsyncEnumerable<StreamingChatCompletionUpdate> CompleteStreamingAsync(
private IAsyncEnumerable<ChatResponseUpdate> CompleteStreamingAsync(
IList<ChatMessage> chatMessages,
ChatOptions? options = null,
CancellationToken cancellationToken = default)
{
return ChatClient.CompleteStreamingAsync(chatMessages, options, cancellationToken);
return ChatClient.GetStreamingResponseAsync(chatMessages, options, cancellationToken);
}

}

+ 3
- 2
dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcMessageRouter.cs View File

@@ -43,7 +43,7 @@ internal sealed class AutoRestartChannel : IDisposable
if (this.RecreateChannel(null) == null)
{
throw new Exception("Failed to connect to gRPC endpoint.");
};
}
}

public AsyncDuplexStreamingCall<Message, Message> StreamingCall
@@ -117,8 +117,9 @@ internal sealed class GrpcMessageRouter(AgentRpc.AgentRpcClient client,
private readonly CancellationTokenSource _shutdownCts = CancellationTokenSource.CreateLinkedTokenSource(shutdownCancellation);

private readonly IMessageSink<Message> _incomingMessageSink = incomingMessageSink;

// TODO: Enable a way to configure the channel options
private readonly Channel<(Message Message, TaskCompletionSource WriteCompletionSource)> _outboundMessagesChannel
// TODO: Enable a way to configure the channel options
= Channel.CreateBounded<(Message, TaskCompletionSource)>(DefaultChannelOptions);

private readonly AutoRestartChannel _incomingMessageChannel = new AutoRestartChannel(client, clientId, logger, shutdownCancellation);


+ 4
- 4
dotnet/src/Microsoft.AutoGen/Core/ResultSink.cs View File

@@ -7,11 +7,11 @@ namespace Microsoft.AutoGen.Core;

internal interface IResultSink<TResult> : IValueTaskSource<TResult>
{
void SetResult(TResult result);
void SetException(Exception exception);
void SetCancelled();
public void SetResult(TResult result);
public void SetException(Exception exception);
public void SetCancelled();

ValueTask<TResult> Future { get; }
public ValueTask<TResult> Future { get; }
}

public sealed class ResultSink<TResult> : IResultSink<TResult>


+ 16
- 16
dotnet/src/Microsoft.AutoGen/Extensions/MEAI/ServiceCollectionChatCompletionExtensions.cs View File

@@ -41,12 +41,13 @@ public static class ServiceCollectionChatClientExtensions
Func<ChatClientBuilder, ChatClientBuilder>? builder = null)
{
uri ??= new Uri("http://localhost:11434");
return services.AddChatClient(pipeline =>
services.AddChatClient(service =>
{
builder?.Invoke(pipeline);
var httpClient = pipeline.Services.GetService<HttpClient>() ?? new();
return pipeline.Use(new OllamaChatClient(uri, modelName, httpClient));
var httpClient = service.GetService<HttpClient>() ?? new();
return new OllamaChatClient(uri, modelName, httpClient);
});

return services;
}
public static IServiceCollection AddOpenAIChatClient(
this IHostApplicationBuilder hostBuilder,
@@ -81,16 +82,17 @@ public static class ServiceCollectionChatClientExtensions
Uri? endpoint = null,
Func<ChatClientBuilder, ChatClientBuilder>? builder = null)
{
return services
services
.AddSingleton(_ => endpoint is null
? new OpenAIClient(apiKey)
: new AzureOpenAIClient(endpoint, new ApiKeyCredential(apiKey)))
.AddChatClient(pipeline =>
.AddChatClient(service =>
{
builder?.Invoke(pipeline);
var openAiClient = pipeline.Services.GetRequiredService<OpenAIClient>();
return pipeline.Use(openAiClient.AsChatClient(modelOrDeploymentName));
var openAiClient = service.GetRequiredService<OpenAIClient>();
return openAiClient.AsChatClient(modelOrDeploymentName);
});

return services;
}
public static IServiceCollection AddAzureChatClient(
this IHostApplicationBuilder hostBuilder,
@@ -109,12 +111,10 @@ public static class ServiceCollectionChatClientExtensions
}
var endpoint = $"{serviceName}:Endpoint" ?? throw new InvalidOperationException($"No endpoint was specified for the Azure Inference Chat Client");
var endpointUri = string.IsNullOrEmpty(endpoint) ? null : new Uri(endpoint);
return hostBuilder.Services.AddChatClient(pipeline =>
{
builder?.Invoke(pipeline);
var token = Environment.GetEnvironmentVariable("GH_TOKEN") ?? throw new InvalidOperationException("No model access token was found in the environment variable GH_TOKEN");
return pipeline.Use(new ChatCompletionsClient(
endpointUri, new AzureKeyCredential(token)).AsChatClient(modelOrDeploymentName));
});
var token = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? throw new InvalidOperationException("No model access token was found in the environment variable AZURE_OPENAI_API_KEY");
var chatClient = new ChatCompletionsClient(endpointUri, new AzureKeyCredential(token)).AsChatClient(modelOrDeploymentName);
hostBuilder.Services.AddChatClient(chatClient);

return hostBuilder.Services;
}
}

+ 1
- 1
dotnet/src/Microsoft.AutoGen/RuntimeGateway.Grpc/Services/Grpc/GrpcGateway.cs View File

@@ -243,7 +243,7 @@ public sealed class GrpcGateway : BackgroundService, IGateway
default:
await RespondBadRequestAsync(connection, $"Unknown message type for message '{message}'.");
break;
};
}
}

/// <summary>


+ 1
- 1
dotnet/test/AutoGen.AotCompatibility.Tests/AutoGen.AotCompatibility.Tests.csproj View File

@@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>


+ 36
- 0
dotnet/test/AutoGen.OpenAI.Tests/ApprovalTests/OpenAIMessageTests.BasicMessageTest.approved.txt View File

@@ -12,6 +12,12 @@
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
@@ -31,6 +37,12 @@
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
@@ -57,6 +69,12 @@
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
@@ -78,6 +96,12 @@
"ImageUri": "https://example.com/image.png",
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
@@ -104,6 +128,12 @@
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
},
@@ -113,6 +143,12 @@
"ImageUri": "https://example.com/image.png",
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}


+ 260
- 0
dotnet/test/AutoGen.OpenAI.Tests/ApprovalTests/OpenAIMessageTests.BasicMessageTest.received.txt View File

@@ -0,0 +1,260 @@
[
{
"OriginalMessage": "TextMessage(system, You are a helpful AI assistant, )",
"ConvertedMessages": [
{
"Name": null,
"Role": "system",
"Content": [
{
"Kind": 0,
"Text": "You are a helpful AI assistant",
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
]
}
]
},
{
"OriginalMessage": "TextMessage(user, Hello, user)",
"ConvertedMessages": [
{
"Role": "user",
"Content": [
{
"Kind": 0,
"Text": "Hello",
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
],
"Name": "user",
"MultiModaItem": [
{
"Type": "Text",
"Text": "Hello"
}
]
}
]
},
{
"OriginalMessage": "TextMessage(assistant, How can I help you?, assistant)",
"ConvertedMessages": [
{
"Role": "assistant",
"Content": [
{
"Kind": 0,
"Text": "How can I help you?",
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
],
"Name": "assistant",
"TooCall": []
}
]
},
{
"OriginalMessage": "ImageMessage(user, https://example.com/image.png, user)",
"ConvertedMessages": [
{
"Role": "user",
"Content": [
{
"Kind": 2,
"Text": null,
"ImageUri": "https://example.com/image.png",
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
],
"Name": "user",
"MultiModaItem": [
{
"Type": "Image",
"ImageUrl": "https://example.com/image.png"
}
]
}
]
},
{
"OriginalMessage": "MultiModalMessage(assistant, user)\n\tTextMessage(user, Hello, user)\n\tImageMessage(user, https://example.com/image.png, user)",
"ConvertedMessages": [
{
"Role": "user",
"Content": [
{
"Kind": 0,
"Text": "Hello",
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
},
{
"Kind": 2,
"Text": null,
"ImageUri": "https://example.com/image.png",
"ImageBytes": null,
"ImageBytesMediaType": null,
"InputAudioBytes": null,
"InputAudioFormat": null,
"FileId": null,
"FileBytes": null,
"FileBytesMediaType": null,
"Filename": null,
"ImageDetailLevel": null,
"Refusal": null
}
],
"Name": "user",
"MultiModaItem": [
{
"Type": "Text",
"Text": "Hello"
},
{
"Type": "Image",
"ImageUrl": "https://example.com/image.png"
}
]
}
]
},
{
"OriginalMessage": "ToolCallMessage(assistant)\n\tToolCall(test, test, )",
"ConvertedMessages": [
{
"Role": "assistant",
"Content": [],
"Name": null,
"TooCall": [
{
"Type": "Function",
"Name": "test",
"Arguments": "dGVzdA==",
"Id": "test"
}
]
}
]
},
{
"OriginalMessage": "ToolCallResultMessage(user)\n\tToolCall(test, test, result)",
"ConvertedMessages": [
{
"Role": "tool",
"Content": "result",
"ToolCallId": "test"
}
]
},
{
"OriginalMessage": "ToolCallResultMessage(user)\n\tToolCall(result, test, test)\n\tToolCall(result, test, test)",
"ConvertedMessages": [
{
"Role": "tool",
"Content": "test",
"ToolCallId": "result_0"
},
{
"Role": "tool",
"Content": "test",
"ToolCallId": "result_1"
}
]
},
{
"OriginalMessage": "ToolCallMessage(assistant)\n\tToolCall(test, test, )\n\tToolCall(test, test, )",
"ConvertedMessages": [
{
"Role": "assistant",
"Content": [],
"Name": null,
"TooCall": [
{
"Type": "Function",
"Name": "test",
"Arguments": "dGVzdA==",
"Id": "test_0"
},
{
"Type": "Function",
"Name": "test",
"Arguments": "dGVzdA==",
"Id": "test_1"
}
]
}
]
},
{
"OriginalMessage": "AggregateMessage(assistant)\n\tToolCallMessage(assistant)\n\tToolCall(test, test, )\n\tToolCallResultMessage(assistant)\n\tToolCall(test, test, result)",
"ConvertedMessages": [
{
"Role": "assistant",
"Content": [],
"Name": null,
"TooCall": [
{
"Type": "Function",
"Name": "test",
"Arguments": "dGVzdA==",
"Id": "test"
}
]
},
{
"Role": "tool",
"Content": "result",
"ToolCallId": "test"
}
]
}
]

+ 1
- 1
dotnet/test/AutoGen.Tests/Function/FunctionTests.cs View File

@@ -60,7 +60,7 @@ public class FunctionTests
GetWeatherAsyncStatic,
];

var functionContracts = availableDelegates.Select(function => (FunctionContract)AIFunctionFactory.Create(function).Metadata).ToList();
var functionContracts = availableDelegates.Select(function => (FunctionContract)AIFunctionFactory.Create(function)).ToList();

// Verify the function contracts
functionContracts.Should().HaveCount(4);


+ 1
- 1
dotnet/test/AutoGen.Tests/MiddlewareTest.cs View File

@@ -72,7 +72,7 @@ public partial class MiddlewareTest
public async Task FunctionCallMiddlewareTestAsync()
{
var agent = new EchoAgent("echo");
var args = new EchoSchema { message = "hello" };
var args = new EchoSchema { message = "hello" }; // make the format check happy on linux
var argsJson = JsonSerializer.Serialize(args) ?? throw new InvalidOperationException("Failed to serialize args");
var functionCall = new ToolCall("Echo", argsJson);
var functionCallAgent = agent.RegisterMiddleware(async (messages, options, agent, ct) =>


+ 1
- 1
dotnet/test/Microsoft.AutoGen.Core.Grpc.Tests/TestGrpcWorkerConnection.cs View File

@@ -92,7 +92,7 @@ internal sealed class TestGrpcWorkerConnection : IAsyncDisposable
default:
// if it wasn't recognized return bad request
throw new RpcException(new Status(StatusCode.InvalidArgument, $"Unknown message type for message '{message}'"));
};
}
}
}
catch (OperationCanceledException)


Loading…
Cancel
Save