Skip to content

Commit 374270f

Browse files
[.Net] Add KernelPluginMiddleware in AutoGen.SemanticKernel (#2595)
* add kernel function middleware * update * fix format * fix build error
1 parent 648dad5 commit 374270f

27 files changed

+455
-26
lines changed

dotnet/AutoGen.sln

+9-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Core", "src\AutoGen
2929
EndProject
3030
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.OpenAI", "src\AutoGen.OpenAI\AutoGen.OpenAI.csproj", "{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}"
3131
EndProject
32-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.Mistral", "src\AutoGen.Mistral\AutoGen.Mistral.csproj", "{6585D1A4-3D97-4D76-A688-1933B61AEB19}"
32+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Mistral", "src\AutoGen.Mistral\AutoGen.Mistral.csproj", "{6585D1A4-3D97-4D76-A688-1933B61AEB19}"
3333
EndProject
34-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.Mistral.Tests", "test\AutoGen.Mistral.Tests\AutoGen.Mistral.Tests.csproj", "{15441693-3659-4868-B6C1-B106F52FF3BA}"
34+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Mistral.Tests", "test\AutoGen.Mistral.Tests\AutoGen.Mistral.Tests.csproj", "{15441693-3659-4868-B6C1-B106F52FF3BA}"
35+
EndProject
36+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.SemanticKernel.Tests", "test\AutoGen.SemanticKernel.Tests\AutoGen.SemanticKernel.Tests.csproj", "{1DFABC4A-8458-4875-8DCB-59F3802DAC65}"
3537
EndProject
3638
Global
3739
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -87,6 +89,10 @@ Global
8789
{15441693-3659-4868-B6C1-B106F52FF3BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
8890
{15441693-3659-4868-B6C1-B106F52FF3BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
8991
{15441693-3659-4868-B6C1-B106F52FF3BA}.Release|Any CPU.Build.0 = Release|Any CPU
92+
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
93+
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Debug|Any CPU.Build.0 = Debug|Any CPU
94+
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Release|Any CPU.ActiveCfg = Release|Any CPU
95+
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Release|Any CPU.Build.0 = Release|Any CPU
9096
EndGlobalSection
9197
GlobalSection(SolutionProperties) = preSolution
9298
HideSolutionNode = FALSE
@@ -104,6 +110,7 @@ Global
104110
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
105111
{6585D1A4-3D97-4D76-A688-1933B61AEB19} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
106112
{15441693-3659-4868-B6C1-B106F52FF3BA} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
113+
{1DFABC4A-8458-4875-8DCB-59F3802DAC65} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
107114
EndGlobalSection
108115
GlobalSection(ExtensibilityGlobals) = postSolution
109116
SolutionGuid = {93384647-528D-46C8-922C-8DB36A382F0B}

dotnet/eng/MetaInfo.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<PropertyGroup>
4-
<VersionPrefix>0.0.12</VersionPrefix>
4+
<VersionPrefix>0.0.13</VersionPrefix>
55
<Authors>AutoGen</Authors>
66
<PackageProjectUrl>https://microsoft.github.io/autogen-for-net/</PackageProjectUrl>
77
<RepositoryUrl>https://github.com/microsoft/autogen</RepositoryUrl>

dotnet/sample/AutoGen.BasicSamples/CodeSnippet/MiddlewareAgentCodeSnippet.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// MiddlewareAgentCodeSnippet.cs
33

4-
using AutoGen.Core;
54
using System.Text.Json;
5+
using AutoGen.Core;
66
using AutoGen.OpenAI;
77
using FluentAssertions;
88

dotnet/sample/AutoGen.BasicSamples/CodeSnippet/MistralAICodeSnippet.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// MistralAICodeSnippet.cs
33

44
#region using_statement
5-
using AutoGen.Mistral;
65
using AutoGen.Core;
6+
using AutoGen.Mistral;
77
using AutoGen.Mistral.Extension;
88
using FluentAssertions;
99
#endregion using_statement
@@ -83,4 +83,4 @@ public async Task MistralAIChatAgentGetWeatherToolUsageAsync()
8383
reply.GetContent().Should().Be("The weather in Seattle is sunny.");
8484
#endregion send_message_with_function_call
8585
}
86-
}
86+
}

dotnet/sample/AutoGen.BasicSamples/Example01_AssistantAgent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Example01_AssistantAgent.cs
33

4-
using AutoGen.Core;
54
using AutoGen;
65
using AutoGen.BasicSample;
6+
using AutoGen.Core;
77
using FluentAssertions;
88

99
/// <summary>

dotnet/sample/AutoGen.BasicSamples/Example02_TwoAgent_MathChat.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Example02_TwoAgent_MathChat.cs
33

4-
using AutoGen.Core;
54
using AutoGen;
65
using AutoGen.BasicSample;
6+
using AutoGen.Core;
77
using FluentAssertions;
88
public static class Example02_TwoAgent_MathChat
99
{

dotnet/sample/AutoGen.BasicSamples/Example03_Agent_FunctionCall.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Example03_Agent_FunctionCall.cs
33

44
using AutoGen;
5-
using AutoGen.Core;
65
using AutoGen.BasicSample;
6+
using AutoGen.Core;
77
using FluentAssertions;
88

99
/// <summary>

dotnet/sample/AutoGen.BasicSamples/Example04_Dynamic_GroupChat_Coding_Task.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Example04_Dynamic_GroupChat_Coding_Task.cs
33

44
using AutoGen;
5-
using AutoGen.Core;
65
using AutoGen.BasicSample;
6+
using AutoGen.Core;
77
using AutoGen.DotnetInteractive;
88
using AutoGen.OpenAI;
99
using FluentAssertions;

dotnet/sample/AutoGen.BasicSamples/Example07_Dynamic_GroupChat_Calculate_Fibonacci.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
using System.Text.Json;
66
using AutoGen;
77
using AutoGen.BasicSample;
8-
using AutoGen.DotnetInteractive;
98
using AutoGen.Core;
9+
using AutoGen.DotnetInteractive;
1010
using AutoGen.OpenAI;
1111
using FluentAssertions;
1212

dotnet/sample/AutoGen.BasicSamples/Example14_MistralClientAgent_TokenCount.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ public static async Task RunAsync()
6262
tokenCounterMiddleware.GetCompletionTokenCount().Should().BeGreaterThan(0);
6363
#endregion chat_with_agent
6464
}
65-
}
65+
}

dotnet/sample/AutoGen.BasicSamples/Example15_GPT4V_BinaryDataImageMessage.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
2-
// Example15_ImageMessage.cs
2+
// Example15_GPT4V_BinaryDataImageMessage.cs
33

44
using AutoGen.Core;
55
using AutoGen.OpenAI;

dotnet/src/AutoGen.Mistral/DTOs/ChatCompletionResponse.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// ChatCompletionResponse.cs
33

44
using System.Collections.Generic;

dotnet/src/AutoGen.Mistral/DTOs/Error.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Error.cs
33

44
using System.Text.Json.Serialization;

dotnet/src/AutoGen.Mistral/DTOs/Model.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Model.cs
33

44
using System;

dotnet/src/AutoGen.SemanticKernel/AutoGen.SemanticKernel.csproj

-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<RootNamespace>AutoGen.SemanticKernel</RootNamespace>
6-
</PropertyGroup>
7-
8-
<PropertyGroup>
96
<NoWarn>$(NoWarn);SKEXP0110</NoWarn>
107
</PropertyGroup>
118

dotnet/src/AutoGen.SemanticKernel/Extension/KernelExtension.cs

+34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// KernelExtension.cs
33

4+
using System.Linq;
45
using Microsoft.SemanticKernel;
56

67
namespace AutoGen.SemanticKernel.Extension;
@@ -11,4 +12,37 @@ public static SemanticKernelAgent ToSemanticKernelAgent(this Kernel kernel, stri
1112
{
1213
return new SemanticKernelAgent(kernel, name, systemMessage, settings);
1314
}
15+
16+
/// <summary>
17+
/// Convert a <see cref="KernelFunctionMetadata"/> to a <see cref="FunctionContract"/>
18+
/// </summary>
19+
/// <param name="metadata">kernel function metadata</param>
20+
public static FunctionContract ToFunctionContract(this KernelFunctionMetadata metadata)
21+
{
22+
return new FunctionContract()
23+
{
24+
Name = metadata.Name,
25+
Description = metadata.Description,
26+
Parameters = metadata.Parameters.Select(p => p.ToFunctionParameterContract()).ToList(),
27+
ReturnType = metadata.ReturnParameter.ParameterType,
28+
ReturnDescription = metadata.ReturnParameter.Description,
29+
ClassName = metadata.PluginName,
30+
};
31+
}
32+
33+
/// <summary>
34+
/// Convert a <see cref="KernelParameterMetadata"/> to a <see cref="FunctionParameterContract"/>
35+
/// </summary>
36+
/// <param name="metadata">kernel parameter metadata</param>
37+
public static FunctionParameterContract ToFunctionParameterContract(this KernelParameterMetadata metadata)
38+
{
39+
return new FunctionParameterContract()
40+
{
41+
Name = metadata.Name,
42+
Description = metadata.Description,
43+
DefaultValue = metadata.DefaultValue,
44+
IsRequired = metadata.IsRequired,
45+
ParameterType = metadata.ParameterType,
46+
};
47+
}
1448
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// KernelPluginMiddleware.cs
3+
4+
using System;
5+
using System.Linq;
6+
using System.Text.Json;
7+
using System.Text.Json.Nodes;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
using AutoGen.SemanticKernel.Extension;
11+
using Microsoft.SemanticKernel;
12+
13+
namespace AutoGen.SemanticKernel;
14+
15+
/// <summary>
16+
/// A middleware that consumes <see cref="KernelPlugin"/>
17+
/// </summary>
18+
public class KernelPluginMiddleware : IMiddleware
19+
{
20+
private readonly KernelPlugin _kernelPlugin;
21+
private readonly FunctionCallMiddleware _functionCallMiddleware;
22+
public string? Name => nameof(KernelPluginMiddleware);
23+
24+
public KernelPluginMiddleware(Kernel kernel, KernelPlugin kernelPlugin)
25+
{
26+
_kernelPlugin = kernelPlugin;
27+
var functionContracts = kernelPlugin.Select(k => k.Metadata.ToFunctionContract());
28+
var functionMap = kernelPlugin.ToDictionary(kv => kv.Metadata.Name, kv => InvokeFunctionPartial(kernel, kv));
29+
_functionCallMiddleware = new FunctionCallMiddleware(functionContracts, functionMap, Name);
30+
}
31+
32+
public Task<IMessage> InvokeAsync(MiddlewareContext context, IAgent agent, CancellationToken cancellationToken = default)
33+
{
34+
return _functionCallMiddleware.InvokeAsync(context, agent, cancellationToken);
35+
}
36+
37+
private async Task<string> InvokeFunctionAsync(Kernel kernel, KernelFunction function, string arguments)
38+
{
39+
var kernelArguments = new KernelArguments();
40+
var parameters = function.Metadata.Parameters;
41+
var jsonObject = JsonSerializer.Deserialize<JsonObject>(arguments) ?? new JsonObject();
42+
foreach (var parameter in parameters)
43+
{
44+
var parameterName = parameter.Name;
45+
if (jsonObject.ContainsKey(parameterName))
46+
{
47+
var parameterType = parameter.ParameterType ?? throw new ArgumentException($"Missing parameter type for {parameterName}");
48+
var parameterValue = jsonObject[parameterName];
49+
var parameterObject = parameterValue.Deserialize(parameterType);
50+
kernelArguments.Add(parameterName, parameterObject);
51+
}
52+
else
53+
{
54+
if (parameter.DefaultValue != null)
55+
{
56+
kernelArguments.Add(parameterName, parameter.DefaultValue);
57+
}
58+
else if (parameter.IsRequired)
59+
{
60+
throw new ArgumentException($"Missing required parameter: {parameterName}");
61+
}
62+
}
63+
}
64+
var result = await function.InvokeAsync(kernel, kernelArguments);
65+
66+
return result.ToString();
67+
}
68+
69+
private Func<string, Task<string>> InvokeFunctionPartial(Kernel kernel, KernelFunction function)
70+
{
71+
return async (string args) =>
72+
{
73+
var result = await InvokeFunctionAsync(kernel, function, args);
74+
return result.ToString();
75+
};
76+
}
77+
}

dotnet/test/AutoGen.Mistral.Tests/MistralClientAgentTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public async Task MistralAgentFunctionCallMessageTest()
9292
new TextMessage(Role.User, "what's the weather in Seattle?"),
9393
new ToolCallMessage(this.GetWeatherFunctionContract.Name!, weatherFunctionArgumets, from: agent.Name),
9494
new ToolCallResultMessage(functionCallResult, this.GetWeatherFunctionContract.Name!, weatherFunctionArgumets),
95-
];
95+
];
9696

9797
var reply = await agent.SendAsync(chatHistory: chatHistory);
9898

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[
2+
{
3+
"Name": "_ItCreateFunctionContractsFromMethod_b__2_0",
4+
"Description": "",
5+
"Parameters": [],
6+
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
7+
"ReturnDescription": ""
8+
},
9+
{
10+
"Name": "_ItCreateFunctionContractsFromMethod_b__2_1",
11+
"Description": "",
12+
"Parameters": [
13+
{
14+
"Name": "message",
15+
"Description": "",
16+
"ParameterType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
17+
"IsRequired": true,
18+
"DefaultValue": ""
19+
}
20+
],
21+
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
22+
"ReturnDescription": ""
23+
}
24+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"Name": "sayHello",
4+
"Description": "Generic function, unknown purpose",
5+
"Parameters": [],
6+
"ReturnDescription": ""
7+
}
8+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"ClassName": "test_plugin",
4+
"Name": "GetState",
5+
"Description": "Gets the state of the light.",
6+
"Parameters": [],
7+
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
8+
"ReturnDescription": ""
9+
},
10+
{
11+
"ClassName": "test_plugin",
12+
"Name": "ChangeState",
13+
"Description": "Changes the state of the light.'",
14+
"Parameters": [
15+
{
16+
"Name": "newState",
17+
"Description": "new state",
18+
"ParameterType": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
19+
"IsRequired": true,
20+
"DefaultValue": ""
21+
}
22+
],
23+
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
24+
"ReturnDescription": ""
25+
}
26+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(TestTargetFramework)</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<IsPackable>false</IsPackable>
7+
<NoWarn>$(NoWarn);SKEXP0110</NoWarn>
8+
<GenerateDocumentationFile>True</GenerateDocumentationFile>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="ApprovalTests" Version="$(ApprovalTestVersion)" />
13+
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionVersion)" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
15+
<PackageReference Include="xunit" Version="$(XUnitVersion)" />
16+
<PackageReference Include="xunit.runner.console" Version="$(XUnitVersion)" />
17+
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\src\AutoGen.SemanticKernel\AutoGen.SemanticKernel.csproj" />
22+
<ProjectReference Include="..\..\src\AutoGen.SourceGenerator\AutoGen.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
23+
<ProjectReference Include="..\..\src\AutoGen\AutoGen.csproj" />
24+
<ProjectReference Include="..\AutoGen.Tests\AutoGen.Tests.csproj" />
25+
</ItemGroup>
26+
27+
</Project>

0 commit comments

Comments
 (0)