chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<Sdk Name="Aspire.AppHost.Sdk" Version="13.0.0" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
<UserSecretsId>61efcc24-41eb-4a92-8ebe-64de14ed54dd</UserSecretsId>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" />
<PackageReference Include="MessagePack" /> <!-- Override vulnerable transitive dependency (2.5.192) from Aspire packages -->
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\src\Experimental\Process.LocalRuntime\Process.LocalRuntime.csproj">
<IsAspireProjectResource>false</IsAspireProjectResource>
</ProjectReference>
<ProjectReference Include="..\ProcessFramework.Aspire.ProcessOrchestrator\ProcessFramework.Aspire.ProcessOrchestrator.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.SummaryAgent\ProcessFramework.Aspire.SummaryAgent.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.TranslatorAgent\ProcessFramework.Aspire.TranslatorAgent.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft. All rights reserved.
var builder = DistributedApplication.CreateBuilder(args);
var openai = builder.AddConnectionString("openAiConnectionName");
var translateAgent = builder.AddProject<Projects.ProcessFramework_Aspire_TranslatorAgent>("translatoragent")
.WithReference(openai);
var summaryAgent = builder.AddProject<Projects.ProcessFramework_Aspire_SummaryAgent>("summaryagent")
.WithReference(openai);
var processOrchestrator = builder.AddProject<Projects.ProcessFramework_Aspire_ProcessOrchestrator>("processorchestrator")
.WithReference(translateAgent)
.WithReference(summaryAgent)
.WithHttpCommand("/api/processdoc", "Trigger Process",
commandOptions: new()
{
Method = HttpMethod.Get
}
);
builder.Build().Run();
@@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
}
},
"ConnectionStrings": {
"openAiConnectionName": "https://{account_name}.openai.azure.com/"
}
}
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
namespace ProcessFramework.Aspire.ProcessOrchestrator.Models;
public static class ProcessEvents
{
public static readonly string TranslateDocument = nameof(TranslateDocument);
public static readonly string DocumentTranslated = nameof(DocumentTranslated);
public static readonly string SummarizeDocument = nameof(SummarizeDocument);
public static readonly string DocumentSummarized = nameof(DocumentSummarized);
}
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>
$(NoWarn);CS8618,IDE0009,CA1051,CA1050,CA1707,CA1054,CA2007,VSTHRD111,CS1591,RCS1110,RCS1243,CA5394,SKEXP0001,SKEXP0010,SKEXP0040,SKEXP0050,SKEXP0060,SKEXP0080,SKEXP0101,SKEXP0110,OPENAI001
</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Azure.AI.OpenAI" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\src\Experimental\Process.Core\Process.Core.csproj" />
<ProjectReference Include="..\..\..\..\..\src\Experimental\Process.LocalRuntime\Process.LocalRuntime.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.ServiceDefaults\ProcessFramework.Aspire.ServiceDefaults.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.Shared\ProcessFramework.Aspire.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,5 @@
GET https://localhost:7207/api/processdoc
Accept: application/json
###
@@ -0,0 +1,58 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.SemanticKernel;
using ProcessFramework.Aspire.ProcessOrchestrator;
using ProcessFramework.Aspire.ProcessOrchestrator.Models;
using ProcessFramework.Aspire.ProcessOrchestrator.Steps;
var builder = WebApplication.CreateBuilder(args);
AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true);
builder.AddServiceDefaults();
builder.Services.AddHttpClient<TranslatorAgentHttpClient>(client => { client.BaseAddress = new("https+http://translatoragent"); });
builder.Services.AddHttpClient<SummaryAgentHttpClient>(client => { client.BaseAddress = new("https+http://summaryagent"); });
builder.Services.AddSingleton(builder =>
{
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.Services.AddSingleton(builder.GetRequiredService<TranslatorAgentHttpClient>());
kernelBuilder.Services.AddSingleton(builder.GetRequiredService<SummaryAgentHttpClient>());
return kernelBuilder.Build();
});
var app = builder.Build();
app.UseHttpsRedirection();
app.MapGet("/api/processdoc", async (Kernel kernel) =>
{
var processBuilder = new ProcessBuilder("ProcessDocument");
var translateDocumentStep = processBuilder.AddStepFromType<TranslateStep>();
var summarizeDocumentStep = processBuilder.AddStepFromType<SummarizeStep>();
processBuilder
.OnInputEvent(ProcessEvents.TranslateDocument)
.SendEventTo(new(translateDocumentStep, TranslateStep.ProcessFunctions.Translate, parameterName: "textToTranslate"));
translateDocumentStep
.OnEvent(ProcessEvents.DocumentTranslated)
.SendEventTo(new ProcessFunctionTargetBuilder(summarizeDocumentStep, SummarizeStep.ProcessFunctions.Summarize, parameterName: "textToSummarize"));
summarizeDocumentStep
.OnEvent(ProcessEvents.DocumentSummarized)
.StopProcess();
var process = processBuilder.Build();
await using var runningProcess = await process.StartAsync(
kernel,
new KernelProcessEvent { Id = ProcessEvents.TranslateDocument, Data = "COME I FORNITORI INFLUENZANO I TUOI COSTI Quando scegli un piano di assicurazione sanitaria, uno dei fattori più importanti da considerare è la rete di fornitori in convenzione disponibili con il piano. Northwind Standard offre un'ampia varietà di fornitori in convenzione, tra cui medici di base, specialisti, ospedali e farmacie. Questo ti permette di scegliere un fornitore comodo per te e la tua famiglia, contribuendo al contempo a mantenere bassi i tuoi costi. Se scegli un fornitore in convenzione con il tuo piano, pagherai generalmente copay e franchigie più basse rispetto a un fornitore fuori rete. Inoltre, molti servizi, come l'assistenza preventiva, possono essere coperti senza alcun costo aggiuntivo se ricevuti da un fornitore in convenzione. È importante notare, tuttavia, che Northwind Standard non copre i servizi di emergenza, l'assistenza per la salute mentale e l'abuso di sostanze, né i servizi fuori rete. Questo significa che potresti dover pagare di tasca tua per questi servizi se ricevuti da un fornitore fuori rete. Quando scegli un fornitore in convenzione, ci sono alcuni suggerimenti da tenere a mente. Verifica che il fornitore sia in convenzione con il tuo piano. Puoi confermarlo chiamando l'ufficio del fornitore e chiedendo se è in rete con Northwind Standard. Puoi anche utilizzare lo strumento di ricerca fornitori sul sito web di Northwind Health per verificare la copertura. Assicurati che il fornitore stia accettando nuovi pazienti. Alcuni fornitori potrebbero essere in convenzione ma non accettare nuovi pazienti. Considera la posizione del fornitore. Se il fornitore è troppo lontano, potrebbe essere difficile raggiungere gli appuntamenti. Valuta gli orari dell'ufficio del fornitore. Se lavori durante il giorno, potresti aver bisogno di trovare un fornitore con orari serali o nel fine settimana. Scegliere un fornitore in convenzione può aiutarti a risparmiare sui costi sanitari. Seguendo i suggerimenti sopra e facendo ricerche sulle opzioni disponibili, puoi trovare un fornitore conveniente, accessibile e in rete con il tuo piano Northwind Standard." }
);
return Results.Ok("Process completed successfully");
});
app.MapDefaultEndpoints();
app.Run();
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.SemanticKernel;
using ProcessFramework.Aspire.ProcessOrchestrator.Models;
namespace ProcessFramework.Aspire.ProcessOrchestrator.Steps;
public class SummarizeStep : KernelProcessStep
{
public static class ProcessFunctions
{
public const string Summarize = nameof(Summarize);
}
[KernelFunction(ProcessFunctions.Summarize)]
public async ValueTask SummarizeAsync(KernelProcessStepContext context, Kernel kernel, string textToSummarize)
{
var summaryAgentHttpClient = kernel.GetRequiredService<SummaryAgentHttpClient>();
var summarizedText = await summaryAgentHttpClient.SummarizeAsync(textToSummarize);
Console.WriteLine($"Summarized text: {summarizedText}");
await context.EmitEventAsync(new() { Id = ProcessEvents.DocumentSummarized, Data = summarizedText });
}
}
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.SemanticKernel;
using ProcessFramework.Aspire.ProcessOrchestrator.Models;
namespace ProcessFramework.Aspire.ProcessOrchestrator.Steps;
public class TranslateStep : KernelProcessStep
{
public static class ProcessFunctions
{
public const string Translate = nameof(Translate);
}
[KernelFunction(ProcessFunctions.Translate)]
public async ValueTask TranslateAsync(KernelProcessStepContext context, Kernel kernel, string textToTranslate)
{
var translatorAgentHttpClient = kernel.GetRequiredService<TranslatorAgentHttpClient>();
var translatedText = await translatorAgentHttpClient.TranslateAsync(textToTranslate);
Console.WriteLine($"Translated text: {translatedText}");
await context.EmitEventAsync(new() { Id = ProcessEvents.DocumentTranslated, Data = translatedText });
}
}
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Text;
using System.Text.Json;
using ProcessFramework.Aspire.Shared;
namespace ProcessFramework.Aspire.ProcessOrchestrator;
public class SummaryAgentHttpClient(HttpClient httpClient)
{
public async Task<string> SummarizeAsync(string textToSummarize)
{
var payload = new SummarizeRequest { TextToSummarize = textToSummarize };
#pragma warning disable CA2234 // We cannot pass uri here since we are using a customer http client with a base address
var response = await httpClient.PostAsync("/api/summary", new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
return responseContent;
}
}
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Text;
using System.Text.Json;
using ProcessFramework.Aspire.Shared;
namespace ProcessFramework.Aspire.ProcessOrchestrator;
public class TranslatorAgentHttpClient(HttpClient httpClient)
{
public async Task<string> TranslateAsync(string textToTranslate)
{
var payload = new TranslationRequest { TextToTranslate = textToTranslate };
#pragma warning disable CA2234 // We cannot pass uri here since we are using a customer http client with a base address
var response = await httpClient.PostAsync("/api/translator", new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
return responseContent;
}
}
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
@@ -0,0 +1,157 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace Microsoft.Extensions.Hosting;
/// <summary>
/// Provides extension methods for adding common .NET Aspire services, including service discovery,
/// resilience, health checks, and OpenTelemetry.
/// </summary>
public static class CommonExtensions
{
private const string HealthEndpointPath = "/health";
private const string AlivenessEndpointPath = "/alive";
/// <summary>
/// Adds default services to the application, including OpenTelemetry, health checks,
/// service discovery, and HTTP client defaults with resilience and service discovery enabled.
/// </summary>
/// <typeparam name="TBuilder">The type of the host application builder.</typeparam>
/// <param name="builder">The host application builder instance.</param>
/// <returns>The updated host application builder.</returns>
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.ConfigureHttpClientDefaults(http =>
{
// Turn on resilience by default
http.AddStandardResilienceHandler();
// Turn on service discovery by default
http.AddServiceDiscovery();
});
// Uncomment the following to restrict the allowed schemes for service discovery.
// builder.Services.Configure<ServiceDiscoveryOptions>(options =>
// {
// options.AllowedSchemes = ["https"];
// });
return builder;
}
/// <summary>
/// Configures OpenTelemetry for the application, including logging, metrics, and tracing.
/// </summary>
/// <typeparam name="TBuilder">The type of the host application builder.</typeparam>
/// <param name="builder">The host application builder instance.</param>
/// <returns>The updated host application builder.</returns>
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
builder.Logging.AddTraceSource("Microsoft.SemanticKernel");
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation()
.AddMeter("Microsoft.SemanticKernel*");
})
.WithTracing(tracing =>
{
tracing.AddSource(builder.Environment.ApplicationName)
.AddAspNetCoreInstrumentation(tracing =>
// Exclude health check requests from tracing
tracing.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath)
&& !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
)
// Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
//.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("Microsoft.SemanticKernel*");
});
builder.AddOpenTelemetryExporters();
return builder;
}
private static TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
if (useOtlpExporter)
{
builder.Services.AddOpenTelemetry().UseOtlpExporter();
}
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
//{
// builder.Services.AddOpenTelemetry()
// .UseAzureMonitor();
//}
return builder;
}
/// <summary>
/// Adds default health checks to the application, including a liveness check to ensure the app is responsive.
/// </summary>
/// <typeparam name="TBuilder">The type of the host application builder.</typeparam>
/// <param name="builder">The host application builder instance.</param>
/// <returns>The updated host application builder.</returns>
public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
builder.Services.AddHealthChecks()
// Add a default liveness check to ensure app is responsive
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
return builder;
}
/// <summary>
/// Maps default health check endpoints for the application.
/// Adds "/health" and "/alive" endpoints in development environments.
/// </summary>
/// <param name="app">The web application instance.</param>
/// <returns>The updated web application instance.</returns>
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
// Adding health checks endpoints to applications in non-development environments has security implications.
// See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
if (app.Environment.IsDevelopment())
{
// All health checks must pass for app to be considered ready to accept traffic after starting
app.MapHealthChecks(HealthEndpointPath);
// Only health checks tagged with the "live" tag must pass for app to be considered alive
app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live")
});
}
return app;
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireSharedProject>true</IsAspireSharedProject>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
</ItemGroup>
</Project>
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CA1716</NoWarn>
</PropertyGroup>
</Project>
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
namespace ProcessFramework.Aspire.Shared;
/// <summary>
/// Represents a request to summarize a given text.
/// </summary>
public class SummarizeRequest
{
/// <summary>
/// Gets or sets the text to be summarized.
/// </summary>
public string TextToSummarize { get; set; } = string.Empty;
}
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
namespace ProcessFramework.Aspire.Shared;
/// <summary>
/// Represents a request to translate a given text.
/// </summary>
public class TranslationRequest
{
/// <summary>
/// Gets or sets the text to be translated.
/// </summary>
public string TextToTranslate { get; set; } = string.Empty;
}
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>SKEXP0001,SKEXP0050,SKEXP0110</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Azure.AI.OpenAI" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
<ProjectReference Include="..\..\..\..\..\src\Connectors\Connectors.AzureOpenAI\Connectors.AzureOpenAI.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.ServiceDefaults\ProcessFramework.Aspire.ServiceDefaults.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.Shared\ProcessFramework.Aspire.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,9 @@
POST https://localhost:7261/api/summary
Accept: application/json
Content-Type: application/json
{
"TextToSummarize": "HOW PROVIDERS AFFECT YOUR COSTS When selecting a health insurance plan, one of the most important factors to consider is the network of in-network providers that are available with the plan. Northwind Standard offers a wide variety of in-network providers, ranging from primary care physicians, specialists, hospitals, and pharmacies. This allows you to choose a provider that is convenient for you and your family, while also helping you to keep your costs low. When you choose a provider that is in-network with your plan, you will typically pay lower copays and deductibles than you would with an out-of-network provider. In addition, many services, such as preventive care, may be covered at no cost when you receive care from an in-network provider. It is important to note, however, that Northwind Standard does not offer coverage for emergency services, mental health and substance abuse coverage, or out-of-network services. This means that you may have to pay out of pocket for these services if you receive them from an out-of-network provider. When choosing an in-network provider, there are a few tips to keep in mind. First, make sure that the provider you choose is in-network with your plan. You can confirm this by calling the provider's office and asking them if they are in-network with Northwind Standard. You can also use the provider search tool on the Northwind Health website to make sure your provider is in-network. Second, make sure that the provider you choose is accepting new patients. Some providers may be in-network but not be taking new patients. Third, consider the location of the provider. If the provider is too far away, it may be difficult for you to get to your appointments. Finally, consider the provider's office hours. If you work during the day, you may need to find a provider that has evening or weekend hours. Choosing an in-network provider can help you save money on your health care costs. By following the tips above and researching your options, you can find a provider that is convenient, affordable, and in-network with your Northwind Standard plan."
}
###
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
using ProcessFramework.Aspire.Shared;
var builder = WebApplication.CreateBuilder(args);
AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true);
builder.AddServiceDefaults();
builder.AddAzureOpenAIClient("openAiConnectionName");
builder.Services.AddKernel().AddAzureOpenAIChatCompletion("gpt-4o");
var app = builder.Build();
app.UseHttpsRedirection();
app.MapPost("/api/summary", async (Kernel kernel, SummarizeRequest summarizeRequest) =>
{
ChatCompletionAgent summaryAgent =
new()
{
Name = "SummarizationAgent",
Instructions = "Summarize user input",
Kernel = kernel
};
// Add a user message to the conversation
var message = new ChatMessageContent(AuthorRole.User, summarizeRequest.TextToSummarize);
// Generate the agent response(s)
await foreach (ChatMessageContent response in summaryAgent.InvokeAsync(message).ConfigureAwait(false))
{
return response.Items.Last().ToString();
}
return null;
});
app.MapDefaultEndpoints();
app.Run();
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>SKEXP0001,SKEXP0050,SKEXP0110</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Azure.AI.OpenAI" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
<ProjectReference Include="..\..\..\..\..\src\Connectors\Connectors.AzureOpenAI\Connectors.AzureOpenAI.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.ServiceDefaults\ProcessFramework.Aspire.ServiceDefaults.csproj" />
<ProjectReference Include="..\ProcessFramework.Aspire.Shared\ProcessFramework.Aspire.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,9 @@
POST https://localhost:7228/api/translator
Accept: application/json
Content-Type: application/json
{
"TextToTranslate": "COME I FORNITORI INFLUENZANO I TUOI COSTI Quando scegli un piano di assicurazione sanitaria, uno dei fattori più importanti da considerare è la rete di fornitori in convenzione disponibili con il piano. Northwind Standard offre un'ampia varietà di fornitori in convenzione, tra cui medici di base, specialisti, ospedali e farmacie. Questo ti permette di scegliere un fornitore comodo per te e la tua famiglia, contribuendo al contempo a mantenere bassi i tuoi costi. Se scegli un fornitore in convenzione con il tuo piano, pagherai generalmente copay e franchigie più basse rispetto a un fornitore fuori rete. Inoltre, molti servizi, come l'assistenza preventiva, possono essere coperti senza alcun costo aggiuntivo se ricevuti da un fornitore in convenzione. È importante notare, tuttavia, che Northwind Standard non copre i servizi di emergenza, l'assistenza per la salute mentale e l'abuso di sostanze, né i servizi fuori rete. Questo significa che potresti dover pagare di tasca tua per questi servizi se ricevuti da un fornitore fuori rete. Quando scegli un fornitore in convenzione, ci sono alcuni suggerimenti da tenere a mente. Verifica che il fornitore sia in convenzione con il tuo piano. Puoi confermarlo chiamando l'ufficio del fornitore e chiedendo se è in rete con Northwind Standard. Puoi anche utilizzare lo strumento di ricerca fornitori sul sito web di Northwind Health per verificare la copertura. Assicurati che il fornitore stia accettando nuovi pazienti. Alcuni fornitori potrebbero essere in convenzione ma non accettare nuovi pazienti. Considera la posizione del fornitore. Se il fornitore è troppo lontano, potrebbe essere difficile raggiungere gli appuntamenti. Valuta gli orari dell'ufficio del fornitore. Se lavori durante il giorno, potresti aver bisogno di trovare un fornitore con orari serali o nel fine settimana. Scegliere un fornitore in convenzione può aiutarti a risparmiare sui costi sanitari. Seguendo i suggerimenti sopra e facendo ricerche sulle opzioni disponibili, puoi trovare un fornitore conveniente, accessibile e in rete con il tuo piano Northwind Standard."
}
###
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
using ProcessFramework.Aspire.Shared;
var builder = WebApplication.CreateBuilder(args);
AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true);
builder.AddServiceDefaults();
builder.AddAzureOpenAIClient("openAiConnectionName");
builder.Services.AddKernel().AddAzureOpenAIChatCompletion("gpt-4o");
var app = builder.Build();
app.UseHttpsRedirection();
app.MapPost("/api/translator", async (Kernel kernel, TranslationRequest translationRequest) =>
{
ChatCompletionAgent summaryAgent =
new()
{
Name = "TranslatorAgent",
Instructions = "Translate user input in english",
Kernel = kernel
};
// Add a user message to the conversation
var message = new ChatMessageContent(AuthorRole.User, translationRequest.TextToTranslate);
// Generate the agent response(s)
await foreach (ChatMessageContent response in summaryAgent.InvokeAsync(message).ConfigureAwait(false))
{
return response.Items.Last().ToString();
}
return null;
});
app.MapDefaultEndpoints();
app.Run();
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
@@ -0,0 +1,45 @@
# Process Framework with .NET Aspire
This demo illustrates how the [Semantic Kernel Process Framework](https://learn.microsoft.com/semantic-kernel/overview) can be integrated with [.NET Aspire](https://learn.microsoft.com/dotnet/aspire/get-started/aspire-overview). The Process Framework enables the creation of business processes based on events, where each process step may invoke an agent or execute native code.
In the demo, agents are defined as **external services**. Each process step issues an HTTP request to call these agents, allowing .NET Aspire to trace the process using **OpenTelemetry**. Furthermore, because each agent is a standalone service, they can be restarted independently via the .NET Aspire developer dashboard.
## Architecture
The business logic of this sample is straightforward: it defines a process that translates text from English and subsequently summarizes it.
![Architecture Diagram](./docs/architecture.png)
## What is .NET Aspire?
.NET Aspire is a set of tools, templates, and packages for building observable, production ready apps. .NET Aspire is delivered through a collection of NuGet packages that bootstrap or improve common challenges in modern app development.
Key features include:
- Dev-Time Orchestration: provides features for running and connecting multi-project applications, container resources, and other dependencies for local development environments.
- Integrations: offers standardized NuGet packages for frequently used services such as Redis and Postgres, with standardized interfaces ensuring they consistent and seamless connectivity.
- Tooling: includes project templates and tools for Visual Studio, Visual Studio Code, and the .NET CLI to help creating and interacting with .NET Aspire projects.
.NET Aspire orchestration assists with the following concerns:
- App composition: specify the .NET projects, containers, executables, and cloud resources that make up the application.
- Service Discovery and Connection String Management: automatically injects the right connection strings, network configurations, and service discovery information to simplify the developer experience.
### Running with .NET Aspire
To run this sample with .NET Aspire, clone the repository and execute the following commands:
```bash
cd scr/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost
dotnet run
```
A dashboard will then be displayed in the browser, similar to this:
![Aspire Dashboard](./docs/aspire-dashboard.png)
By invoking the `ProcessOrchestrator` service, the process can be started. A predefined request is available in [`ProcessFramework.Aspire.ProcessOrchestrator.http``](./ProcessFramework.Aspire/ProcessFramework.Aspire.ProcessOrchestrator/ProcessFramework.Aspire.ProcessOrchestrator.http).
This will generate a trace in the Aspire dashboard that looks like this:
![Aspire Trace](./docs/aspire-traces.png)
Additionally, the metrics for each agent can be monitored in the Metrics tab:
![Aspire Metrics](./docs/aspire-metrics.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB