mirror of https://github.com/microsoft/autogen.git
[.Net] Add KernelPluginMiddleware in AutoGen.SemanticKernel (#2595)
* add kernel function middleware * update * fix format * fix build error
This commit is contained in:
parent
648dad5c40
commit
374270f9c7
|
@ -29,9 +29,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Core", "src\AutoGen
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.OpenAI", "src\AutoGen.OpenAI\AutoGen.OpenAI.csproj", "{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.Mistral", "src\AutoGen.Mistral\AutoGen.Mistral.csproj", "{6585D1A4-3D97-4D76-A688-1933B61AEB19}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Mistral", "src\AutoGen.Mistral\AutoGen.Mistral.csproj", "{6585D1A4-3D97-4D76-A688-1933B61AEB19}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.Mistral.Tests", "test\AutoGen.Mistral.Tests\AutoGen.Mistral.Tests.csproj", "{15441693-3659-4868-B6C1-B106F52FF3BA}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Mistral.Tests", "test\AutoGen.Mistral.Tests\AutoGen.Mistral.Tests.csproj", "{15441693-3659-4868-B6C1-B106F52FF3BA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.SemanticKernel.Tests", "test\AutoGen.SemanticKernel.Tests\AutoGen.SemanticKernel.Tests.csproj", "{1DFABC4A-8458-4875-8DCB-59F3802DAC65}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -87,6 +89,10 @@ Global
|
|||
{15441693-3659-4868-B6C1-B106F52FF3BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{15441693-3659-4868-B6C1-B106F52FF3BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{15441693-3659-4868-B6C1-B106F52FF3BA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1DFABC4A-8458-4875-8DCB-59F3802DAC65}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -104,6 +110,7 @@ Global
|
|||
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{6585D1A4-3D97-4D76-A688-1933B61AEB19} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{15441693-3659-4868-B6C1-B106F52FF3BA} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
|
||||
{1DFABC4A-8458-4875-8DCB-59F3802DAC65} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {93384647-528D-46C8-922C-8DB36A382F0B}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.12</VersionPrefix>
|
||||
<VersionPrefix>0.0.13</VersionPrefix>
|
||||
<Authors>AutoGen</Authors>
|
||||
<PackageProjectUrl>https://microsoft.github.io/autogen-for-net/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/microsoft/autogen</RepositoryUrl>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// MiddlewareAgentCodeSnippet.cs
|
||||
|
||||
using AutoGen.Core;
|
||||
using System.Text.Json;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.OpenAI;
|
||||
using FluentAssertions;
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// MistralAICodeSnippet.cs
|
||||
|
||||
#region using_statement
|
||||
using AutoGen.Mistral;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.Mistral;
|
||||
using AutoGen.Mistral.Extension;
|
||||
using FluentAssertions;
|
||||
#endregion using_statement
|
||||
|
@ -83,4 +83,4 @@ internal class MistralAICodeSnippet
|
|||
reply.GetContent().Should().Be("The weather in Seattle is sunny.");
|
||||
#endregion send_message_with_function_call
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Example01_AssistantAgent.cs
|
||||
|
||||
using AutoGen.Core;
|
||||
using AutoGen;
|
||||
using AutoGen.BasicSample;
|
||||
using AutoGen.Core;
|
||||
using FluentAssertions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Example02_TwoAgent_MathChat.cs
|
||||
|
||||
using AutoGen.Core;
|
||||
using AutoGen;
|
||||
using AutoGen.BasicSample;
|
||||
using AutoGen.Core;
|
||||
using FluentAssertions;
|
||||
public static class Example02_TwoAgent_MathChat
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Example03_Agent_FunctionCall.cs
|
||||
|
||||
using AutoGen;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.BasicSample;
|
||||
using AutoGen.Core;
|
||||
using FluentAssertions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Example04_Dynamic_GroupChat_Coding_Task.cs
|
||||
|
||||
using AutoGen;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.BasicSample;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.DotnetInteractive;
|
||||
using AutoGen.OpenAI;
|
||||
using FluentAssertions;
|
||||
|
|
|
@ -5,8 +5,8 @@ using System.Text;
|
|||
using System.Text.Json;
|
||||
using AutoGen;
|
||||
using AutoGen.BasicSample;
|
||||
using AutoGen.DotnetInteractive;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.DotnetInteractive;
|
||||
using AutoGen.OpenAI;
|
||||
using FluentAssertions;
|
||||
|
||||
|
|
|
@ -62,4 +62,4 @@ public class Example14_MistralClientAgent_TokenCount
|
|||
tokenCounterMiddleware.GetCompletionTokenCount().Should().BeGreaterThan(0);
|
||||
#endregion chat_with_agent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Example15_ImageMessage.cs
|
||||
// Example15_GPT4V_BinaryDataImageMessage.cs
|
||||
|
||||
using AutoGen.Core;
|
||||
using AutoGen.OpenAI;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// ChatCompletionResponse.cs
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Error.cs
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Model.cs
|
||||
|
||||
using System;
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>AutoGen.SemanticKernel</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);SKEXP0110</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// KernelExtension.cs
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.SemanticKernel;
|
||||
|
||||
namespace AutoGen.SemanticKernel.Extension;
|
||||
|
@ -11,4 +12,37 @@ public static class KernelExtension
|
|||
{
|
||||
return new SemanticKernelAgent(kernel, name, systemMessage, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a <see cref="KernelFunctionMetadata"/> to a <see cref="FunctionContract"/>
|
||||
/// </summary>
|
||||
/// <param name="metadata">kernel function metadata</param>
|
||||
public static FunctionContract ToFunctionContract(this KernelFunctionMetadata metadata)
|
||||
{
|
||||
return new FunctionContract()
|
||||
{
|
||||
Name = metadata.Name,
|
||||
Description = metadata.Description,
|
||||
Parameters = metadata.Parameters.Select(p => p.ToFunctionParameterContract()).ToList(),
|
||||
ReturnType = metadata.ReturnParameter.ParameterType,
|
||||
ReturnDescription = metadata.ReturnParameter.Description,
|
||||
ClassName = metadata.PluginName,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a <see cref="KernelParameterMetadata"/> to a <see cref="FunctionParameterContract"/>
|
||||
/// </summary>
|
||||
/// <param name="metadata">kernel parameter metadata</param>
|
||||
public static FunctionParameterContract ToFunctionParameterContract(this KernelParameterMetadata metadata)
|
||||
{
|
||||
return new FunctionParameterContract()
|
||||
{
|
||||
Name = metadata.Name,
|
||||
Description = metadata.Description,
|
||||
DefaultValue = metadata.DefaultValue,
|
||||
IsRequired = metadata.IsRequired,
|
||||
ParameterType = metadata.ParameterType,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// KernelPluginMiddleware.cs
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoGen.SemanticKernel.Extension;
|
||||
using Microsoft.SemanticKernel;
|
||||
|
||||
namespace AutoGen.SemanticKernel;
|
||||
|
||||
/// <summary>
|
||||
/// A middleware that consumes <see cref="KernelPlugin"/>
|
||||
/// </summary>
|
||||
public class KernelPluginMiddleware : IMiddleware
|
||||
{
|
||||
private readonly KernelPlugin _kernelPlugin;
|
||||
private readonly FunctionCallMiddleware _functionCallMiddleware;
|
||||
public string? Name => nameof(KernelPluginMiddleware);
|
||||
|
||||
public KernelPluginMiddleware(Kernel kernel, KernelPlugin kernelPlugin)
|
||||
{
|
||||
_kernelPlugin = kernelPlugin;
|
||||
var functionContracts = kernelPlugin.Select(k => k.Metadata.ToFunctionContract());
|
||||
var functionMap = kernelPlugin.ToDictionary(kv => kv.Metadata.Name, kv => InvokeFunctionPartial(kernel, kv));
|
||||
_functionCallMiddleware = new FunctionCallMiddleware(functionContracts, functionMap, Name);
|
||||
}
|
||||
|
||||
public Task<IMessage> InvokeAsync(MiddlewareContext context, IAgent agent, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _functionCallMiddleware.InvokeAsync(context, agent, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<string> InvokeFunctionAsync(Kernel kernel, KernelFunction function, string arguments)
|
||||
{
|
||||
var kernelArguments = new KernelArguments();
|
||||
var parameters = function.Metadata.Parameters;
|
||||
var jsonObject = JsonSerializer.Deserialize<JsonObject>(arguments) ?? new JsonObject();
|
||||
foreach (var parameter in parameters)
|
||||
{
|
||||
var parameterName = parameter.Name;
|
||||
if (jsonObject.ContainsKey(parameterName))
|
||||
{
|
||||
var parameterType = parameter.ParameterType ?? throw new ArgumentException($"Missing parameter type for {parameterName}");
|
||||
var parameterValue = jsonObject[parameterName];
|
||||
var parameterObject = parameterValue.Deserialize(parameterType);
|
||||
kernelArguments.Add(parameterName, parameterObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parameter.DefaultValue != null)
|
||||
{
|
||||
kernelArguments.Add(parameterName, parameter.DefaultValue);
|
||||
}
|
||||
else if (parameter.IsRequired)
|
||||
{
|
||||
throw new ArgumentException($"Missing required parameter: {parameterName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
var result = await function.InvokeAsync(kernel, kernelArguments);
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private Func<string, Task<string>> InvokeFunctionPartial(Kernel kernel, KernelFunction function)
|
||||
{
|
||||
return async (string args) =>
|
||||
{
|
||||
var result = await InvokeFunctionAsync(kernel, function, args);
|
||||
return result.ToString();
|
||||
};
|
||||
}
|
||||
}
|
|
@ -92,7 +92,7 @@ public partial class MistralClientAgentTests
|
|||
new TextMessage(Role.User, "what's the weather in Seattle?"),
|
||||
new ToolCallMessage(this.GetWeatherFunctionContract.Name!, weatherFunctionArgumets, from: agent.Name),
|
||||
new ToolCallResultMessage(functionCallResult, this.GetWeatherFunctionContract.Name!, weatherFunctionArgumets),
|
||||
];
|
||||
];
|
||||
|
||||
var reply = await agent.SendAsync(chatHistory: chatHistory);
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
[
|
||||
{
|
||||
"Name": "_ItCreateFunctionContractsFromMethod_b__2_0",
|
||||
"Description": "",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
|
||||
"ReturnDescription": ""
|
||||
},
|
||||
{
|
||||
"Name": "_ItCreateFunctionContractsFromMethod_b__2_1",
|
||||
"Description": "",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "message",
|
||||
"Description": "",
|
||||
"ParameterType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
|
||||
"IsRequired": true,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
|
||||
"ReturnDescription": ""
|
||||
}
|
||||
]
|
|
@ -0,0 +1,8 @@
|
|||
[
|
||||
{
|
||||
"Name": "sayHello",
|
||||
"Description": "Generic function, unknown purpose",
|
||||
"Parameters": [],
|
||||
"ReturnDescription": ""
|
||||
}
|
||||
]
|
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
{
|
||||
"ClassName": "test_plugin",
|
||||
"Name": "GetState",
|
||||
"Description": "Gets the state of the light.",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
|
||||
"ReturnDescription": ""
|
||||
},
|
||||
{
|
||||
"ClassName": "test_plugin",
|
||||
"Name": "ChangeState",
|
||||
"Description": "Changes the state of the light.'",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "newState",
|
||||
"Description": "new state",
|
||||
"ParameterType": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
|
||||
"IsRequired": true,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
|
||||
"ReturnDescription": ""
|
||||
}
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TestTargetFramework)</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<IsPackable>false</IsPackable>
|
||||
<NoWarn>$(NoWarn);SKEXP0110</NoWarn>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApprovalTests" Version="$(ApprovalTestVersion)" />
|
||||
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionVersion)" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
|
||||
<PackageReference Include="xunit" Version="$(XUnitVersion)" />
|
||||
<PackageReference Include="xunit.runner.console" Version="$(XUnitVersion)" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\AutoGen.SemanticKernel\AutoGen.SemanticKernel.csproj" />
|
||||
<ProjectReference Include="..\..\src\AutoGen.SourceGenerator\AutoGen.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="..\..\src\AutoGen\AutoGen.csproj" />
|
||||
<ProjectReference Include="..\AutoGen.Tests\AutoGen.Tests.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// KernelFunctionExtensionTests.cs
|
||||
|
||||
using System.ComponentModel;
|
||||
using ApprovalTests;
|
||||
using ApprovalTests.Namers;
|
||||
using ApprovalTests.Reporters;
|
||||
using AutoGen.SemanticKernel.Extension;
|
||||
using FluentAssertions;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace AutoGen.SemanticKernel.Tests;
|
||||
|
||||
public class TestPlugin
|
||||
{
|
||||
public bool IsOn { get; set; } = false;
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Gets the state of the light.")]
|
||||
public string GetState() => this.IsOn ? "on" : "off";
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Changes the state of the light.'")]
|
||||
public string ChangeState(
|
||||
[Description("new state")] bool newState)
|
||||
{
|
||||
this.IsOn = newState;
|
||||
var state = this.GetState();
|
||||
|
||||
// Print the state to the console
|
||||
Console.ForegroundColor = ConsoleColor.DarkBlue;
|
||||
Console.WriteLine($"[Light is now {state}]");
|
||||
Console.ResetColor();
|
||||
|
||||
return $"The status of the light is now {state}";
|
||||
}
|
||||
}
|
||||
public class KernelFunctionExtensionTests
|
||||
{
|
||||
private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
StringEscapeHandling = StringEscapeHandling.Default,
|
||||
};
|
||||
|
||||
[Fact]
|
||||
[UseReporter(typeof(DiffReporter))]
|
||||
[UseApprovalSubdirectory("ApprovalTests")]
|
||||
public void ItCreateFunctionContractsFromTestPlugin()
|
||||
{
|
||||
var kernel = new Kernel();
|
||||
var plugin = kernel.ImportPluginFromType<TestPlugin>("test_plugin");
|
||||
|
||||
var functionContracts = plugin.Select(f => f.Metadata.ToFunctionContract()).ToList();
|
||||
|
||||
functionContracts.Count.Should().Be(2);
|
||||
var json = JsonConvert.SerializeObject(functionContracts, _serializerSettings);
|
||||
|
||||
Approvals.Verify(json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[UseReporter(typeof(DiffReporter))]
|
||||
[UseApprovalSubdirectory("ApprovalTests")]
|
||||
public void ItCreateFunctionContractsFromMethod()
|
||||
{
|
||||
var kernel = new Kernel();
|
||||
var sayHelloFunction = KernelFunctionFactory.CreateFromMethod(() => "Hello, World!");
|
||||
var echoFunction = KernelFunctionFactory.CreateFromMethod((string message) => message);
|
||||
|
||||
var functionContracts = new[]
|
||||
{
|
||||
sayHelloFunction.Metadata.ToFunctionContract(),
|
||||
echoFunction.Metadata.ToFunctionContract(),
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(functionContracts, _serializerSettings);
|
||||
|
||||
functionContracts.Length.Should().Be(2);
|
||||
Approvals.Verify(json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[UseReporter(typeof(DiffReporter))]
|
||||
[UseApprovalSubdirectory("ApprovalTests")]
|
||||
public void ItCreateFunctionContractsFromPrompt()
|
||||
{
|
||||
var kernel = new Kernel();
|
||||
var sayHelloFunction = KernelFunctionFactory.CreateFromPrompt("Say {{hello}}, World!", functionName: "sayHello");
|
||||
|
||||
var functionContracts = new[]
|
||||
{
|
||||
sayHelloFunction.Metadata.ToFunctionContract(),
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(functionContracts, _serializerSettings);
|
||||
|
||||
functionContracts.Length.Should().Be(1);
|
||||
Approvals.Verify(json);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// KernelFunctionMiddlewareTests.cs
|
||||
|
||||
using AutoGen.Core;
|
||||
using AutoGen.OpenAI;
|
||||
using AutoGen.OpenAI.Extension;
|
||||
using AutoGen.Tests;
|
||||
using Azure.AI.OpenAI;
|
||||
using FluentAssertions;
|
||||
using Microsoft.SemanticKernel;
|
||||
|
||||
namespace AutoGen.SemanticKernel.Tests;
|
||||
|
||||
public class KernelFunctionMiddlewareTests
|
||||
{
|
||||
[ApiKeyFact("AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT")]
|
||||
public async Task ItRegisterKernelFunctionMiddlewareFromTestPluginTests()
|
||||
{
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new Exception("Please set AZURE_OPENAI_ENDPOINT environment variable.");
|
||||
var key = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? throw new Exception("Please set AZURE_OPENAI_API_KEY environment variable.");
|
||||
var openaiClient = new OpenAIClient(new Uri(endpoint), new Azure.AzureKeyCredential(key));
|
||||
|
||||
var kernel = new Kernel();
|
||||
var plugin = kernel.ImportPluginFromType<TestPlugin>();
|
||||
var kernelFunctionMiddleware = new KernelPluginMiddleware(kernel, plugin);
|
||||
|
||||
var agent = new OpenAIChatAgent(openaiClient, "assistant", modelName: "gpt-35-turbo-16k")
|
||||
.RegisterMessageConnector()
|
||||
.RegisterMiddleware(kernelFunctionMiddleware);
|
||||
|
||||
var reply = await agent.SendAsync("what's the status of the light?");
|
||||
reply.GetContent().Should().Be("off");
|
||||
reply.Should().BeOfType<AggregateMessage<ToolCallMessage, ToolCallResultMessage>>();
|
||||
if (reply is AggregateMessage<ToolCallMessage, ToolCallResultMessage> aggregateMessage)
|
||||
{
|
||||
var toolCallMessage = aggregateMessage.Message1;
|
||||
toolCallMessage.ToolCalls.Should().HaveCount(1);
|
||||
toolCallMessage.ToolCalls[0].FunctionName.Should().Be("GetState");
|
||||
|
||||
var toolCallResultMessage = aggregateMessage.Message2;
|
||||
toolCallResultMessage.ToolCalls.Should().HaveCount(1);
|
||||
toolCallResultMessage.ToolCalls[0].Result.Should().Be("off");
|
||||
}
|
||||
|
||||
reply = await agent.SendAsync("change the status of the light to on");
|
||||
reply.GetContent().Should().Be("The status of the light is now on");
|
||||
reply.Should().BeOfType<AggregateMessage<ToolCallMessage, ToolCallResultMessage>>();
|
||||
if (reply is AggregateMessage<ToolCallMessage, ToolCallResultMessage> aggregateMessage1)
|
||||
{
|
||||
var toolCallMessage = aggregateMessage1.Message1;
|
||||
toolCallMessage.ToolCalls.Should().HaveCount(1);
|
||||
toolCallMessage.ToolCalls[0].FunctionName.Should().Be("ChangeState");
|
||||
|
||||
var toolCallResultMessage = aggregateMessage1.Message2;
|
||||
toolCallResultMessage.ToolCalls.Should().HaveCount(1);
|
||||
}
|
||||
}
|
||||
|
||||
[ApiKeyFact("AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT")]
|
||||
public async Task ItRegisterKernelFunctionMiddlewareFromMethodTests()
|
||||
{
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new Exception("Please set AZURE_OPENAI_ENDPOINT environment variable.");
|
||||
var key = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? throw new Exception("Please set AZURE_OPENAI_API_KEY environment variable.");
|
||||
var openaiClient = new OpenAIClient(new Uri(endpoint), new Azure.AzureKeyCredential(key));
|
||||
|
||||
var kernel = new Kernel();
|
||||
var getWeatherMethod = kernel.CreateFunctionFromMethod((string location) => $"The weather in {location} is sunny.", functionName: "GetWeather", description: "Get the weather for a location.");
|
||||
var createPersonObjectMethod = kernel.CreateFunctionFromMethod((string name, string email, int age) => new Person(name, email, age), functionName: "CreatePersonObject", description: "Creates a person object.");
|
||||
var plugin = kernel.ImportPluginFromFunctions("plugin", [getWeatherMethod, createPersonObjectMethod]);
|
||||
var kernelFunctionMiddleware = new KernelPluginMiddleware(kernel, plugin);
|
||||
|
||||
var agent = new OpenAIChatAgent(openaiClient, "assistant", modelName: "gpt-35-turbo-16k")
|
||||
.RegisterMessageConnector()
|
||||
.RegisterMiddleware(kernelFunctionMiddleware);
|
||||
|
||||
var reply = await agent.SendAsync("what's the weather in Seattle?");
|
||||
reply.GetContent().Should().Be("The weather in Seattle is sunny.");
|
||||
reply.Should().BeOfType<AggregateMessage<ToolCallMessage, ToolCallResultMessage>>();
|
||||
if (reply is AggregateMessage<ToolCallMessage, ToolCallResultMessage> getWeatherMessage)
|
||||
{
|
||||
var toolCallMessage = getWeatherMessage.Message1;
|
||||
toolCallMessage.ToolCalls.Should().HaveCount(1);
|
||||
toolCallMessage.ToolCalls[0].FunctionName.Should().Be("GetWeather");
|
||||
|
||||
var toolCallResultMessage = getWeatherMessage.Message2;
|
||||
toolCallResultMessage.ToolCalls.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
reply = await agent.SendAsync("Create a person object with name: John, email: 12345@gmail.com, age: 30");
|
||||
reply.GetContent().Should().Be("Name: John, Email: 12345@gmail.com, Age: 30");
|
||||
reply.Should().BeOfType<AggregateMessage<ToolCallMessage, ToolCallResultMessage>>();
|
||||
if (reply is AggregateMessage<ToolCallMessage, ToolCallResultMessage> createPersonObjectMessage)
|
||||
{
|
||||
var toolCallMessage = createPersonObjectMessage.Message1;
|
||||
toolCallMessage.ToolCalls.Should().HaveCount(1);
|
||||
toolCallMessage.ToolCalls[0].FunctionName.Should().Be("CreatePersonObject");
|
||||
|
||||
var toolCallResultMessage = createPersonObjectMessage.Message2;
|
||||
toolCallResultMessage.ToolCalls.Should().HaveCount(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Person
|
||||
{
|
||||
public Person(string name, string email, int age)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Email = email;
|
||||
this.Age = age;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public int Age { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Name: {this.Name}, Email: {this.Email}, Age: {this.Age}";
|
||||
}
|
||||
}
|
|
@ -1,18 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SemanticKernelAgentTest.cs
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AutoGen.SemanticKernel;
|
||||
using AutoGen.Core;
|
||||
using AutoGen.SemanticKernel.Extension;
|
||||
using AutoGen.Tests;
|
||||
using FluentAssertions;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
|
||||
namespace AutoGen.Tests;
|
||||
namespace AutoGen.SemanticKernel.Tests;
|
||||
|
||||
public partial class SemanticKernelAgentTest
|
||||
{
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// globalUsing.cs
|
||||
// GlobalUsing.cs
|
||||
|
||||
global using AutoGen.Core;
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
##### Update
|
||||
###### New features
|
||||
- [Issue 2593](https://github.com/microsoft/autogen/issues/2593) In AutoGen.SemanticKernel, add `KernelPluginMiddleware` to support consume semantic kernel plugin in `IAgent`.
|
||||
|
||||
###### API Breaking Changes
|
||||
- [API Breaking Change] Update the return type of `IStreamingAgent.GenerateStreamingReplyAsync` from `Task<IAsyncEnumerable<IStreamingMessage>>` to `IAsyncEnumerable<IStreamingMessage>`
|
||||
- [API Breaking Change] Update the return type of `IStreamingMiddleware.InvokeAsync` from `Task<IAsyncEnumerable<IStreamingMessage>>` to `IAsyncEnumerable<IStreamingMessage>`
|
||||
- [API Breaking Change] Mark `RegisterReply`, `RegisterPreProcess` and `RegisterPostProcess` as obsolete. You can replace them with `RegisterMiddleware`
|
||||
|
||||
###### Bug Fixes
|
||||
- Fix [Issue 2609](https://github.com/microsoft/autogen/issues/2609)
|
||||
##### Update on 0.0.12 (2024-04-22)
|
||||
- Add AutoGen.Mistral package to support Mistral.AI models
|
||||
|
|
Loading…
Reference in New Issue