Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring back agents project #5323

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions dotnet/AutoGen.sln
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hello", "Hello", "{F42F9C8E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AutoGen.Core.Grpc", "src\Microsoft.AutoGen\Core.Grpc\Microsoft.AutoGen.Core.Grpc.csproj", "{3D83C6DB-ACEA-48F3-959F-145CCD2EE135}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AutoGen.Agents", "src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj", "{FD2CD462-5B90-4547-B576-D5F10F63A4FC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -296,6 +298,12 @@ Global
{70A8D4B5-D0A6-4098-A6F3-6ED274B65E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70A8D4B5-D0A6-4098-A6F3-6ED274B65E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70A8D4B5-D0A6-4098-A6F3-6ED274B65E7D}.Release|Any CPU.Build.0 = Release|Any CPU
{FD2CD462-5B90-4547-B576-D5F10F63A4FC}.CoreOnly|Any CPU.ActiveCfg = Debug|Any CPU
{FD2CD462-5B90-4547-B576-D5F10F63A4FC}.CoreOnly|Any CPU.Build.0 = Debug|Any CPU
{FD2CD462-5B90-4547-B576-D5F10F63A4FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD2CD462-5B90-4547-B576-D5F10F63A4FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD2CD462-5B90-4547-B576-D5F10F63A4FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD2CD462-5B90-4547-B576-D5F10F63A4FC}.Release|Any CPU.Build.0 = Release|Any CPU
{3D83C6DB-ACEA-48F3-959F-145CCD2EE135}.CoreOnly|Any CPU.ActiveCfg = Debug|Any CPU
{3D83C6DB-ACEA-48F3-959F-145CCD2EE135}.CoreOnly|Any CPU.Build.0 = Debug|Any CPU
{3D83C6DB-ACEA-48F3-959F-145CCD2EE135}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -356,6 +364,7 @@ Global
{EAFFE339-26CB-4019-991D-BCCE8E7D33A1} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
{58AD8E1D-83BD-4950-A324-1A20677D78D9} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
{70A8D4B5-D0A6-4098-A6F3-6ED274B65E7D} = {CE0AA8D5-12B8-4628-9589-DAD8CB0DDCF6}
{FD2CD462-5B90-4547-B576-D5F10F63A4FC} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{3D83C6DB-ACEA-48F3-959F-145CCD2EE135} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
{AAD593FE-A49B-425E-A9FE-A0022CD25E3D} = {F42F9C8E-7BD9-4687-9B63-AFFA461AF5C1}
{F42F9C8E-7BD9-4687-9B63-AFFA461AF5C1} = {CE0AA8D5-12B8-4628-9589-DAD8CB0DDCF6}
Expand Down
11 changes: 5 additions & 6 deletions dotnet/samples/Hello/HelloAgent/HelloAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class HelloAgent(
IHandle<Shutdown>
{
// This will capture the message sent in Program.cs
public async ValueTask HandleAsync(NewMessageReceived item, MessageContext messageContext)
public async ValueTask HandleAsync(NewMessageReceived item, MessageContext messageContext, CancellationToken? cancellationToken = default)
{
Console.Out.WriteLine(item.Message); // Print message to console
ConversationClosed goodbye = new ConversationClosed
Expand All @@ -28,20 +28,19 @@ public async ValueTask HandleAsync(NewMessageReceived item, MessageContext messa
UserMessage = "Goodbye"
};
// This will publish the new message type which will be handled by the ConversationClosed handler
await this.PublishMessageAsync(goodbye, new TopicId("HelloTopic"));
await this.PublishMessageAsync(goodbye, new TopicId("HelloTopic"), null, cancellationToken ?? default);
}
public async ValueTask HandleAsync(ConversationClosed item, MessageContext messageContext)
public async ValueTask HandleAsync(ConversationClosed item, MessageContext messageContext, CancellationToken? cancellationToken = default)
{
var goodbye = $"{item.UserId} said {item.UserMessage}"; // Print goodbye message to console
Console.Out.WriteLine(goodbye);
if (Environment.GetEnvironmentVariable("STAY_ALIVE_ON_GOODBYE") != "true")
{
// Publish message that will be handled by shutdown handler
await this.PublishMessageAsync(new Shutdown(), new TopicId("HelloTopic"));
await this.PublishMessageAsync(new Shutdown(), new TopicId("HelloTopic"), null, cancellationToken ?? default);
}
}

public async ValueTask HandleAsync(Shutdown item, MessageContext messageContext)
public async ValueTask HandleAsync(Shutdown item, MessageContext messageContext, CancellationToken? cancellationToken = default)
{
Console.WriteLine("Shutting down...");
hostApplicationLifetime.StopApplication(); // Shuts down application
Expand Down
44 changes: 44 additions & 0 deletions dotnet/src/Microsoft.AutoGen/Agents/AIAgent/InferenceAgent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// InferenceAgent.cs
using Google.Protobuf;
using Microsoft.AutoGen.Contracts;
using Microsoft.AutoGen.Core;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
namespace Microsoft.AutoGen.Agents;
/// <summary>
/// Base class for inference agents using the Microsoft.Extensions.AI library.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <param name="runtime"></param>
/// <param name="name"></param>
/// <param name="logger"></param>
/// <param name="client"></param>
public abstract class InferenceAgent<T>(
AgentId id,
IAgentRuntime runtime,
string name,
ILogger<InferenceAgent<T>>? logger,
IChatClient client)
: BaseAgent(id, runtime, name, logger)
where T : IMessage, new()
{
protected IChatClient ChatClient { get; } = client;
private ILogger<InferenceAgent<T>>? Logger => _logger as ILogger<InferenceAgent<T>>;
private Task<ChatCompletion> CompleteAsync(
IList<ChatMessage> chatMessages,
ChatOptions? options = null,
CancellationToken cancellationToken = default)
{
return ChatClient.CompleteAsync(chatMessages, options, cancellationToken);
}
private IAsyncEnumerable<StreamingChatCompletionUpdate> CompleteStreamingAsync(
IList<ChatMessage> chatMessages,
ChatOptions? options = null,
CancellationToken cancellationToken = default)
{
return ChatClient.CompleteStreamingAsync(chatMessages, options, cancellationToken);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IHandleConsole.cs
using Google.Protobuf;
using Microsoft.AutoGen.Contracts;

namespace Microsoft.AutoGen.Agents;
/// <summary>
/// Default interface methods for an event handler for Input and Output that writes or reads from the console
/// Can be used inside your agents by inheriting from this interface
/// public class MyAgent : BaseAgent, IHandleConsole
/// </summary>
public interface IHandleConsole : IHandle<Output>, IHandle<Input>, IProcessIO
{
/// <summary>
/// Prototype for Publish Message Async method
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="message"></param>
/// <param name="topic"></param>
/// <param name="messageId"></param>
/// <param name="token"></param>
/// <returns>ValueTask</returns>
ValueTask PublishMessageAsync<T>(T message, TopicId topic, string? messageId, CancellationToken token = default) where T : IMessage;

/// <summary>
/// Receives events of type Output and writes them to the console
/// then runs the ProcessOutputAsync method which you should implement in your agent
/// </summary>
/// <param name="item"></param>
/// <param name="messageContext"></param>
/// <param name="cancellationToken"></param>
/// <returns>ValueTask</returns>
async ValueTask IHandle<Output>.HandleAsync(Output item, MessageContext messageContext, CancellationToken? cancellationToken)
{
// Assuming item has a property `Message` that we want to write to the console
Console.WriteLine(item.Message);
await ProcessOutputAsync(item.Message);

var evt = new OutputWritten
{
Route = "console"
};
await PublishMessageAsync(evt, new TopicId("OutputWritten"), null, token: cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
}

/// <summary>
/// Receives events of type Input and reads from the console, then runs the ProcessInputAsync method
/// which you should implement in your agent
/// </summary>
/// <param name="item"></param>
/// <param name="messageContext"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
async ValueTask IHandle<Input>.HandleAsync(Input item, MessageContext messageContext, CancellationToken? cancellationToken)
{
Console.WriteLine("Please enter input:");
string content = Console.ReadLine() ?? string.Empty;

await ProcessInputAsync(content);

var evt = new InputProcessed
{
Route = "console"
};
await PublishMessageAsync(evt, new TopicId("InputProcessed"), null, token: cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IHandleFileIO.cs

using Google.Protobuf;
using Microsoft.AutoGen.Contracts;
using Microsoft.Extensions.Logging;

namespace Microsoft.AutoGen.Agents;
/// <summary>
/// Default interface methods for an event handler for Input and Output that writes or reads from a file
/// Can be used inside your agents by inheriting from this interface
/// public class MyAgent : BaseAgent, IHandleFileIO
/// </summary>
public interface IHandleFileIO : IHandle<Input>, IHandle<Output>, IProcessIO
{
// A Logger instance to log messages
ILogger LogTarget { get; }
// The path to the input file
string InputPath { get; }
// The path to the output file
string OutputPath { get; }
// The route of the agent (used in the post-process events)
const string Route = "Microsoft.AutoGen.Agents.IHandleFileIO";

/// <summary>
/// Prototype for Publish Message Async method
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="message"></param>
/// <param name="topic"></param>
/// <param name="messageId"></param>
/// <param name="token"></param>
/// <returns>ValueTask</returns>
ValueTask PublishMessageAsync<T>(T message, TopicId topic, string? messageId, CancellationToken token = default) where T : IMessage;
async ValueTask IHandle<Input>.HandleAsync(Input item, MessageContext messageContext, CancellationToken? cancellationToken)
{

// validate that the file exists
if (!File.Exists(InputPath))
{
var errorMessage = $"File not found: {InputPath}";
LogTarget.LogError(errorMessage);
//publish IOError event
var err = new IOError
{
Message = errorMessage
};
await PublishMessageAsync(err, new TopicId("IOError"), null, token: cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
return;
}
string content;
using (var reader = new StreamReader(item.Message))
{
content = await reader.ReadToEndAsync(cancellationToken ?? CancellationToken.None);
}
await ProcessInputAsync(content);
var evt = new InputProcessed
{
Route = Route
};
await PublishMessageAsync(evt, new TopicId("InputProcessed"), null, token: cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
}
async ValueTask IHandle<Output>.HandleAsync(Output item, MessageContext messageContext, CancellationToken? cancellationToken)
{
using (var writer = new StreamWriter(OutputPath, append: true))
{
await writer.WriteLineAsync(item.Message);
}
var evt = new OutputWritten
{
Route = Route
};
await PublishMessageAsync(evt, new TopicId("OutputWritten"), null, token: cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
}
}
23 changes: 23 additions & 0 deletions dotnet/src/Microsoft.AutoGen/Agents/IOAgent/IProcessIO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IProcessIO.cs

namespace Microsoft.AutoGen.Agents;

/// <summary>
/// Default Interface methods for processing input and output shared by IOAgents that should be implemented in your agent
/// </summary>
public interface IProcessIO
{
/// <summary>
/// Implement this method in your agent to process the input
/// </summary>
/// <param name="message"></param>
/// <returns>Task</returns>
static Task ProcessOutputAsync(string message) { return Task.CompletedTask; }
/// <summary>
/// Implement this method in your agent to process the output
/// </summary>
/// <param name="message"></param>
/// <returns>Task</returns>
static Task<string> ProcessInputAsync(string message) { return Task.FromResult(message); }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<Import Project="$(RepoRoot)/nuget/nuget-package.props" />

<ItemGroup>
<ProjectReference Include="..\Contracts\Microsoft.AutoGen.Contracts.csproj" />
<ProjectReference Include="..\Core\Microsoft.AutoGen.Core.csproj" />
<ProjectReference Include="..\Extensions\Aspire\Microsoft.AutoGen.Extensions.Aspire.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SemanticKernel" />
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" />
<PackageReference Include="Grpc.Tools" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\agent_events.proto" GrpcServices="Client;Server" Link="Protos\agent_events.proto" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ syntax = "proto3";

package agents;

option csharp_namespace = "Microsoft.AutoGen.Contracts";
option csharp_namespace = "Microsoft.AutoGen.Agents";
message TextMessage {
string textMessage = 1;
string source = 2;
Expand Down
5 changes: 2 additions & 3 deletions dotnet/src/Microsoft.AutoGen/Contracts/IHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ public interface IHandle<in T>
/// </summary>
/// <param name="item">The item to be handled.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
ValueTask HandleAsync(T item, MessageContext messageContext);
ValueTask HandleAsync(T item, MessageContext messageContext, CancellationToken? cancellationToken = default);
}

public interface IHandle<in InT, OutT>
{
/// <summary>
/// Handles the specified item asynchronously.
/// </summary>
/// <param name="item">The item to be handled.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
ValueTask<OutT> HandleAsync(InT item, MessageContext messageContext);
ValueTask<OutT> HandleAsync(InT item, MessageContext messageContext, CancellationToken? cancellationToken = default);
}
Loading