Compare commits

...

42 Commits

Author SHA1 Message Date
Leonardo Pinheiro 134fa25114
Merge 0b952d4ae1 into f40336fda1 2024-11-04 22:12:52 +00:00
Reuben Bond f40336fda1
Do not exclude Properties or appsettings.json via .gitignore, commit missing files (#4057) 2024-11-04 20:48:46 +01:00
Eric Zhu 16e64c4c10
Rename `model_usage` to `models_usage`. (#4053) 2024-11-04 09:25:53 -08:00
David Luong f46e52e6ff
[.NET] Update version of Microsoft.Extension.Ai & System.Text.Json (#4044)
* Upgrade version of M.E.A.I & STJ

* remove copilot generated comment

* Revert NoWarnDuplicatePackages and remove S.T.J from Directory.Packages.props

---------

Co-authored-by: Xiaoyun Zhang <bigmiao.zhang@gmail.com>
2024-11-04 08:40:53 -05:00
Xiaoyun Zhang 5e0b677acc
[.NET] Create tools from M.E.A.I AIFunctionFactory (#4041)
* add MEAI tool support

* fix format

* update

---------

Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
2024-11-03 09:18:32 -08:00
Eric Zhu 4e5f3ababe
Update version to 0.4.0.dev3 (#4043) 2024-11-01 16:08:09 -07:00
Eric Zhu 4fec22ddc5
Team termination condition sets in the constructor (#4042)
* Termination condition as part of constructor

* Update doc

* Update notebooks
2024-11-01 15:49:37 -07:00
Reuben Bond 7d1857dae6
Clean up the Hello sample, support Aspire 9.0, & fix shutdown in the sample (#4037)
* Wait for acknowledgment when sending message to gRPC channel

* Add CancellationToken parameters to API surface

* Clean up the Hello sample, support Aspire 9.0, & fix shutdown
2024-11-01 15:43:20 -07:00
Eric Zhu 27ea99a485
Add token usage termination (#4035)
* Add token usage termination

* fix test
2024-11-01 15:01:43 -07:00
Eric Zhu ca7caa779d
Add token usage to messages (#4028)
* Add token usage to messages

* small test edit
2024-11-01 13:20:25 -07:00
Reuben Bond e9c16fe22e
Add CancellationToken parameters to API surface (#4036) 2024-11-01 13:17:17 -07:00
Reuben Bond a4901f3ba8
Wait for acknowledgment when sending message to gRPC channel (#4034) 2024-11-01 12:59:50 -07:00
Eric Zhu c3b2597e12
AssistantAgent no longer sends out StopMessage. We use TextMentionTermination("TERMINATE") on the team instead for default setting. (#4030)
* AssistantAgent no longer sends out StopMessage. We use TextMentionTermination("TERMINATE") on the team instead for default setting.

* Fix test
2024-11-01 12:35:26 -07:00
Eric Zhu 173acc6638
Custom selector function for SelectorGroupChat (#4026)
* Custom selector function for SelectorGroupChat

* Update documentation
2024-11-01 09:08:29 -07:00
Eric Zhu 369ffb511b
Remove termination condition from team constructor (#4025)
* Remove termination condition from team constructor

* fix usage
2024-11-01 05:50:20 -07:00
Eric Zhu cff7d842a6
AgentChat streaming API (#4015) 2024-11-01 04:12:43 -07:00
Mohammad Mazraeh 4023454c58
add simple chainlit integration (#3999) 2024-10-31 04:54:24 -07:00
Rohan Thacker 3c63f6f3ef
Corrected typo in get_capabilities in _model_info.py (#4002) 2024-10-30 13:39:45 -07:00
Xiaoyun Zhang 6bea055b26
[.Net] Add a generic `IHandle` interface so AgentRuntime doesn't need to deal with typed handler (#3985)
* add IHandle for object type

* rename handle -> handleObject

* remove duplicate file header setting

* update

* remove AgentId

* fix format
2024-10-30 11:53:37 -07:00
Eric Zhu 3d51ab76ae
Formalize `ChatAgent` response as a dataclass with inner messages (#3990) 2024-10-30 10:27:57 -07:00
Xiaoyun Zhang e63fd17ed5
[.Net] use file-scope (#3997)
* use file-scope

* reformat
2024-10-30 10:05:58 -07:00
Ryan Sweet 51cd5b8d1f
interface inheritance examples (#3989)
changes to AgentBase and HostBuilderExtensions to enable leveraging handlers from composition (interfaces) vs inheritance... see HelloAgents sample for usage

closes #3928
is related to #3925
2024-10-30 09:51:01 -07:00
Leonardo Pinheiro 0b952d4ae1
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-30 09:33:43 +10:00
Leonardo Pinheiro fc5602486a
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-30 08:19:22 +10:00
Leonardo Pinheiro 5116a52ba7 add create collection kwargs 2024-10-29 19:06:29 +10:00
Leonardo Pinheiro d427e0ba93
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-29 10:50:42 +10:00
Leonardo Pinheiro 0eba50a392
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-28 17:36:20 +10:00
Leonardo Pinheiro b3f06724c8 merge main 2024-10-27 11:28:08 +10:00
Leonardo Pinheiro 4391961400 test fix 2024-10-25 17:38:42 +10:00
Leonardo Pinheiro 5745849826 add parallel test setup 2024-10-25 17:23:45 +10:00
Leonardo Pinheiro ab7fd07bc2 fix tests 2024-10-25 15:07:51 +10:00
Leonardo Pinheiro 1a147cbec4
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-25 12:42:35 +10:00
Leonardo Pinheiro 2354a49a80 update tests 2024-10-25 12:41:55 +10:00
Leonardo Pinheiro 299a2eb866 mypy fixes 2024-10-24 17:20:04 +10:00
Leonardo Pinheiro 1d59e51616 update lock file 2024-10-24 16:51:47 +10:00
Leonardo Pinheiro 9fdc30c2db
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-24 16:48:59 +10:00
Leonardo Pinheiro ae4d8aeab4 update shared functions 2024-10-24 16:47:58 +10:00
Leonardo Pinheiro b9b72d6c3a fix pyproject version 2024-10-24 14:33:51 +10:00
Leonardo Pinheiro 4b886b0d54 typing fixes 2024-10-24 14:30:49 +10:00
Leonardo Pinheiro 347fb6034b fix autogen-core dep 2024-10-24 14:30:48 +10:00
Li Jiang f4f3c3ff24
Merge branch 'main' into lpinheiro/feat/add-vectordb-chroma-store 2024-10-24 12:20:06 +08:00
Leonardo Pinheiro 7da80e9361 initial vectordb storage 2024-10-24 07:13:37 +10:00
193 changed files with 5267 additions and 1425 deletions

View File

@ -35,6 +35,7 @@ jobs:
{ ref: "v0.4.0.dev0", dest-dir: "0.4.0.dev0" },
{ ref: "v0.4.0.dev1", dest-dir: "0.4.0.dev1" },
{ ref: "v0.4.0.dev2", dest-dir: "0.4.0.dev2" },
{ ref: "v0.4.0.dev3", dest-dir: "0.4.0.dev3" },
]
steps:
- name: Checkout

View File

@ -101,7 +101,7 @@ We look forward to your contributions!
First install the packages:
```bash
pip install autogen-agentchat==0.4.0.dev2 autogen-ext==0.4.0.dev2
pip install 'autogen-agentchat==0.4.0.dev3' 'autogen-ext[docker]==0.4.0.dev3'
```
The following code uses code execution, you need to have [Docker installed](https://docs.docker.com/engine/install/)
@ -109,17 +109,11 @@ and running on your machine.
```python
import asyncio
import logging
from autogen_agentchat import EVENT_LOGGER_NAME
from autogen_agentchat.agents import CodeExecutorAgent, CodingAssistantAgent
from autogen_agentchat.logging import ConsoleLogHandler
from autogen_agentchat.teams import RoundRobinGroupChat, StopMessageTermination
from autogen_ext.code_executor.docker_executor import DockerCommandLineCodeExecutor
from autogen_ext.models import OpenAIChatCompletionClient
logger = logging.getLogger(EVENT_LOGGER_NAME)
logger.addHandler(ConsoleLogHandler())
logger.setLevel(logging.INFO)
from autogen_agentchat.agents import CodeExecutorAgent, CodingAssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.task import TextMentionTermination
async def main() -> None:
async with DockerCommandLineCodeExecutor(work_dir="coding") as code_executor:
@ -127,11 +121,13 @@ async def main() -> None:
coding_assistant_agent = CodingAssistantAgent(
"coding_assistant", model_client=OpenAIChatCompletionClient(model="gpt-4o", api_key="YOUR_API_KEY")
)
group_chat = RoundRobinGroupChat([coding_assistant_agent, code_executor_agent])
result = await group_chat.run(
task="Create a plot of NVDIA and TSLA stock returns YTD from 2024-01-01 and save it to 'nvidia_tesla_2024_ytd.png'.",
termination_condition=StopMessageTermination(),
termination = TextMentionTermination("TERMINATE")
group_chat = RoundRobinGroupChat([coding_assistant_agent, code_executor_agent], termination_condition=termination)
stream = group_chat.run_stream(
"Create a plot of NVDIA and TSLA stock returns YTD from 2024-01-01 and save it to 'nvidia_tesla_2024_ytd.png'."
)
async for message in stream:
print(message)
asyncio.run(main())
```

View File

@ -21,7 +21,12 @@
{
"name": "0.4.0.dev2",
"version": "0.4.0.dev2",
"url": "/autogen/0.4.0.dev2/",
"url": "/autogen/0.4.0.dev2/"
},
{
"name": "0.4.0.dev3",
"version": "0.4.0.dev3",
"url": "/autogen/0.4.0.dev3/",
"preferred": true
}
]

View File

@ -193,10 +193,6 @@ csharp_using_directive_placement = outside_namespace:error
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
# Header template
file_header_template = Copyright (c) Microsoft Corporation. All rights reserved.\n{fileName}
dotnet_diagnostic.IDE0073.severity = error
# enable format error
dotnet_diagnostic.IDE0055.severity = error
@ -221,13 +217,14 @@ dotnet_diagnostic.IDE0161.severity = warning # Use file-scoped namespace
csharp_style_var_elsewhere = true:suggestion # Prefer 'var' everywhere
csharp_prefer_simple_using_statement = true:suggestion
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_primary_constructors = true:suggestion
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_prefer_local_over_anonymous_function = true:suggestion
dotnet_diagnostic.CA2016.severity = suggestion
csharp_prefer_static_anonymous_function = true:suggestion
# disable check for generated code
[*.generated.cs]
@ -556,8 +553,8 @@ dotnet_diagnostic.IDE0060.severity = warning
dotnet_diagnostic.IDE0062.severity = warning
# IDE0073: File header
dotnet_diagnostic.IDE0073.severity = suggestion
file_header_template = Copyright (c) Microsoft. All rights reserved.
dotnet_diagnostic.IDE0073.severity = warning
file_header_template = Copyright (c) Microsoft Corporation. All rights reserved.\n{fileName}
# IDE1006: Required naming style
dotnet_diagnostic.IDE1006.severity = warning
@ -697,6 +694,7 @@ dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion
dotnet_style_namespace_match_folder = true:suggestion
dotnet_style_qualification_for_method = false:silent
[**/*.g.cs]
generated_code = true

5
dotnet/.gitignore vendored
View File

@ -37,9 +37,6 @@ bld/
# vs code cache
.vscode/
# Properties
Properties/
artifacts/
output/
@ -56,8 +53,6 @@ bld/
[Ll]og/
[Ll]ogs/
appsettings.json
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot

View File

@ -68,6 +68,13 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{243E768F-EA7D-4AF1-B625-0398440BB1AB}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitattributes = .gitattributes
.gitignore = .gitignore
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
Directory.Packages.props = Directory.Packages.props
global.json = global.json
NuGet.config = NuGet.config
spelling.dic = spelling.dic
EndProjectSection
EndProject
@ -123,9 +130,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloAgent", "samples\Hello
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIModelClientHostingExtensions", "src\Microsoft.AutoGen\Extensions\AIModelClientHostingExtensions\AIModelClientHostingExtensions.csproj", "{97550E87-48C6-4EBF-85E1-413ABAE9DBFD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AutoGen.Agents.Tests", "Microsoft.AutoGen.Agents.Tests\Microsoft.AutoGen.Agents.Tests.csproj", "{CF4C92BD-28AE-4B8F-B173-601004AEC9BF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{686480D7-8FEC-4ED3-9C5D-CEBE1057A7ED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloAgentState", "samples\Hello\HelloAgentState\HelloAgentState.csproj", "{64EF61E7-00A6-4E5E-9808-62E10993A0E5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloAgentState", "samples\Hello\HelloAgentState\HelloAgentState.csproj", "{64EF61E7-00A6-4E5E-9808-62E10993A0E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -337,6 +346,10 @@ Global
{97550E87-48C6-4EBF-85E1-413ABAE9DBFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97550E87-48C6-4EBF-85E1-413ABAE9DBFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97550E87-48C6-4EBF-85E1-413ABAE9DBFD}.Release|Any CPU.Build.0 = Release|Any CPU
{CF4C92BD-28AE-4B8F-B173-601004AEC9BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF4C92BD-28AE-4B8F-B173-601004AEC9BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF4C92BD-28AE-4B8F-B173-601004AEC9BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF4C92BD-28AE-4B8F-B173-601004AEC9BF}.Release|Any CPU.Build.0 = Release|Any CPU
{64EF61E7-00A6-4E5E-9808-62E10993A0E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64EF61E7-00A6-4E5E-9808-62E10993A0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64EF61E7-00A6-4E5E-9808-62E10993A0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -401,6 +414,7 @@ Global
{A20B9894-F352-4338-872A-F215A241D43D} = {7EB336C2-7C0A-4BC8-80C6-A3173AB8DC45}
{8F7560CF-EEBB-4333-A69F-838CA40FD85D} = {7EB336C2-7C0A-4BC8-80C6-A3173AB8DC45}
{97550E87-48C6-4EBF-85E1-413ABAE9DBFD} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{CF4C92BD-28AE-4B8F-B173-601004AEC9BF} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
{64EF61E7-00A6-4E5E-9808-62E10993A0E5} = {7EB336C2-7C0A-4BC8-80C6-A3173AB8DC45}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

View File

@ -13,6 +13,7 @@
<CSNoWarn>CS1998;CS1591;CS8002;</CSNoWarn>
<SKEXPNoWarn>SKEXP0001;SKEXP0010;SKEXP0020</SKEXPNoWarn>
<NoWarn>$(NoWarn);$(CSNoWarn);$(SKEXPNoWarn);NU5104</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPackable>false</IsPackable>
@ -32,10 +33,6 @@
<NoWarn>$(NoWarn);CA1829</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" />
</ItemGroup>
<ItemGroup Condition="'$(IsTestProject)' == 'true'">
<PackageReference Include="ApprovalTests" />
<PackageReference Include="FluentAssertions" />

View File

@ -3,7 +3,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<MicrosoftSemanticKernelVersion>1.22.0</MicrosoftSemanticKernelVersion>
<MicrosoftSemanticKernelExperimentalVersion>1.22.0-alpha</MicrosoftSemanticKernelExperimentalVersion>
<MicrosoftExtensionsAIVersion>9.0.0-preview.9.24507.7</MicrosoftExtensionsAIVersion>
<MicrosoftExtensionsAIVersion>9.0.0-preview.9.24525.1</MicrosoftExtensionsAIVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Aspire.Hosting" Version="9.0.0-rc.1.24511.1" />
@ -111,6 +111,5 @@
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Microsoft.PowerShell.SDK" Version="7.4.5" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.10" />
<PackageVersion Include="System.Text.Json" Version="9.0.0-rc.2.24473.5" />
</ItemGroup>
</Project>
</Project>

View File

@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentBaseTests.cs
using FluentAssertions;
using Google.Protobuf.Reflection;
using Microsoft.AutoGen.Abstractions;
using Moq;
using Xunit;
namespace Microsoft.AutoGen.Agents.Tests;
public class AgentBaseTests
{
[Fact]
public async Task ItInvokeRightHandlerTestAsync()
{
var mockContext = new Mock<IAgentContext>();
var agent = new TestAgent(mockContext.Object, new EventTypes(TypeRegistry.Empty, [], []));
await agent.HandleObject("hello world");
await agent.HandleObject(42);
agent.ReceivedItems.Should().HaveCount(2);
agent.ReceivedItems[0].Should().Be("hello world");
agent.ReceivedItems[1].Should().Be(42);
}
/// <summary>
/// The test agent is a simple agent that is used for testing purposes.
/// </summary>
public class TestAgent : AgentBase, IHandle<string>, IHandle<int>
{
public TestAgent(IAgentContext context, EventTypes eventTypes) : base(context, eventTypes)
{
}
public Task Handle(string item)
{
ReceivedItems.Add(item);
return Task.CompletedTask;
}
public Task Handle(int item)
{
ReceivedItems.Add(item);
return Task.CompletedTask;
}
public List<object> ReceivedItems { get; private set; } = [];
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(TestTargetFrameworks)</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsTestProject>True</IsTestProject>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
</ItemGroup>
</Project>

View File

@ -15,5 +15,6 @@
<ProjectReference Include="..\..\src\AutoGen\AutoGen.csproj" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Web" />
<PackageReference Include="Microsoft.Extensions.AI" />
</ItemGroup>
</Project>

View File

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentCodeSnippet.cs
using AutoGen.Core;
namespace AutoGen.BasicSample.CodeSnippet;

View File

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// UserProxyAgentCodeSnippet.cs
using AutoGen.Core;
namespace AutoGen.BasicSample.CodeSnippet;

View File

@ -6,6 +6,7 @@ using AutoGen.Core;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;
using FluentAssertions;
using Microsoft.Extensions.AI;
/// <summary>
/// This example shows how to add type-safe function call to an agent.
@ -37,13 +38,20 @@ public partial class Example03_Agent_FunctionCall
/// </summary>
/// <param name="price">price, should be an integer</param>
/// <param name="taxRate">tax rate, should be in range (0, 1)</param>
[FunctionAttribute]
[Function]
public async Task<string> CalculateTax(int price, float taxRate)
{
return $"tax is {price * taxRate}";
}
public static async Task RunAsync()
/// <summary>
/// This example shows how to add type-safe function call using AutoGen.SourceGenerator.
/// The SourceGenerator will automatically generate FunctionDefinition and FunctionCallWrapper during compiling time.
///
/// For adding type-safe function call from M.E.A.I tools, please refer to <see cref="ToolCallWithMEAITools"/>.
/// </summary>
/// <returns></returns>
public static async Task ToolCallWithSourceGenerator()
{
var instance = new Example03_Agent_FunctionCall();
var gpt4o = LLMConfiguration.GetOpenAIGPT4o_mini();
@ -101,4 +109,60 @@ public partial class Example03_Agent_FunctionCall
// send aggregate message back to llm to get the final result
var finalResult = await agent.SendAsync(calculateTaxes);
}
/// <summary>
/// This example shows how to add type-safe function call from M.E.A.I tools.
///
/// For adding type-safe function call from source generator, please refer to <see cref="ToolCallWithSourceGenerator"/>.
/// </summary>
public static async Task ToolCallWithMEAITools()
{
var gpt4o = LLMConfiguration.GetOpenAIGPT4o_mini();
var instance = new Example03_Agent_FunctionCall();
AIFunction[] tools = [
AIFunctionFactory.Create(instance.UpperCase),
AIFunctionFactory.Create(instance.ConcatString),
AIFunctionFactory.Create(instance.CalculateTax),
];
var toolCallMiddleware = new FunctionCallMiddleware(tools);
var agent = new OpenAIChatAgent(
chatClient: gpt4o,
name: "agent",
systemMessage: "You are a helpful AI assistant")
.RegisterMessageConnector()
.RegisterStreamingMiddleware(toolCallMiddleware)
.RegisterPrintMessage();
// talk to the assistant agent
var upperCase = await agent.SendAsync("convert to upper case: hello world");
upperCase.GetContent()?.Should().Be("HELLO WORLD");
upperCase.Should().BeOfType<ToolCallAggregateMessage>();
upperCase.GetToolCalls().Should().HaveCount(1);
upperCase.GetToolCalls().First().FunctionName.Should().Be(nameof(UpperCase));
var concatString = await agent.SendAsync("concatenate strings: a, b, c, d, e");
concatString.GetContent()?.Should().Be("a b c d e");
concatString.Should().BeOfType<ToolCallAggregateMessage>();
concatString.GetToolCalls().Should().HaveCount(1);
concatString.GetToolCalls().First().FunctionName.Should().Be(nameof(ConcatString));
var calculateTax = await agent.SendAsync("calculate tax: 100, 0.1");
calculateTax.GetContent().Should().Be("tax is 10");
calculateTax.Should().BeOfType<ToolCallAggregateMessage>();
calculateTax.GetToolCalls().Should().HaveCount(1);
calculateTax.GetToolCalls().First().FunctionName.Should().Be(nameof(CalculateTax));
// parallel function calls
var calculateTaxes = await agent.SendAsync("calculate tax: 100, 0.1; calculate tax: 200, 0.2");
calculateTaxes.GetContent().Should().Be("tax is 10\ntax is 40"); // "tax is 10\n tax is 40
calculateTaxes.Should().BeOfType<ToolCallAggregateMessage>();
calculateTaxes.GetToolCalls().Should().HaveCount(2);
calculateTaxes.GetToolCalls().First().FunctionName.Should().Be(nameof(CalculateTax));
// send aggregate message back to llm to get the final result
var finalResult = await agent.SendAsync(calculateTaxes);
}
}

View File

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Example06_UserProxyAgent.cs
using AutoGen.Core;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
//await Example07_Dynamic_GroupChat_Calculate_Fibonacci.RunAsync();
@ -10,7 +11,8 @@ var allSamples = new List<(string, Func<Task>)>
// When a new sample is created please add them to the allSamples collection
("Assistant Agent", Example01_AssistantAgent.RunAsync),
("Two-agent Math Chat", Example02_TwoAgent_MathChat.RunAsync),
("Agent Function Call", Example03_Agent_FunctionCall.RunAsync),
("Agent Function Call With Source Generator", Example03_Agent_FunctionCall.ToolCallWithSourceGenerator),
("Agent Function Call With M.E.A.I AI Functions", Example03_Agent_FunctionCall.ToolCallWithMEAITools),
("Dynamic Group Chat Coding Task", Example04_Dynamic_GroupChat_Coding_Task.RunAsync),
("DALL-E and GPT4v", Example05_Dalle_And_GPT4V.RunAsync),
("User Proxy Agent", Example06_UserProxyAgent.RunAsync),

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Connect_To_Azure_OpenAI.cs
#region using_statement
using System.ClientModel;

View File

@ -0,0 +1,12 @@
{
"profiles": {
"AutoGen.WebAPI.Sample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:50675;http://localhost:50676"
}
}
}

View File

@ -1,14 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
</Project>

View File

@ -1,5 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.Extensions.Hosting;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
var app = await Microsoft.AutoGen.Runtime.Host.StartAsync(local: true);
await app.WaitForShutdownAsync();

View File

@ -0,0 +1,12 @@
{
"profiles": {
"Backend": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:53071;http://localhost:53072"
}
}
}

View File

@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@ -10,12 +9,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost"/>
<PackageReference Include="Aspire.Hosting"/>
<PackageReference Include="Aspire.Hosting.AppHost" />
<PackageReference Include="Aspire.Hosting" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Backend\Backend.csproj" />
<ProjectReference Include="..\HelloAgent\HelloAgent.csproj" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
var builder = DistributedApplication.CreateBuilder(args);
var backend = builder.AddProject<Projects.Backend>("backend");

View File

@ -0,0 +1,43 @@
{
"profiles": {
"https": {
"commandName": "Project",
"launchBrowser": true,
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:15887;http://localhost:15888",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
//"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:16037",
"DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "https://localhost:16038",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037",
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true"
}
},
"http": {
"commandName": "Project",
"launchBrowser": true,
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:15888",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
//"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16031",
"DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "http://localhost:16032",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17031",
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true",
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
}
},
"generate-manifest": {
"commandName": "Project",
"dotnetRunMessages": true,
"commandLineArgs": "--publisher manifest --output-path aspire-manifest.json",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development"
}
}
},
"$schema": "https://json.schemastore.org/launchsettings.json"
}

View File

@ -1,7 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// HelloAIAgent.cs
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
namespace Hello;
[TopicSubscription("HelloAgents")]

View File

@ -1,16 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Extensions\AIModelClientHostingExtensions\AIModelClientHostingExtensions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@ -18,4 +6,14 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Extensions\AIModelClientHostingExtensions\AIModelClientHostingExtensions.csproj" />
</ItemGroup>
</Project>

View File

@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
using Hello;
using Microsoft.AspNetCore.Builder;
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
// send a message to the agent
var builder = WebApplication.CreateBuilder();

View File

@ -0,0 +1,12 @@
{
"profiles": {
"HelloAIAgents": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:53139;http://localhost:53140"
}
}
}

View File

@ -1,16 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Aspire.Hosting.AppHost" />
</ItemGroup>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@ -18,4 +6,14 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Aspire.Hosting.AppHost" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>
</Project>

View File

@ -1,11 +1,18 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
// send a message to the agent
// step 1: create in-memory agent runtime
// step 2: register HelloAgent to that agent runtime
// step 3: start the agent runtime
// step 4: send a message to the agent
// step 5: wait for the agent runtime to shutdown
var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived
{
Message = "World"
@ -18,10 +25,12 @@ namespace Hello
[TopicSubscription("HelloAgents")]
public class HelloAgent(
IAgentContext context,
[FromKeyedServices("EventTypes")] EventTypes typeRegistry) : ConsoleAgent(
[FromKeyedServices("EventTypes")] EventTypes typeRegistry,
IHostApplicationLifetime hostApplicationLifetime) : AgentBase(
context,
typeRegistry),
ISayHello,
IHandleConsole,
IHandle<NewMessageReceived>,
IHandle<ConversationClosed>
{
@ -48,11 +57,11 @@ namespace Hello
Message = goodbye
}.ToCloudEvent(this.AgentId.Key);
await PublishEvent(evt).ConfigureAwait(false);
//sleep
await Task.Delay(10000).ConfigureAwait(false);
await AgentsApp.ShutdownAsync().ConfigureAwait(false);
// Signal shutdown.
hostApplicationLifetime.StopApplication();
}
public async Task<string> SayHello(string ask)
{
var response = $"\n\n\n\n***************Hello {ask}**********************\n\n\n\n";

View File

@ -0,0 +1,12 @@
{
"profiles": {
"HelloAgent": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:53113;http://localhost:53114"
}
}
}

View File

@ -1,16 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Aspire.Hosting.AppHost" />
</ItemGroup>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@ -18,4 +6,14 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Aspire.Hosting.AppHost" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>
</Project>

View File

@ -1,9 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
// send a message to the agent
var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived

View File

@ -0,0 +1,12 @@
{
"profiles": {
"HelloAgentState": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:53136;http://localhost:53137"
}
}
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
using Microsoft.AutoGen.Runtime;
var builder = WebApplication.CreateBuilder(args);

View File

@ -0,0 +1,12 @@
{
"profiles": {
"DevTeam.AgentHost": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:50670;http://localhost:50673"
}
}
}

View File

@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../../src/Microsoft.AutoGen/Agents/Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="../../../src/Microsoft.AutoGen/ServiceDefaults/Microsoft.AutoGen.ServiceDefaults.csproj" />
<ProjectReference Include="..\DevTeam.Shared\DevTeam.Shared.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Extensions\SemanticKernel\Microsoft.AutoGen.Extensions.SemanticKernel.csproj" />

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Developer.cs
using DevTeam.Shared;
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;

View File

@ -1,3 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DeveloperPrompts.cs
namespace DevTeam.Agents;
public static class DeveloperSkills

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DeveloperLead.cs
using DevTeam.Shared;
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DeveloperLeadPrompts.cs
namespace DevTeam.Agents;
public static class DevLeadSkills
{

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// PMPrompts.cs
namespace DevTeam.Agents;
public static class PMSkills
{

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ProductManager.cs
using DevTeam.Shared;
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
using DevTeam.Agents;
using Microsoft.AutoGen.Agents;
using Microsoft.AutoGen.Extensions.SemanticKernel;

View File

@ -0,0 +1,12 @@
{
"profiles": {
"DevTeam.Agents": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:50669;http://localhost:50671"
}
}
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureProvisioning();

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AzureGenie.cs
using DevTeam.Backend;
using DevTeam.Shared;
using Microsoft.AutoGen.Abstractions;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Hubber.cs
using System.Text.Json;
using DevTeam;
using DevTeam.Backend;

View File

@ -1,7 +1,5 @@
// TODO: Reimplement using ACA Sessions
// using DevTeam.Events;
// using Microsoft.AutoGen.Abstractions;
// using Microsoft.AutoGen.Agents;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Sandbox.cs
// namespace DevTeam.Backend;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Program.cs
using Azure.Identity;
using DevTeam.Backend;
using DevTeam.Options;

View File

@ -0,0 +1,12 @@
{
"profiles": {
"DevTeam.Backend": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:50672;http://localhost:50674"
}
}
}

View File

@ -1,3 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AzureService.cs
using System.Text;
using Azure;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// GithubAuthService.cs
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// GithubService.cs
using System.Text;
using Azure.Storage.Files.Shares;
using DevTeam.Options;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// GithubWebHookProcessor.cs
using System.Globalization;
using DevTeam.Shared;
using Microsoft.AutoGen.Abstractions;

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// EventExtensions.cs
using System.Globalization;
using Microsoft.AutoGen.Abstractions;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DevPlan.cs
namespace DevTeam;
public class DevLeadPlan
{

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AzureOptions.cs
using System.ComponentModel.DataAnnotations;
namespace DevTeam.Options;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// GithubOptions.cs
using System.ComponentModel.DataAnnotations;
namespace DevTeam.Options;

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// ParseExtensions.cs
namespace DevTeam;

View File

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ChatCompletionRequest.cs
using System.Collections.Generic;
using System.Text.Json.Serialization;

View File

@ -17,6 +17,7 @@
<ItemGroup>
<PackageReference Include="JsonSchema.Net.Generation" />
<PackageReference Include="System.Memory.Data" />
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentExtension.cs
using System;
using System.Collections.Generic;

View File

@ -3,6 +3,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Microsoft.Extensions.AI;
namespace AutoGen.Core;
@ -22,6 +25,10 @@ public class FunctionAttribute : Attribute
public class FunctionContract
{
private const string NamespaceKey = nameof(Namespace);
private const string ClassNameKey = nameof(ClassName);
/// <summary>
/// The namespace of the function.
/// </summary>
@ -52,6 +59,7 @@ public class FunctionContract
/// <summary>
/// The return type of the function.
/// </summary>
[JsonIgnore]
public Type? ReturnType { get; set; }
/// <summary>
@ -60,6 +68,39 @@ public class FunctionContract
/// Otherwise, the description will be null.
/// </summary>
public string? ReturnDescription { get; set; }
public static implicit operator FunctionContract(AIFunctionMetadata metadata)
{
return new FunctionContract
{
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,
};
}
public static implicit operator AIFunctionMetadata(FunctionContract contract)
{
return new AIFunctionMetadata(contract.Name)
{
Description = contract.Description,
ReturnParameter = new AIFunctionReturnParameterMetadata()
{
Description = contract.ReturnDescription,
ParameterType = contract.ReturnType,
},
AdditionalProperties = new Dictionary<string, object?>
{
[NamespaceKey] = contract.Namespace,
[ClassNameKey] = contract.ClassName,
},
Parameters = [.. contract.Parameters?.Select(p => (AIFunctionParameterMetadata)p)],
};
}
}
public class FunctionParameterContract
@ -79,6 +120,7 @@ public class FunctionParameterContract
/// <summary>
/// The type of the parameter.
/// </summary>
[JsonIgnore]
public Type? ParameterType { get; set; }
/// <summary>
@ -90,4 +132,29 @@ 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,
};
}
}

View File

@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// GroupChat.cs
using System;
using System.Collections.Generic;

View File

@ -5,8 +5,10 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
namespace AutoGen.Core;
@ -43,6 +45,19 @@ public class FunctionCallMiddleware : IStreamingMiddleware
this.functionMap = functionMap;
}
/// <summary>
/// Create a new instance of <see cref="FunctionCallMiddleware"/> with a list of <see cref="AIFunction"/>.
/// </summary>
/// <param name="functions">function list</param>
/// <param name="name">optional middleware name. If not provided, the class name <see cref="FunctionCallMiddleware"/> will be used.</param>
public FunctionCallMiddleware(IEnumerable<AIFunction> functions, string? name = null)
{
this.Name = name ?? nameof(FunctionCallMiddleware);
this.functions = functions.Select(f => (FunctionContract)f.Metadata).ToArray();
this.functionMap = functions.Select(f => (f.Metadata.Name, this.AIToolInvokeWrapper(f.InvokeAsync))).ToDictionary(f => f.Name, f => f.Item2);
}
public string? Name { get; }
public async Task<IMessage> InvokeAsync(MiddlewareContext context, IAgent agent, CancellationToken cancellationToken = default)
@ -173,4 +188,20 @@ public class FunctionCallMiddleware : IStreamingMiddleware
return toolCallMsg;
}
}
private Func<string, Task<string>> AIToolInvokeWrapper(Func<IEnumerable<KeyValuePair<string, object?>>?, CancellationToken, Task<object?>> lambda)
{
return async (string args) =>
{
var arguments = JsonSerializer.Deserialize<Dictionary<string, object?>>(args);
var result = await lambda(arguments, CancellationToken.None);
return result switch
{
string s => s,
JsonElement e => e.ToString(),
_ => JsonSerializer.Serialize(result),
};
};
}
}

View File

@ -5,45 +5,44 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace AutoGen
namespace AutoGen;
public static class LLMConfigAPI
{
public static class LLMConfigAPI
public static IEnumerable<ILLMConfig> GetOpenAIConfigList(
string apiKey,
IEnumerable<string>? modelIDs = null)
{
public static IEnumerable<ILLMConfig> GetOpenAIConfigList(
string apiKey,
IEnumerable<string>? modelIDs = null)
var models = modelIDs ?? new[]
{
var models = modelIDs ?? new[]
{
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k",
"gpt-4",
"gpt-4-32k",
"gpt-4-0613",
"gpt-4-32k-0613",
"gpt-4-1106-preview",
};
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k",
"gpt-4",
"gpt-4-32k",
"gpt-4-0613",
"gpt-4-32k-0613",
"gpt-4-1106-preview",
};
return models.Select(modelId => new OpenAIConfig(apiKey, modelId));
}
return models.Select(modelId => new OpenAIConfig(apiKey, modelId));
}
public static IEnumerable<ILLMConfig> GetAzureOpenAIConfigList(
string endpoint,
string apiKey,
IEnumerable<string> deploymentNames)
{
return deploymentNames.Select(deploymentName => new AzureOpenAIConfig(endpoint, deploymentName, apiKey));
}
public static IEnumerable<ILLMConfig> GetAzureOpenAIConfigList(
string endpoint,
string apiKey,
IEnumerable<string> deploymentNames)
{
return deploymentNames.Select(deploymentName => new AzureOpenAIConfig(endpoint, deploymentName, apiKey));
}
/// <summary>
/// Get a list of LLMConfig objects from a JSON file.
/// </summary>
internal static IEnumerable<ILLMConfig> ConfigListFromJson(
string filePath,
IEnumerable<string>? filterModels = null)
{
// Disable this API from documentation for now.
throw new NotImplementedException();
}
/// <summary>
/// Get a list of LLMConfig objects from a JSON file.
/// </summary>
internal static IEnumerable<ILLMConfig> ConfigListFromJson(
string filePath,
IEnumerable<string>? filterModels = null)
{
// Disable this API from documentation for now.
throw new NotImplementedException();
}
}

View File

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// LMStudioConfig.cs
using System;
using System.ClientModel;
using OpenAI;

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentId.cs
namespace Microsoft.AutoGen.Abstractions;
public partial class AgentId
{
public AgentId(string type, string key)
{
Type = type;
Key = key;
}
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ChatHistoryItem.cs
namespace Microsoft.AutoGen.Abstractions;
[Serializable]

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ChatState.cs
using Google.Protobuf;
namespace Microsoft.AutoGen.Abstractions;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ChatUserType.cs
namespace Microsoft.AutoGen.Abstractions;
public enum ChatUserType

View File

@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IAgentBase.cs
using Google.Protobuf;
namespace Microsoft.AutoGen.Abstractions;
public interface IAgentBase
{
// Properties
AgentId AgentId { get; }
IAgentContext Context { get; }
// Methods
Task CallHandler(CloudEvent item);
Task<RpcResponse> HandleRequest(RpcRequest request);
void ReceiveMessage(Message message);
Task Store(AgentState state);
Task<T> Read<T>(AgentId agentId) where T : IMessage, new();
ValueTask PublishEvent(CloudEvent item);
}

View File

@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IAgentContext.cs
using System.Diagnostics;
using Microsoft.Extensions.Logging;
namespace Microsoft.AutoGen.Abstractions;
public interface IAgentContext
{
AgentId AgentId { get; }
IAgentBase? AgentInstance { get; set; }
DistributedContextPropagator DistributedContextPropagator { get; } // TODO: Remove this. An abstraction should not have a dependency on DistributedContextPropagator.
ILogger Logger { get; } // TODO: Remove this. An abstraction should not have a dependency on ILogger.
ValueTask Store(AgentState value, CancellationToken cancellationToken = default);
ValueTask<AgentState> Read(AgentId agentId, CancellationToken cancellationToken = default);
ValueTask SendResponseAsync(RpcRequest request, RpcResponse response, CancellationToken cancellationToken = default);
ValueTask SendRequestAsync(IAgentBase agent, RpcRequest request, CancellationToken cancellationToken = default);
ValueTask PublishEventAsync(CloudEvent @event, CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IAgentWorkerRuntime.cs
namespace Microsoft.AutoGen.Abstractions;
public interface IAgentWorkerRuntime
{
ValueTask PublishEvent(CloudEvent evt, CancellationToken cancellationToken);
ValueTask SendRequest(IAgentBase agent, RpcRequest request, CancellationToken cancellationToken);
ValueTask SendResponse(RpcResponse response, CancellationToken cancellationToken);
ValueTask Store(AgentState value, CancellationToken cancellationToken);
ValueTask<AgentState> Read(AgentId agentId, CancellationToken cancellationToken);
}

View File

@ -1,6 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IHandle.cs
namespace Microsoft.AutoGen.Abstractions;
public interface IHandle<T>
public interface IHandle
{
Task HandleObject(object item);
}
public interface IHandle<T> : IHandle
{
Task Handle(T item);
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// MessageExtensions.cs
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// TopicSubscriptionAttribute.cs
namespace Microsoft.AutoGen.Abstractions;
[AttributeUsage(AttributeTargets.All)]

View File

@ -1,4 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentBase.cs
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Channels;
@ -8,7 +12,7 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AutoGen.Agents;
public abstract class AgentBase : IAgentBase
public abstract class AgentBase : IAgentBase, IHandle
{
public static readonly ActivitySource s_source = new("AutoGen.Agent");
public AgentId AgentId => _context.AgentId;
@ -17,6 +21,8 @@ public abstract class AgentBase : IAgentBase
private readonly Channel<object> _mailbox = Channel.CreateUnbounded<object>();
private readonly IAgentContext _context;
public string Route { get; set; } = "base";
protected internal ILogger Logger => _context.Logger;
public IAgentContext Context => _context;
protected readonly EventTypes EventTypes;
@ -196,15 +202,14 @@ public abstract class AgentBase : IAgentBase
var activity = s_source.StartActivity($"PublishEvent '{item.Type}'", ActivityKind.Client, Activity.Current?.Context ?? default);
activity?.SetTag("peer.service", $"{item.Type}/{item.Source}");
var completion = new TaskCompletionSource<CloudEvent>(TaskCreationOptions.RunContinuationsAsynchronously);
// TODO: fix activity
Context.DistributedContextPropagator.Inject(activity, item.Metadata, static (carrier, key, value) => ((IDictionary<string, string>)carrier!)[key] = value);
await this.InvokeWithActivityAsync(
static async ((AgentBase Agent, CloudEvent Event, TaskCompletionSource<CloudEvent>) state) =>
static async ((AgentBase Agent, CloudEvent Event) state) =>
{
await state.Agent._context.PublishEventAsync(state.Event).ConfigureAwait(false);
},
(this, item, completion),
(this, item),
activity,
item.Type).ConfigureAwait(false);
}
@ -212,16 +217,59 @@ public abstract class AgentBase : IAgentBase
public Task CallHandler(CloudEvent item)
{
// Only send the event to the handler if the agent type is handling that type
if (EventTypes.EventsMap[GetType()].Contains(item.Type))
// foreach of the keys in the EventTypes.EventsMap[] if it contains the item.type
foreach (var key in EventTypes.EventsMap.Keys)
{
var payload = item.ProtoData.Unpack(EventTypes.TypeRegistry);
var convertedPayload = Convert.ChangeType(payload, EventTypes.Types[item.Type]);
var genericInterfaceType = typeof(IHandle<>).MakeGenericType(EventTypes.Types[item.Type]);
var methodInfo = genericInterfaceType.GetMethod(nameof(IHandle<object>.Handle)) ?? throw new InvalidOperationException($"Method not found on type {genericInterfaceType.FullName}");
return methodInfo.Invoke(this, [payload]) as Task ?? Task.CompletedTask;
if (EventTypes.EventsMap[key].Contains(item.Type))
{
var payload = item.ProtoData.Unpack(EventTypes.TypeRegistry);
var convertedPayload = Convert.ChangeType(payload, EventTypes.Types[item.Type]);
var genericInterfaceType = typeof(IHandle<>).MakeGenericType(EventTypes.Types[item.Type]);
MethodInfo methodInfo;
try
{
// check that our target actually implements this interface, otherwise call the default static
if (genericInterfaceType.IsAssignableFrom(this.GetType()))
{
methodInfo = genericInterfaceType.GetMethod(nameof(IHandle<object>.Handle), BindingFlags.Public | BindingFlags.Instance)
?? throw new InvalidOperationException($"Method not found on type {genericInterfaceType.FullName}");
return methodInfo.Invoke(this, [payload]) as Task ?? Task.CompletedTask;
}
else
{
// The error here is we have registered for an event that we do not have code to listen to
throw new InvalidOperationException($"No handler found for event '{item.Type}'; expecting IHandle<{item.Type}> implementation.");
}
}
catch (Exception ex)
{
Logger.LogError(ex, $"Error invoking method {nameof(IHandle<object>.Handle)}");
throw; // TODO: ?
}
}
}
return Task.CompletedTask;
}
public virtual Task<RpcResponse> HandleRequest(RpcRequest request) => Task.FromResult(new RpcResponse { Error = "Not implemented" });
public Task<RpcResponse> HandleRequest(RpcRequest request) => Task.FromResult(new RpcResponse { Error = "Not implemented" });
public virtual Task HandleObject(object item)
{
// get all Handle<T> methods
var handleTMethods = this.GetType().GetMethods().Where(m => m.Name == "Handle" && m.GetParameters().Length == 1).ToList();
// get the one that matches the type of the item
var handleTMethod = handleTMethods.FirstOrDefault(m => m.GetParameters()[0].ParameterType == item.GetType());
// if we found one, invoke it
if (handleTMethod != null)
{
return (Task)handleTMethod.Invoke(this, [item])!;
}
// otherwise, complain
throw new InvalidOperationException($"No handler found for type {item.GetType().FullName}");
}
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentBaseExtensions.cs
using System.Diagnostics;
namespace Microsoft.AutoGen.Agents;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentContext.cs
using System.Diagnostics;
using Microsoft.AutoGen.Abstractions;
using Microsoft.Extensions.Logging;
@ -10,27 +13,27 @@ internal sealed class AgentContext(AgentId agentId, IAgentWorkerRuntime runtime,
public AgentId AgentId { get; } = agentId;
public ILogger Logger { get; } = logger;
public AgentBase? AgentInstance { get; set; }
public IAgentBase? AgentInstance { get; set; }
public DistributedContextPropagator DistributedContextPropagator { get; } = distributedContextPropagator;
public async ValueTask SendResponseAsync(RpcRequest request, RpcResponse response)
public async ValueTask SendResponseAsync(RpcRequest request, RpcResponse response, CancellationToken cancellationToken)
{
response.RequestId = request.RequestId;
await _runtime.SendResponse(response);
await _runtime.SendResponse(response, cancellationToken).ConfigureAwait(false);
}
public async ValueTask SendRequestAsync(AgentBase agent, RpcRequest request)
public async ValueTask SendRequestAsync(IAgentBase agent, RpcRequest request, CancellationToken cancellationToken)
{
await _runtime.SendRequest(agent, request).ConfigureAwait(false);
await _runtime.SendRequest(agent, request, cancellationToken).ConfigureAwait(false);
}
public async ValueTask PublishEventAsync(CloudEvent @event)
public async ValueTask PublishEventAsync(CloudEvent @event, CancellationToken cancellationToken)
{
await _runtime.PublishEvent(@event).ConfigureAwait(false);
await _runtime.PublishEvent(@event, cancellationToken).ConfigureAwait(false);
}
public async ValueTask Store(AgentState value)
public async ValueTask Store(AgentState value, CancellationToken cancellationToken)
{
await _runtime.Store(value).ConfigureAwait(false);
await _runtime.Store(value, cancellationToken).ConfigureAwait(false);
}
public ValueTask<AgentState> Read(AgentId agentId)
public ValueTask<AgentState> Read(AgentId agentId, CancellationToken cancellationToken)
{
return _runtime.Read(agentId);
return _runtime.Read(agentId, cancellationToken);
}
}

View File

@ -1,15 +0,0 @@
using RpcAgentId = Microsoft.AutoGen.Abstractions.AgentId;
namespace Microsoft.AutoGen.Agents;
public sealed record class AgentId(string Type, string Key)
{
public static implicit operator RpcAgentId(AgentId agentId) => new()
{
Type = agentId.Type,
Key = agentId.Key
};
public static implicit operator AgentId(RpcAgentId agentId) => new(agentId.Type, agentId.Key);
public override string ToString() => $"{Type}/{Key}";
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentWorker.cs
using System.Diagnostics;
using Google.Protobuf;
using Microsoft.AutoGen.Abstractions;

View File

@ -1,4 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// InferenceAgent.cs
using Google.Protobuf;
using Microsoft.AutoGen.Abstractions;
using Microsoft.Extensions.AI;
namespace Microsoft.AutoGen.Agents.Client;
public abstract class InferenceAgent<T> : AgentBase where T : IMessage, new()

View File

@ -1,7 +1,9 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// SKAiAgent.cs
using System.Globalization;
using System.Text;
using Microsoft.AutoGen.Abstractions;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Memory;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ConsoleAgent.cs
using Microsoft.AutoGen.Abstractions;
using Microsoft.Extensions.DependencyInjection;

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IHandleConsole.cs
using Microsoft.AutoGen.Abstractions;
namespace Microsoft.AutoGen.Agents;
public interface IHandleConsole : IHandle<Output>, IHandle<Input>
{
string Route { get; }
AgentId AgentId { get; }
ValueTask PublishEvent(CloudEvent item);
async Task IHandle<Output>.Handle(Output item)
{
// Assuming item has a property `Message` that we want to write to the console
Console.WriteLine(item.Message);
await ProcessOutput(item.Message);
var evt = new OutputWritten
{
Route = "console"
}.ToCloudEvent(AgentId.Key);
await PublishEvent(evt);
}
async Task IHandle<Input>.Handle(Input item)
{
Console.WriteLine("Please enter input:");
string content = Console.ReadLine() ?? string.Empty;
await ProcessInput(content);
var evt = new InputProcessed
{
Route = "console"
}.ToCloudEvent(AgentId.Key);
await PublishEvent(evt);
}
static Task ProcessOutput(string message)
{
// Implement your output processing logic here
return Task.CompletedTask;
}
static Task<string> ProcessInput(string message)
{
// Implement your input processing logic here
return Task.FromResult(message);
}
}

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// FileAgent.cs
using Microsoft.AutoGen.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IOAgent.cs
using Microsoft.AutoGen.Abstractions;
namespace Microsoft.AutoGen.Agents;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// WebAPIAgent.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AutoGen.Abstractions;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// App.cs
using System.Diagnostics.CodeAnalysis;
using Google.Protobuf;
using Microsoft.AspNetCore.Builder;

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// GrpcAgentWorkerRuntime.cs
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Reflection;
@ -16,7 +19,7 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
private readonly ConcurrentDictionary<string, Type> _agentTypes = new();
private readonly ConcurrentDictionary<(string Type, string Key), IAgentBase> _agents = new();
private readonly ConcurrentDictionary<string, (IAgentBase Agent, string OriginalRequestId)> _pendingRequests = new();
private readonly Channel<Message> _outboundMessagesChannel = Channel.CreateBounded<Message>(new BoundedChannelOptions(1024)
private readonly Channel<(Message Message, TaskCompletionSource WriteCompletionSource)> _outboundMessagesChannel = Channel.CreateBounded<(Message, TaskCompletionSource)>(new BoundedChannelOptions(1024)
{
AllowSynchronousContinuations = true,
SingleReader = true,
@ -83,6 +86,7 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
message.Response.RequestId = request.OriginalRequestId;
request.Agent.ReceiveMessage(message);
break;
case Message.MessageOneofCase.RegisterAgentTypeResponse:
if (!message.RegisterAgentTypeResponse.Success)
{
@ -134,30 +138,34 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
var outboundMessages = _outboundMessagesChannel.Reader;
while (!_shutdownCts.IsCancellationRequested)
{
(Message Message, TaskCompletionSource WriteCompletionSource) item = default;
try
{
await outboundMessages.WaitToReadAsync().ConfigureAwait(false);
// Read the next message if we don't already have an unsent message
// waiting to be sent.
if (!outboundMessages.TryRead(out var message))
if (!outboundMessages.TryRead(out item))
{
break;
}
while (!_shutdownCts.IsCancellationRequested)
{
await channel.RequestStream.WriteAsync(message, _shutdownCts.Token).ConfigureAwait(false);
await channel.RequestStream.WriteAsync(item.Message, _shutdownCts.Token).ConfigureAwait(false);
item.WriteCompletionSource.TrySetResult();
break;
}
}
catch (OperationCanceledException)
{
// Time to shut down.
item.WriteCompletionSource?.TrySetCanceled();
break;
}
catch (Exception ex) when (!_shutdownCts.IsCancellationRequested)
{
item.WriteCompletionSource?.TrySetException(ex);
_logger.LogError(ex, "Error writing to channel.");
channel = RecreateChannel(channel);
continue;
@ -165,9 +173,15 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
catch
{
// Shutdown requested.
item.WriteCompletionSource?.TrySetCanceled();
break;
}
}
while (outboundMessages.TryRead(out var item))
{
item.WriteCompletionSource.TrySetCanceled();
}
}
private IAgentBase GetOrActivateAgent(AgentId agentId)
@ -209,33 +223,53 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
//StateType = state?.Name,
//Events = { events }
}
}).ConfigureAwait(false);
},
_shutdownCts.Token).ConfigureAwait(false);
}
}
public async ValueTask SendResponse(RpcResponse response)
public async ValueTask SendResponse(RpcResponse response, CancellationToken cancellationToken)
{
_logger.LogInformation("Sending response '{Response}'.", response);
await WriteChannelAsync(new Message { Response = response }).ConfigureAwait(false);
await WriteChannelAsync(new Message { Response = response }, cancellationToken).ConfigureAwait(false);
}
public async ValueTask SendRequest(IAgentBase agent, RpcRequest request)
public async ValueTask SendRequest(IAgentBase agent, RpcRequest request, CancellationToken cancellationToken)
{
_logger.LogInformation("[{AgentId}] Sending request '{Request}'.", agent.AgentId, request);
var requestId = Guid.NewGuid().ToString();
_pendingRequests[requestId] = (agent, request.RequestId);
request.RequestId = requestId;
await WriteChannelAsync(new Message { Request = request }).ConfigureAwait(false);
try
{
await WriteChannelAsync(new Message { Request = request }, cancellationToken).ConfigureAwait(false);
}
catch (Exception exception)
{
if (_pendingRequests.TryRemove(requestId, out _))
{
agent.ReceiveMessage(new Message { Response = new RpcResponse { RequestId = request.RequestId, Error = exception.Message } });
}
}
}
public async ValueTask PublishEvent(CloudEvent @event)
public async ValueTask PublishEvent(CloudEvent @event, CancellationToken cancellationToken)
{
await WriteChannelAsync(new Message { CloudEvent = @event }).ConfigureAwait(false);
try
{
await WriteChannelAsync(new Message { CloudEvent = @event }, cancellationToken).ConfigureAwait(false);
}
catch (Exception exception)
{
_logger.LogWarning(exception, "Failed to publish event '{Event}'.", @event);
}
}
private async Task WriteChannelAsync(Message message)
private async Task WriteChannelAsync(Message message, CancellationToken cancellationToken)
{
await _outboundMessagesChannel.Writer.WriteAsync(message).ConfigureAwait(false);
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
await _outboundMessagesChannel.Writer.WriteAsync((message, tcs), cancellationToken).ConfigureAwait(false);
await tcs.Task.WaitAsync(cancellationToken);
}
private AsyncDuplexStreamingCall<Message, Message> GetChannel()
@ -265,7 +299,7 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
if (_channel is null || _channel == channel)
{
_channel?.Dispose();
_channel = _client.OpenChannel();
_channel = _client.OpenChannel(cancellationToken: _shutdownCts.Token);
}
}
}
@ -330,19 +364,19 @@ public sealed class GrpcAgentWorkerRuntime : IHostedService, IDisposable, IAgent
_channel?.Dispose();
}
}
public ValueTask Store(AgentState value)
public ValueTask Store(AgentState value, CancellationToken cancellationToken)
{
var agentId = value.AgentId ?? throw new InvalidOperationException("AgentId is required when saving AgentState.");
var response = _client.SaveState(value);
var response = _client.SaveState(value, cancellationToken: cancellationToken);
if (!response.Success)
{
throw new InvalidOperationException($"Error saving AgentState for AgentId {agentId}.");
}
return ValueTask.CompletedTask;
}
public async ValueTask<AgentState> Read(AgentId agentId)
public async ValueTask<AgentState> Read(AgentId agentId, CancellationToken cancellationToken)
{
var response = await _client.GetStateAsync(agentId);
var response = await _client.GetStateAsync(agentId, cancellationToken: cancellationToken);
// if (response.Success && response.AgentState.AgentId is not null) - why is success always false?
if (response.AgentState.AgentId is not null)
{

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// HostBuilderExtensions.cs
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
@ -71,7 +74,52 @@ public static class HostBuilderExtensions
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IHandle<>))
.Select(i => (GetMessageDescriptor(i.GetGenericArguments().First())?.FullName ?? "")).ToHashSet()))
.ToDictionary(item => item.t, item => item.Item2);
// if the assembly contains any interfaces of type IHandler, then add all the methods of the interface to the eventsMap
var handlersMap = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => ReflectionHelper.IsSubclassOfGeneric(type, typeof(AgentBase)) && !type.IsAbstract)
.Select(t => (t, t.GetMethods()
.Where(m => m.Name == "Handle")
.Select(m => (GetMessageDescriptor(m.GetParameters().First().ParameterType)?.FullName ?? "")).ToHashSet()))
.ToDictionary(item => item.t, item => item.Item2);
// get interfaces implemented by the agent and get the methods of the interface if they are named Handle
var ifaceHandlersMap = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => ReflectionHelper.IsSubclassOfGeneric(type, typeof(AgentBase)) && !type.IsAbstract)
.Select(t => t.GetInterfaces()
.Select(i => (t, i, i.GetMethods()
.Where(m => m.Name == "Handle")
.Select(m => (GetMessageDescriptor(m.GetParameters().First().ParameterType)?.FullName ?? ""))
//to dictionary of type t and paramter type of the method
.ToDictionary(m => m, m => m).Keys.ToHashSet())).ToList());
// for each item in ifaceHandlersMap, add the handlers to eventsMap with item as the key
foreach (var item in ifaceHandlersMap)
{
foreach (var iface in item)
{
if (eventsMap.TryGetValue(iface.Item2, out var events))
{
events.UnionWith(iface.Item3);
}
else
{
eventsMap[iface.Item2] = iface.Item3;
}
}
}
// merge the handlersMap into the eventsMap
foreach (var item in handlersMap)
{
if (eventsMap.TryGetValue(item.Key, out var events))
{
events.UnionWith(item.Value);
}
else
{
eventsMap[item.Key] = item.Value;
}
}
return new EventTypes(typeRegistry, types, eventsMap);
});
return new AgentApplicationBuilder(builder);

View File

@ -1,20 +0,0 @@
using Google.Protobuf;
using Microsoft.AutoGen.Abstractions;
namespace Microsoft.AutoGen.Agents
{
public interface IAgentBase
{
// Properties
AgentId AgentId { get; }
IAgentContext Context { get; }
// Methods
Task CallHandler(CloudEvent item);
Task<RpcResponse> HandleRequest(RpcRequest request);
void ReceiveMessage(Message message);
Task Store(AgentState state);
Task<T> Read<T>(AgentId agentId) where T : IMessage, new();
ValueTask PublishEvent(CloudEvent item);
}
}

View File

@ -1,18 +0,0 @@
using System.Diagnostics;
using Microsoft.AutoGen.Abstractions;
using Microsoft.Extensions.Logging;
namespace Microsoft.AutoGen.Agents;
public interface IAgentContext
{
AgentId AgentId { get; }
AgentBase? AgentInstance { get; set; }
DistributedContextPropagator DistributedContextPropagator { get; }
ILogger Logger { get; }
ValueTask Store(AgentState value);
ValueTask<AgentState> Read(AgentId agentId);
ValueTask SendResponseAsync(RpcRequest request, RpcResponse response);
ValueTask SendRequestAsync(AgentBase agent, RpcRequest request);
ValueTask PublishEventAsync(CloudEvent @event);
}

View File

@ -1,13 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.AutoGen.Abstractions;
namespace Microsoft.AutoGen.Agents;
public interface IAgentWorkerRuntime
{
ValueTask PublishEvent(CloudEvent evt);
ValueTask SendRequest(IAgentBase agent, RpcRequest request);
ValueTask SendResponse(RpcResponse response);
ValueTask Store(AgentState value);
ValueTask<AgentState> Read(AgentId agentId);
}

View File

@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Abstractions/Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
<ProjectReference Include="..\Runtime\Microsoft.AutoGen.Runtime.csproj" />
</ItemGroup>

View File

@ -1,33 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AIModelClientHostingExtensions.cs
using Microsoft.Extensions.AI;
namespace Microsoft.Extensions.Hosting
{
public static class AIModelClient
{
public static IHostApplicationBuilder AddChatCompletionService(this IHostApplicationBuilder builder, string serviceName)
{
var pipeline = (ChatClientBuilder pipeline) => pipeline
.UseLogging()
.UseFunctionInvocation()
.UseOpenTelemetry(configure: c => c.EnableSensitiveData = true);
namespace Microsoft.Extensions.Hosting;
if (builder.Configuration[$"{serviceName}:ModelType"] == "ollama")
{
builder.AddOllamaChatClient(serviceName, pipeline);
}
else if (builder.Configuration[$"{serviceName}:ModelType"] == "openai" || builder.Configuration[$"{serviceName}:ModelType"] == "azureopenai")
{
builder.AddOpenAIChatClient(serviceName, pipeline);
}
else if (builder.Configuration[$"{serviceName}:ModelType"] == "azureaiinference")
{
builder.AddAzureChatClient(serviceName, pipeline);
}
else
{
throw new InvalidOperationException("Did not find a valid model implementation for the given service name ${serviceName}, valid supported implemenation types are ollama, openai, azureopenai, azureaiinference");
}
return builder;
public static class AIModelClient
{
public static IHostApplicationBuilder AddChatCompletionService(this IHostApplicationBuilder builder, string serviceName)
{
var pipeline = (ChatClientBuilder pipeline) => pipeline
.UseLogging()
.UseFunctionInvocation()
.UseOpenTelemetry(configure: c => c.EnableSensitiveData = true);
if (builder.Configuration[$"{serviceName}:ModelType"] == "ollama")
{
builder.AddOllamaChatClient(serviceName, pipeline);
}
else if (builder.Configuration[$"{serviceName}:ModelType"] == "openai" || builder.Configuration[$"{serviceName}:ModelType"] == "azureopenai")
{
builder.AddOpenAIChatClient(serviceName, pipeline);
}
else if (builder.Configuration[$"{serviceName}:ModelType"] == "azureaiinference")
{
builder.AddAzureChatClient(serviceName, pipeline);
}
else
{
throw new InvalidOperationException("Did not find a valid model implementation for the given service name ${serviceName}, valid supported implemenation types are ollama, openai, azureopenai, azureaiinference");
}
return builder;
}
}

View File

@ -14,5 +14,6 @@
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="System.Text.Json" VersionOverride="9.0.0-rc.2.24473.5" />
</ItemGroup>
</Project>

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AIClientOptions.cs
using System.ComponentModel.DataAnnotations;
namespace Microsoft.Extensions.Hosting;

Some files were not shown because too many files have changed in this diff Show More