Skip to content

Commit

Permalink
Upgrade .NET connector in the examples (microsoft#212)
Browse files Browse the repository at this point in the history
  • Loading branch information
dluc authored Nov 5, 2024
1 parent 8db5455 commit f237727
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 68 deletions.
23 changes: 2 additions & 21 deletions examples/dotnet/dotnet-01-echo-bot/MyAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,8 @@

namespace AgentExample;

public class MyAgent : AgentBase
public class MyAgent : AgentBase<MyAgentConfig>
{
// Agent settings
public MyAgentConfig Config
{
get { return (MyAgentConfig)this.RawConfig; }
private set { this.RawConfig = value; }
}

/// <summary>
/// Create a new agent instance
/// </summary>
Expand All @@ -28,7 +21,7 @@ public MyAgent(
string agentId,
string agentName,
MyAgentConfig? agentConfig,
WorkbenchConnector workbenchConnector,
WorkbenchConnector<MyAgentConfig> workbenchConnector,
IAgentServiceStorage storage,
ILoggerFactory? loggerFactory = null)
: base(
Expand All @@ -43,18 +36,6 @@ public MyAgent(
this.Config = JsonSerializer.Deserialize<MyAgentConfig>(JsonSerializer.Serialize(agentConfig)) ?? new MyAgentConfig();
}

/// <inheritdoc />
public override IAgentConfig GetDefaultConfig()
{
return new MyAgentConfig();
}

/// <inheritdoc />
public override IAgentConfig? ParseConfig(object data)
{
return JsonSerializer.Deserialize<MyAgentConfig>(JsonSerializer.Serialize(data));
}

/// <inheritdoc />
public override async Task ReceiveCommandAsync(
string conversationId,
Expand Down
2 changes: 1 addition & 1 deletion examples/dotnet/dotnet-01-echo-bot/MyAgentConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace AgentExample;

public class MyAgentConfig : AgentConfig
public class MyAgentConfig : AgentConfigBase
{
[JsonPropertyName(nameof(this.ReplyToAgents))]
[JsonPropertyOrder(10)]
Expand Down
18 changes: 12 additions & 6 deletions examples/dotnet/dotnet-01-echo-bot/MyWorkbenchConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@

namespace AgentExample;

public sealed class MyWorkbenchConnector : WorkbenchConnector
public sealed class MyWorkbenchConnector : WorkbenchConnector<MyAgentConfig>
{
private readonly MyAgentConfig _defaultAgentConfig = new();
private readonly IServiceProvider _sp;

public MyWorkbenchConnector(
IServiceProvider sp,
IConfiguration appConfig,
IAgentServiceStorage storage,
ILoggerFactory? loggerFactory = null)
: base(appConfig, storage, loggerFactory?.CreateLogger<MyWorkbenchConnector>() ?? new NullLogger<MyWorkbenchConnector>())
: base(
workbenchConfig: appConfig.GetSection("Workbench").Get<WorkbenchConfig>(),
defaultAgentConfig: appConfig.GetSection("Agent").Get<MyAgentConfig>(),
storage,
loggerFactory?.CreateLogger<MyWorkbenchConnector>() ?? new NullLogger<MyWorkbenchConnector>())
{
appConfig.GetSection("Agent").Bind(this._defaultAgentConfig);
this._sp = sp;
}

Expand All @@ -33,15 +35,19 @@ public override async Task CreateAgentAsync(

this.Log.LogDebug("Creating agent '{0}'", agentId);

MyAgentConfig config = this._defaultAgentConfig;
MyAgentConfig config = this.DefaultAgentConfig;
if (configData != null)
{
var newCfg = JsonSerializer.Deserialize<MyAgentConfig>(JsonSerializer.Serialize(configData));
if (newCfg != null) { config = newCfg; }
}

// Instantiate using .NET Service Provider so that dependencies are automatically injected
var agent = ActivatorUtilities.CreateInstance<MyAgent>(this._sp, agentId, name ?? agentId, config);
var agent = ActivatorUtilities.CreateInstance<MyAgent>(
this._sp,
agentId,
name ?? agentId,
config);

await agent.StartAsync(cancellationToken).ConfigureAwait(false);
this.Agents.TryAdd(agentId, agent);
Expand Down
4 changes: 2 additions & 2 deletions examples/dotnet/dotnet-01-echo-bot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal static async Task Main(string[] args)
appBuilder.Services.AddSingleton<IAgentServiceStorage, AgentServiceStorage>();

// Agent service to support multiple agent instances
appBuilder.Services.AddSingleton<WorkbenchConnector, MyWorkbenchConnector>();
appBuilder.Services.AddSingleton<WorkbenchConnector<MyAgentConfig>, MyWorkbenchConnector>();

// Misc
appBuilder.Services.AddLogging()
Expand All @@ -36,7 +36,7 @@ internal static async Task Main(string[] args)

// Connect to workbench backend, keep alive, and accept incoming requests
var connectorEndpoint = app.Configuration.GetSection("Workbench").Get<WorkbenchConfig>()!.ConnectorEndpoint;
using var agentService = app.UseAgentWebservice(connectorEndpoint, true);
using var agentService = app.UseAgentWebservice<MyAgentConfig>(connectorEndpoint, true);
await agentService.ConnectAsync().ConfigureAwait(false);

// Start app and webservice
Expand Down
4 changes: 2 additions & 2 deletions examples/dotnet/dotnet-01-echo-bot/dotnet-01-echo-bot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SemanticWorkbench.Connector" Version="0.2.241009.1" />
<PackageReference Include="Microsoft.SemanticWorkbench.Connector" Version="0.3.241104.1" />
</ItemGroup>

<PropertyGroup>
Expand Down Expand Up @@ -39,7 +39,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.12.7">
<PackageReference Include="Roslynator.Analyzers" Version="4.12.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Text;
using Microsoft.SemanticWorkbench.Connector;

namespace AgentExample;

public static class ConnectorExtensions
{
public static string GetParticipantName(this Conversation conversation, string id)
{
if (conversation.Participants.TryGetValue(id, out Participant? participant))
{
return participant.Name;
}

return "Unknown";
}

public static string ToHtmlString(
this Conversation conversation,
string assistantId)
{
var result = new StringBuilder();
result.AppendLine("<style>");
result.AppendLine("DIV.conversationHistory { padding: 0 20px 60px 20px; }");
result.AppendLine("DIV.conversationHistory P { margin: 0 0 8px 0; }");
result.AppendLine("</style>");
result.AppendLine("<div class='conversationHistory'>");

foreach (var msg in conversation.Messages)
{
result.AppendLine("<p>");
if (msg.Sender.Id == assistantId)
{
result.AppendLine("<b>Assistant</b><br/>");
}
else
{
result
.Append("<b>")
.Append(conversation.GetParticipantName(msg.Sender.Id))
.AppendLine("</b><br/>");
}

result.AppendLine(msg.Content).AppendLine("</p>");
}

result.Append("</div>");

return result.ToString();
}
}
23 changes: 2 additions & 21 deletions examples/dotnet/dotnet-02-message-types-demo/MyAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,8 @@

namespace AgentExample;

public class MyAgent : AgentBase
public class MyAgent : AgentBase<MyAgentConfig>
{
// Agent settings
public MyAgentConfig Config
{
get { return (MyAgentConfig)this.RawConfig; }
private set { this.RawConfig = value; }
}

// Azure Content Safety
private readonly ContentSafetyClient _contentSafety;

Expand All @@ -34,7 +27,7 @@ public MyAgent(
string agentId,
string agentName,
MyAgentConfig? agentConfig,
WorkbenchConnector workbenchConnector,
WorkbenchConnector<MyAgentConfig> workbenchConnector,
IAgentServiceStorage storage,
ContentSafetyClient contentSafety,
ILoggerFactory? loggerFactory = null)
Expand All @@ -51,18 +44,6 @@ public MyAgent(
this.Config = JsonSerializer.Deserialize<MyAgentConfig>(JsonSerializer.Serialize(agentConfig)) ?? new MyAgentConfig();
}

/// <inheritdoc />
public override IAgentConfig GetDefaultConfig()
{
return new MyAgentConfig();
}

/// <inheritdoc />
public override IAgentConfig? ParseConfig(object data)
{
return JsonSerializer.Deserialize<MyAgentConfig>(JsonSerializer.Serialize(data));
}

/// <inheritdoc />
public override async Task ReceiveCommandAsync(
string conversationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace AgentExample;

public class MyAgentConfig : AgentConfig
public class MyAgentConfig : AgentConfigBase
{
[JsonPropertyName(nameof(this.ReplyToAgents))]
[JsonPropertyOrder(10)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@

namespace AgentExample;

public sealed class MyWorkbenchConnector : WorkbenchConnector
public sealed class MyWorkbenchConnector : WorkbenchConnector<MyAgentConfig>
{
private readonly MyAgentConfig _defaultAgentConfig = new();
private readonly IServiceProvider _sp;

public MyWorkbenchConnector(
IServiceProvider sp,
IConfiguration appConfig,
IAgentServiceStorage storage,
ILoggerFactory? loggerFactory = null)
: base(appConfig, storage, loggerFactory?.CreateLogger<MyWorkbenchConnector>() ?? new NullLogger<MyWorkbenchConnector>())
: base(
workbenchConfig: appConfig.GetSection("Workbench").Get<WorkbenchConfig>(),
defaultAgentConfig: appConfig.GetSection("Agent").Get<MyAgentConfig>(),
storage,
loggerFactory?.CreateLogger<MyWorkbenchConnector>() ?? new NullLogger<MyWorkbenchConnector>())
{
appConfig.GetSection("Agent").Bind(this._defaultAgentConfig);
this._sp = sp;
}

Expand All @@ -33,15 +35,19 @@ public override async Task CreateAgentAsync(

this.Log.LogDebug("Creating agent '{0}'", agentId);

MyAgentConfig config = this._defaultAgentConfig;
MyAgentConfig config = this.DefaultAgentConfig;
if (configData != null)
{
var newCfg = JsonSerializer.Deserialize<MyAgentConfig>(JsonSerializer.Serialize(configData));
if (newCfg != null) { config = newCfg; }
}

// Instantiate using .NET Service Provider so that dependencies are automatically injected
var agent = ActivatorUtilities.CreateInstance<MyAgent>(this._sp, agentId, name ?? agentId, config);
var agent = ActivatorUtilities.CreateInstance<MyAgent>(
this._sp,
agentId,
name ?? agentId,
config);

await agent.StartAsync(cancellationToken).ConfigureAwait(false);
this.Agents.TryAdd(agentId, agent);
Expand Down
4 changes: 2 additions & 2 deletions examples/dotnet/dotnet-02-message-types-demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal static async Task Main(string[] args)
appBuilder.Services.AddSingleton<IAgentServiceStorage, AgentServiceStorage>();

// Agent service to support multiple agent instances
appBuilder.Services.AddSingleton<WorkbenchConnector, MyWorkbenchConnector>();
appBuilder.Services.AddSingleton<WorkbenchConnector<MyAgentConfig>, MyWorkbenchConnector>();

// Azure AI Content Safety, used to monitor I/O
appBuilder.Services.AddAzureAIContentSafety(appBuilder.Configuration.GetSection("AzureContentSafety"));
Expand All @@ -42,7 +42,7 @@ internal static async Task Main(string[] args)

// Connect to workbench backend, keep alive, and accept incoming requests
var connectorEndpoint = app.Configuration.GetSection("Workbench").Get<WorkbenchConfig>()!.ConnectorEndpoint;
using var agentService = app.UseAgentWebservice(connectorEndpoint, true);
using var agentService = app.UseAgentWebservice<MyAgentConfig>(connectorEndpoint, true);
await agentService.ConnectAsync().ConfigureAwait(false);

// Start app and webservice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReference Include="Azure.AI.ContentSafety" Version="1.0.0" />
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Microsoft.SemanticKernel" Version="1.26.0" />
<PackageReference Include="Microsoft.SemanticWorkbench.Connector" Version="0.2.241009.1" />
<PackageReference Include="Microsoft.SemanticWorkbench.Connector" Version="0.3.241104.1" />
</ItemGroup>

<PropertyGroup>
Expand Down Expand Up @@ -43,7 +43,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.12.7">
<PackageReference Include="Roslynator.Analyzers" Version="4.12.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace AgentExample;

public static class ConnectorExtensions
{
// TODO: the list of participants is incomplete, because agents see only participants being added
public static string GetParticipantName(this Conversation conversation, string id)
{
if (conversation.Participants.TryGetValue(id, out Participant? participant))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\libraries\dotnet\WorkbenchConnector\WorkbenchConnector.csproj" />
<!-- <PackageReference Include="Microsoft.SemanticWorkbench.Connector" Version="0.2.241009.1" />-->
<PackageReference Include="Microsoft.SemanticWorkbench.Connector" Version="0.3.241104.1" />
</ItemGroup>

<ItemGroup>
Expand Down Expand Up @@ -47,7 +46,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.12.7">
<PackageReference Include="Roslynator.Analyzers" Version="4.12.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down

0 comments on commit f237727

Please sign in to comment.