Skip to content

Commit

Permalink
Merge pull request #1676 from microsoft/u/xiaoyun/dotnet/message
Browse files Browse the repository at this point in the history
[.Net] Bring Semantic-Kernel to AutoGen && Propose a new message abstraction to support multi-modal/parallel function call && potential breaking change from openai api
  • Loading branch information
LittleLittleCloud committed Mar 3, 2024
2 parents 25498f6 + 222a57c commit e12a824
Show file tree
Hide file tree
Showing 114 changed files with 4,329 additions and 1,364 deletions.
3 changes: 0 additions & 3 deletions dotnet/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,6 @@ dotnet_diagnostic.IDE0005.severity = error
# IDE0069: Remove unused local variable
dotnet_diagnostic.IDE0069.severity = error

# IDE0060: Remove unused parameter
dotnet_diagnostic.IDE0060.severity = warning

# disable CS1573: Parameter has no matching param tag in the XML comment for
dotnet_diagnostic.CS1573.severity = none

Expand Down
23 changes: 22 additions & 1 deletion dotnet/AutoGen.sln
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{FBFEAD
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.DotnetInteractive", "src\AutoGen.DotnetInteractive\AutoGen.DotnetInteractive.csproj", "{B61D8008-7FB7-4C0E-8044-3A74AA63A596}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.LMStudio", "src\AutoGen.LMStudio\AutoGen.LMStudio.csproj", "{F98BDA9B-8657-4BA8-9B03-BAEA454CAE60}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.LMStudio", "src\AutoGen.LMStudio\AutoGen.LMStudio.csproj", "{F98BDA9B-8657-4BA8-9B03-BAEA454CAE60}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.SemanticKernel", "src\AutoGen.SemanticKernel\AutoGen.SemanticKernel.csproj", "{45D6FC80-36F3-4967-9663-E20B63824621}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.Core", "src\AutoGen.Core\AutoGen.Core.csproj", "{D58D43D1-0617-4A3D-9932-C773E6398535}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoGen.OpenAI", "src\AutoGen.OpenAI\AutoGen.OpenAI.csproj", "{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -57,6 +63,18 @@ Global
{F98BDA9B-8657-4BA8-9B03-BAEA454CAE60}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F98BDA9B-8657-4BA8-9B03-BAEA454CAE60}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F98BDA9B-8657-4BA8-9B03-BAEA454CAE60}.Release|Any CPU.Build.0 = Release|Any CPU
{45D6FC80-36F3-4967-9663-E20B63824621}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{45D6FC80-36F3-4967-9663-E20B63824621}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45D6FC80-36F3-4967-9663-E20B63824621}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45D6FC80-36F3-4967-9663-E20B63824621}.Release|Any CPU.Build.0 = Release|Any CPU
{D58D43D1-0617-4A3D-9932-C773E6398535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D58D43D1-0617-4A3D-9932-C773E6398535}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D58D43D1-0617-4A3D-9932-C773E6398535}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D58D43D1-0617-4A3D-9932-C773E6398535}.Release|Any CPU.Build.0 = Release|Any CPU
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -69,6 +87,9 @@ Global
{7EBF916A-A7B1-4B74-AF10-D705B7A18F58} = {FBFEAD1F-29EB-4D99-A672-0CD8473E10B9}
{B61D8008-7FB7-4C0E-8044-3A74AA63A596} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{F98BDA9B-8657-4BA8-9B03-BAEA454CAE60} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{45D6FC80-36F3-4967-9663-E20B63824621} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{D58D43D1-0617-4A3D-9932-C773E6398535} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{63445BB7-DBB9-4AEF-9D6F-98BBE75EE1EC} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {93384647-528D-46C8-922C-8DB36A382F0B}
Expand Down
2 changes: 2 additions & 0 deletions dotnet/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<NoWarn>$(NoWarn);$(CSNoWarn);NU5104</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<IsPackable>false</IsPackable>
<EnableNetAnalyzers>true</EnableNetAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>

<PropertyGroup>
Expand Down
4 changes: 2 additions & 2 deletions dotnet/eng/MetaInfo.props
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VersionPrefix>0.0.8</VersionPrefix>
<VersionPrefix>0.0.9</VersionPrefix>
<Authors>AutoGen</Authors>
<PackageProjectUrl>https://github.com/microsoft/autogen</PackageProjectUrl>
<PackageProjectUrl>https://microsoft.github.io/autogen-for-net/</PackageProjectUrl>
<RepositoryUrl>https://github.com/microsoft/autogen</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
7 changes: 4 additions & 3 deletions dotnet/eng/Version.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AzureOpenAIVersion>1.0.0-beta.12</AzureOpenAIVersion>
<SemanticKernelVersion>1.0.1</SemanticKernelVersion>
<AzureOpenAIVersion>1.0.0-beta.13</AzureOpenAIVersion>
<SemanticKernelVersion>1.5.0</SemanticKernelVersion>
<SemanticKernelExperimentalVersion>1.5.0-alpha</SemanticKernelExperimentalVersion>
<SystemCodeDomVersion>5.0.0</SystemCodeDomVersion>
<MicrosoftCodeAnalysisVersion>4.3.0</MicrosoftCodeAnalysisVersion>
<ApprovalTestVersion>5.2.4</ApprovalTestVersion>
<ApprovalTestVersion>6.0.0</ApprovalTestVersion>
<FluentAssertionVersion>6.8.0</FluentAssertionVersion>
<XUnitVersion>2.4.2</XUnitVersion>
<MicrosoftNETTestSdkVersion>17.7.0</MicrosoftNETTestSdkVersion>
Expand Down
2 changes: 1 addition & 1 deletion dotnet/global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.101",
"rollForward": "latestMajor"
"rollForward": "latestMinor"
}
}
5 changes: 5 additions & 0 deletions dotnet/nuget/NUGET.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
## AutoGen
#### Update on 0.0.9 (2024-03-02)
- Refactor over @AutoGen.Message and introducing `TextMessage`, `ImageMessage`, `MultiModalMessage` and so on. PR [#1676](https://github.com/microsoft/autogen/pull/1676)
- Add `AutoGen.SemanticKernel` to support seamless integration with Semantic Kernel
- Move the agent contract abstraction to `AutoGen.Core` package. The `AutoGen.Core` package provides the abstraction for message type, agent and group chat and doesn't contain dependencies over `Azure.AI.OpenAI` or `Semantic Kernel`. This is useful when you want to leverage AutoGen's abstraction only and want to avoid introducing any other dependencies.
- Move `GPTAgent`, `OpenAIChatAgent` and all openai-dependencies to `AutoGen.OpenAI`
#### Update on 0.0.8 (2024-02-28)
- Fix [#1804](https://github.com/microsoft/autogen/pull/1804)
- Streaming support for IAgent [#1656](https://github.com/microsoft/autogen/pull/1656)
Expand Down
4 changes: 2 additions & 2 deletions dotnet/sample/AutoGen.BasicSamples/AutoGen.BasicSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<NoWarn>$(NoWarn);CS8981;CS8600;CS8602;CS8604;CS8618;CS0219</NoWarn>
<NoWarn>$(NoWarn);CS8981;CS8600;CS8602;CS8604;CS8618;CS0219;SKEXP0054</NoWarn>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\AutoGen.DotnetInteractive\AutoGen.DotnetInteractive.csproj" />
<ProjectReference Include="..\..\src\AutoGen.LMStudio\AutoGen.LMStudio.csproj" />
<ProjectReference Include="..\..\src\AutoGen.SourceGenerator\AutoGen.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\src\AutoGen\AutoGen.csproj" />
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionVersion)" />
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Web" Version="$(SemanticKernelExperimentalVersion)" />
</ItemGroup>
</Project>
19 changes: 12 additions & 7 deletions dotnet/sample/AutoGen.BasicSamples/CodeSnippet/CreateAnAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,17 @@ public async Task CodeSnippet4()
{
llmConfig
},
FunctionDefinitions = new[]
FunctionContracts = new[]
{
this.UpperCaseFunction, // The FunctionDefinition object for the UpperCase function
this.UpperCaseFunctionContract, // The FunctionDefinition object for the UpperCase function
},
});

var response = await assistantAgent.SendAsync("hello");
response.FunctionName.Should().Be("UpperCase");
response.Content.Should().BeNullOrEmpty();
response.Should().BeOfType<ToolCallMessage>();
var toolCallMessage = (ToolCallMessage)response;
toolCallMessage.ToolCalls.Count().Should().Be(1);
toolCallMessage.ToolCalls.First().FunctionName.Should().Be("UpperCase");
#endregion code_snippet_4
}

Expand All @@ -119,9 +121,9 @@ public async Task CodeSnippet5()
{
llmConfig
},
FunctionDefinitions = new[]
FunctionContracts = new[]
{
this.UpperCaseFunction, // The FunctionDefinition object for the UpperCase function
this.UpperCaseFunctionContract, // The FunctionDefinition object for the UpperCase function
},
},
functionMap: new Dictionary<string, Func<string, Task<string>>>
Expand All @@ -130,7 +132,10 @@ public async Task CodeSnippet5()
});

var response = await assistantAgent.SendAsync("hello");
response.Content.Should().Be("HELLO");
response.Should().BeOfType<TextMessage>();
response.From.Should().Be("assistant");
var textMessage = (TextMessage)response;
textMessage.Content.Should().Be("HELLO");
#endregion code_snippet_5
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using AutoGen;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;
using FluentAssertions;

public partial class FunctionCallCodeSnippet
Expand All @@ -30,15 +29,18 @@ public async Task CodeSnippet4()
{
llmConfig
},
FunctionDefinitions = new[]
FunctionContracts = new[]
{
function.WeatherReportFunctionContract.ToOpenAIFunctionDefinition(), // The FunctionDefinition object for the weather report function
function.WeatherReportFunctionContract,
},
});

var response = await assistantAgent.SendAsync("hello What's the weather in Seattle today? today is 2024-01-01");
response.FunctionName.Should().Be("WeatherReport");
response.FunctionArguments.Should().Be(@"{""location"":""Seattle"",""date"":""2024-01-01""}");
response.Should().BeOfType<ToolCallMessage>();
var toolCallMessage = (ToolCallMessage)response;
toolCallMessage.ToolCalls.Count().Should().Be(1);
toolCallMessage.ToolCalls[0].FunctionName.Should().Be("WeatherReport");
toolCallMessage.ToolCalls[0].FunctionArguments.Should().Be(@"{""location"":""Seattle"",""date"":""2024-01-01""}");
#endregion code_snippet_4
}

Expand All @@ -64,9 +66,9 @@ public async Task CodeSnippet6()
{
llmConfig
},
FunctionDefinitions = new[]
FunctionContracts = new[]
{
function.WeatherReportFunctionContract.ToOpenAIFunctionDefinition(), // The FunctionDefinition object for the weather report function
function.WeatherReportFunctionContract,
},
},
functionMap: new Dictionary<string, Func<string, Task<string>>>
Expand All @@ -78,7 +80,9 @@ public async Task CodeSnippet6()

#region code_snippet_6_1
var response = await assistantAgent.SendAsync("What's the weather in Seattle today? today is 2024-01-01");
response.Content.Should().Be("Weather report for Seattle on 2024-01-01 is sunny");
response.Should().BeOfType<TextMessage>();
var textMessage = (TextMessage)response;
textMessage.Content.Should().Be("Weather report for Seattle on 2024-01-01 is sunny");
#endregion code_snippet_6_1
}

Expand All @@ -95,9 +99,9 @@ public async Task TwoAgentWeatherChatTestAsync()
llmConfig: new ConversableAgentConfig
{
ConfigList = new[] { config },
FunctionDefinitions = new[]
FunctionContracts = new[]
{
function.WeatherReportFunctionContract.ToOpenAIFunctionDefinition(),
function.WeatherReportFunctionContract,
},
});

Expand All @@ -111,4 +115,4 @@ public async Task TwoAgentWeatherChatTestAsync()
await user.InitiateChatAsync(assistant, "what's weather in Seattle today, today is 2024-01-01", 10);
#endregion two_agent_weather_chat
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,56 @@ public async Task CodeSnippet1()
// Since no middleware is added, middlewareAgent will simply proxy into the inner agent to generate reply.
var reply = await middlewareAgent.SendAsync("Hello World");
reply.From.Should().Be("assistant");
reply.Content.Should().Be("Hello World");
reply.GetContent().Should().Be("Hello World");
#endregion code_snippet_1

#region code_snippet_2
middlewareAgent.Use(async (messages, options, agent, ct) =>
{
var lastMessage = messages.Last();
var lastMessage = messages.Last() as TextMessage;
lastMessage.Content = $"[middleware 0] {lastMessage.Content}";
return await agent.GenerateReplyAsync(messages, options, ct);
});

reply = await middlewareAgent.SendAsync("Hello World");
reply.Content.Should().Be("[middleware 0] Hello World");
reply.Should().BeOfType<TextMessage>();
var textReply = (TextMessage)reply;
textReply.Content.Should().Be("[middleware 0] Hello World");
#endregion code_snippet_2
#region code_snippet_2_1
middlewareAgent = agent.RegisterMiddleware(async (messages, options, agnet, ct) =>
{
var lastMessage = messages.Last();
var lastMessage = messages.Last() as TextMessage;
lastMessage.Content = $"[middleware 0] {lastMessage.Content}";
return await agent.GenerateReplyAsync(messages, options, ct);
});

reply = await middlewareAgent.SendAsync("Hello World");
reply.Content.Should().Be("[middleware 0] Hello World");
reply.GetContent().Should().Be("[middleware 0] Hello World");
#endregion code_snippet_2_1
#region code_snippet_3
middlewareAgent.Use(async (messages, options, agent, ct) =>
{
var lastMessage = messages.Last();
var lastMessage = messages.Last() as TextMessage;
lastMessage.Content = $"[middleware 1] {lastMessage.Content}";
return await agent.GenerateReplyAsync(messages, options, ct);
});

reply = await middlewareAgent.SendAsync("Hello World");
reply.Content.Should().Be("[middleware 0] [middleware 1] Hello World");
reply.GetContent().Should().Be("[middleware 0] [middleware 1] Hello World");
#endregion code_snippet_3

#region code_snippet_4
middlewareAgent.Use(async (messages, options, next, ct) =>
{
var lastMessage = messages.Last();
var lastMessage = messages.Last() as TextMessage;
lastMessage.Content = $"[middleware shortcut]";
return lastMessage;
});

reply = await middlewareAgent.SendAsync("Hello World");
reply.Content.Should().Be("[middleware shortcut]");
reply.GetContent().Should().Be("[middleware shortcut]");
#endregion code_snippet_4

#region retrieve_inner_agent
Expand All @@ -92,7 +94,7 @@ public async Task CodeSnippet1()
var reply = await agent.GenerateReplyAsync(messages, options, ct);
while (maxAttempt-- > 0)
{
if (JsonSerializer.Deserialize<Dictionary<string, object>>(reply.Content) is { } dict)
if (JsonSerializer.Deserialize<Dictionary<string, object>>(reply.GetContent()) is { } dict)
{
return reply;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// TypeSafeFunctionCallCodeSnippet.cs

using System.Text.Json;
using AutoGen;
using AutoGen.OpenAI.Extension;
using Azure.AI.OpenAI;

Expand Down
18 changes: 9 additions & 9 deletions dotnet/sample/AutoGen.BasicSamples/Example01_AssistantAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Example01_AssistantAgent.cs

using AutoGen;
using AutoGen.BasicSample;
using FluentAssertions;
using autogen = AutoGen.LLMConfigAPI;

/// <summary>
/// This example shows the basic usage of <see cref="ConversableAgent"/> class.
Expand All @@ -12,13 +12,11 @@ public static class Example01_AssistantAgent
{
public static async Task RunAsync()
{
// get OpenAI Key and create config
var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
var llmConfig = autogen.GetOpenAIConfigList(openAIKey, new[] { "gpt-3.5-turbo" });
var gpt35 = LLMConfiguration.GetAzureOpenAIGPT3_5_Turbo();
var config = new ConversableAgentConfig
{
Temperature = 0,
ConfigList = llmConfig,
ConfigList = [gpt35],
};

// create assistant agent
Expand All @@ -30,16 +28,18 @@ public static async Task RunAsync()

// talk to the assistant agent
var reply = await assistantAgent.SendAsync("hello world");
reply.Content?.Should().Be("HELLO WORLD");
reply.Should().BeOfType<TextMessage>();
reply.GetContent().Should().Be("HELLO WORLD");

// to carry on the conversation, pass the previous conversation history to the next call
var conversationHistory = new List<Message>
var conversationHistory = new List<IMessage>
{
new Message(Role.User, "hello world"), // first message
new TextMessage(Role.User, "hello world"), // first message
reply, // reply from assistant agent
};

reply = await assistantAgent.SendAsync("hello world again", conversationHistory);
reply.Content?.Should().Be("HELLO WORLD AGAIN");
reply.Should().BeOfType<TextMessage>();
reply.GetContent().Should().Be("HELLO WORLD AGAIN");
}
}
Loading

0 comments on commit e12a824

Please sign in to comment.