-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
On localhost launch all .NET + python examples + assistants in Aspire (…
…#272) * When running Aspire locally, load all .NET agent examples, all python examples, all python assistants * Fix Aspire `uv` extension not to change `uv.lock` files * Automatically open Aspire dashboard in browser * Improve connector ping logic ![image](https://github.com/user-attachments/assets/1c0fd578-97ba-473f-b46a-aa365c2cd723) ![image](https://github.com/user-attachments/assets/b11b6fa7-c67b-4928-9bb0-45ba80aca9e6)
- Loading branch information
Showing
17 changed files
with
218 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,117 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
var builder = DistributedApplication.CreateBuilder(args); | ||
|
||
var authority = builder.AddParameterFromConfiguration("authority", "EntraId:Authority"); | ||
var clientId = builder.AddParameterFromConfiguration("clientId", "EntraId:ClientId"); | ||
|
||
// Workbench backend | ||
var workbenchService = builder.AddWorkbenchService("workbenchservice", projectDirectory: Path.Combine("..", "..", "workbench-service"), clientId: clientId); | ||
var workbenchServiceEndpoint = workbenchService.GetSemanticWorkbenchEndpoint(builder.ExecutionContext.IsPublishMode); | ||
|
||
// Workbench frontend | ||
var workbenchApp = builder.AddViteApp("workbenchapp", workingDirectory: Path.Combine("..", "..", "workbench-app"), packageManager: "pnpm") | ||
.WithPnpmPackageInstallation() | ||
.WithEnvironment(name: "VITE_SEMANTIC_WORKBENCH_SERVICE_URL", workbenchServiceEndpoint) | ||
.WaitFor(workbenchService) | ||
.PublishAsDockerFile([ | ||
new DockerBuildArg("VITE_SEMANTIC_WORKBENCH_CLIENT_ID", clientId.Resource.Value), | ||
new DockerBuildArg("VITE_SEMANTIC_WORKBENCH_AUTHORITY", authority.Resource.Value), | ||
]); | ||
|
||
// Sample Python agent | ||
builder.AddAssistantApp("skill-assistant", projectDirectory: Path.Combine("..", "..", "assistants", "skill-assistant"), assistantModuleName: "skill-assistant") | ||
.WithEnvironment(name: "assistant__workbench_service_url", workbenchServiceEndpoint); | ||
|
||
// Sample .NET agent | ||
var simpleChatBot = builder.AddProject<Projects.dotnet_03_simple_chatbot>("simple-chatbot-dotnet") | ||
.WithHttpEndpoint() | ||
.WaitFor(workbenchService) | ||
.WithEnvironment(name: "Workbench__WorkbenchEndpoint", workbenchServiceEndpoint); | ||
|
||
simpleChatBot.WithEnvironment("Workbench__ConnectorHost", $"{simpleChatBot.GetEndpoint("http")}"); | ||
|
||
if (!builder.ExecutionContext.IsPublishMode) | ||
using Aspire.Hosting.Extensions; | ||
using Projects; | ||
|
||
internal static class Program | ||
{ | ||
workbenchApp.WithHttpsEndpoint(env: "PORT"); | ||
} | ||
public static void Main(string[] args) | ||
{ | ||
var builder = DistributedApplication.CreateBuilder(args); | ||
|
||
builder | ||
.AddSemanticWorkbench(out IResourceBuilder<ExecutableResource> workbenchBackend, out EndpointReference workbenchEndpoint) | ||
.AddPythonAssistant("skill-assistant", workbenchEndpoint) | ||
.AddDotnetExample<dotnet_03_simple_chatbot>("simple-chatbot-dotnet", workbenchBackend, workbenchEndpoint); | ||
|
||
// When running locally | ||
if (!builder.ExecutionContext.IsPublishMode) | ||
{ | ||
builder | ||
.AddPythonExample("python-01-echo-bot", workbenchEndpoint) | ||
.AddPythonExample("python-02-simple-chatbot", workbenchEndpoint) | ||
.AddPythonExample("python-03-multimodel-chatbot", workbenchEndpoint) | ||
.AddPythonAssistant("explorer-assistant", workbenchEndpoint) | ||
.AddPythonAssistant("guided-conversation-assistant", workbenchEndpoint) | ||
.AddPythonAssistant("prospector-assistant", workbenchEndpoint) | ||
.AddDotnetExample<dotnet_01_echo_bot>("echo-bot-dotnet", workbenchBackend, workbenchEndpoint) | ||
.AddDotnetExample<dotnet_02_message_types_demo>("sw-tutorial-bot-dotnet", workbenchBackend, workbenchEndpoint); | ||
} | ||
|
||
builder | ||
.ShowDashboardUrl(true) | ||
.LaunchDashboard(delay: 5000) | ||
.Build() | ||
.Run(); | ||
} | ||
|
||
/// <summary> | ||
/// Add the workbench frontend and backend components | ||
/// </summary> | ||
private static IDistributedApplicationBuilder AddSemanticWorkbench(this IDistributedApplicationBuilder builder, | ||
out IResourceBuilder<ExecutableResource> workbenchBackend, out EndpointReference workbenchServiceEndpoint) | ||
{ | ||
var authority = builder.AddParameterFromConfiguration("authority", "EntraId:Authority"); | ||
var clientId = builder.AddParameterFromConfiguration("clientId", "EntraId:ClientId"); | ||
|
||
// Workbench backend | ||
workbenchBackend = builder.AddWorkbenchService( | ||
name: "workbenchservice", | ||
projectDirectory: Path.Combine("..", "..", "workbench-service"), | ||
clientId: clientId); | ||
|
||
workbenchServiceEndpoint = workbenchBackend.GetSemanticWorkbenchEndpoint(builder.ExecutionContext.IsPublishMode); | ||
|
||
// Workbench frontend | ||
var workbenchApp = builder.AddViteApp( | ||
name: "workbenchapp", | ||
workingDirectory: Path.Combine("..", "..", "workbench-app"), | ||
packageManager: "pnpm") | ||
.WithPnpmPackageInstallation() | ||
.WithEnvironment(name: "VITE_SEMANTIC_WORKBENCH_SERVICE_URL", workbenchServiceEndpoint) | ||
.WaitFor(workbenchBackend) | ||
.PublishAsDockerFile([ | ||
new DockerBuildArg("VITE_SEMANTIC_WORKBENCH_CLIENT_ID", clientId.Resource.Value), | ||
new DockerBuildArg("VITE_SEMANTIC_WORKBENCH_AUTHORITY", authority.Resource.Value), | ||
]); | ||
|
||
builder.Build().Run(); | ||
// When running locally | ||
if (!builder.ExecutionContext.IsPublishMode) | ||
{ | ||
workbenchApp.WithHttpsEndpoint(env: "PORT"); | ||
} | ||
|
||
return builder; | ||
} | ||
|
||
private static IDistributedApplicationBuilder AddPythonAssistant(this IDistributedApplicationBuilder builder, | ||
string name, EndpointReference workbenchServiceEndpoint) | ||
{ | ||
builder | ||
.AddAssistantUvPythonApp( | ||
name: name, | ||
projectDirectory: Path.Combine("..", "..", "assistants", name), | ||
assistantModuleName: name) | ||
.WithEnvironment(name: "assistant__workbench_service_url", workbenchServiceEndpoint); | ||
|
||
return builder; | ||
} | ||
|
||
private static IDistributedApplicationBuilder AddPythonExample(this IDistributedApplicationBuilder builder, | ||
string name, EndpointReference workbenchServiceEndpoint) | ||
{ | ||
builder | ||
.AddAssistantUvPythonApp( | ||
name: name, | ||
projectDirectory: Path.Combine("..", "..", "examples", "python", name), | ||
assistantModuleName: "assistant") | ||
.WithEnvironment(name: "assistant__workbench_service_url", workbenchServiceEndpoint); | ||
|
||
return builder; | ||
} | ||
|
||
// .NET Agent Example 1 | ||
private static IDistributedApplicationBuilder AddDotnetExample<T>(this IDistributedApplicationBuilder builder, | ||
string name, IResourceBuilder<ExecutableResource> workbenchBackend, EndpointReference workbenchServiceEndpoint) where T : IProjectMetadata, new() | ||
{ | ||
var agent = builder | ||
.AddProject<T>(name: name) | ||
.WithHttpEndpoint() | ||
.WaitFor(workbenchBackend) | ||
.WithEnvironment(name: "Workbench__WorkbenchEndpoint", workbenchServiceEndpoint); | ||
|
||
agent.WithEnvironment("Workbench__ConnectorHost", $"{agent.GetEndpoint("http")}"); | ||
|
||
return builder; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using System.Diagnostics; | ||
|
||
namespace Aspire.Hosting.Extensions; | ||
|
||
public static class Dashboard | ||
{ | ||
/// <summary> | ||
/// Show Aspire dashboard URL before the logging start. | ||
/// </summary> | ||
public static IDistributedApplicationBuilder ShowDashboardUrl(this IDistributedApplicationBuilder builder, bool withStyle = false) | ||
{ | ||
Console.WriteLine(withStyle | ||
? $"\u001b[1mAspire dashboard URL: {GetUrl(builder)}\u001b[0m\n\n" | ||
: $"Aspire dashboard URL: {GetUrl(builder)}\n\n"); | ||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Wait 5 seconds and automatically open the browser (when using 'dotnet run' the browser doesn't open) | ||
/// </summary> | ||
public static IDistributedApplicationBuilder LaunchDashboard(this IDistributedApplicationBuilder builder, int delay = 5000) | ||
{ | ||
Task.Run(async () => | ||
{ | ||
await Task.Delay(delay).ConfigureAwait(false); | ||
Process.Start(new ProcessStartInfo { FileName = GetUrl(builder), UseShellExecute = true }); | ||
}); | ||
|
||
return builder; | ||
} | ||
|
||
private static string GetUrl(IDistributedApplicationBuilder builder) | ||
{ | ||
string token = builder.Configuration["AppHost:BrowserToken"] ?? string.Empty; | ||
string url = builder.Configuration["ASPNETCORE_URLS"]?.Split(";")[0] ?? throw new ArgumentException("ASPNETCORE_URLS is empty"); | ||
return $"{url}/login?t={token}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,4 +35,4 @@ fi | |
|
||
cd Aspire.AppHost | ||
|
||
dotnet run | ||
dotnet run --launch-profile https |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.