mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
904a5b843e
* Python: .NET Samples - Restructure and Improve Samples (Feature Branch) (#4091) * Moved by agent (#4094) * Fix readme links * .NET Samples - Create `04-hosting` learning path step (#4098) * Agent move * Agent reorderd * Remove A2A section from README Removed A2A section from the Getting Started README. * Agent fixed links * Fix broken sample links in durable-agents README (#4101) * Initial plan * Fix broken internal links in documentation Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Revert template link changes; keep only durable-agents README fix Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * .NET Samples - Create `03-workflows` learning path step (#4102) * Fix solution project path * Python: Fix broken markdown links to repo resources (outside /docs) (#4105) * Initial plan * Fix broken markdown links to repo resources Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Update README to rename .NET Workflows Samples section --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * .NET Samples - Create `02-agents` learning path step (#4107) * .NET: Fix broken relative link in GroupChatToolApproval README (#4108) * Initial plan * Fix broken link in GroupChatToolApproval README Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Update labeler configuration for workflow samples * .NET - Reorder Agents samples to start from Step01 instead of Step04 (#4110) * Fix solution * Resolve new sample paths * Move new AgentSkills and AgentWithMemory_Step04 samples * Fix link * Fix readme path * fix: update stale dotnet/samples/Durable path reference in AGENTS.md Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Moved new sample * Update solution * Resolve merge (new sample) * Sync to new sample - FoundryAgents_Step21_BingCustomSearch * Updated README * .NET Samples - Configuration Naming Update (#4149) * .NET: Restore AzureFunctions index parity with ConsoleApps under DurableAgents samples (#4221) * Clean-up `05_host_your_agent` * Config setting consistency * Refine samples * AGENTS.md * Move new samples * Re-order samples * Move new project and fixup solution * Fixup model config * Fix up new UT project --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
267 lines
9.8 KiB
C#
267 lines
9.8 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
namespace AgentWebChat.AppHost;
|
|
|
|
public static class ModelExtensions
|
|
{
|
|
public static IResourceBuilder<AIModel> AddAIModel(this IDistributedApplicationBuilder builder, string name)
|
|
{
|
|
var model = new AIModel(name);
|
|
return builder.CreateResourceBuilder(model);
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> RunAsOpenAI(this IResourceBuilder<AIModel> builder, string modelName, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
return builder.AsOpenAI(modelName, apiKey);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> PublishAsOpenAI(this IResourceBuilder<AIModel> builder, string modelName, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
|
|
{
|
|
return builder.AsOpenAI(modelName, apiKey);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> RunAsAzureOpenAI(this IResourceBuilder<AIModel> builder, string modelName, Action<IResourceBuilder<AzureOpenAIResource>>? configure)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
return builder.AsAzureOpenAI(modelName, configure);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> PublishAsAzureOpenAI(this IResourceBuilder<AIModel> builder, string modelName, Action<IResourceBuilder<AzureOpenAIResource>>? configure)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
|
|
{
|
|
return builder.AsAzureOpenAI(modelName, configure);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> AsAzureOpenAI(this IResourceBuilder<AIModel> builder, string modelName, Action<IResourceBuilder<AzureOpenAIResource>>? configure)
|
|
{
|
|
builder.Reset();
|
|
|
|
var openAIModel = builder.ApplicationBuilder.AddAzureOpenAI(builder.Resource.Name);
|
|
|
|
configure?.Invoke(openAIModel);
|
|
|
|
builder.Resource.UnderlyingResource = openAIModel.Resource;
|
|
// Add the model name to the connection string
|
|
builder.Resource.ConnectionString = ReferenceExpression.Create($"{openAIModel.Resource.ConnectionStringExpression};Model={modelName}");
|
|
builder.Resource.Provider = "AzureOpenAI";
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> RunAsAzureAIInference(this IResourceBuilder<AIModel> builder, string modelName, IResourceBuilder<ParameterResource> endpoint, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
return builder.AsAzureAIInference(modelName, endpoint, apiKey);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> PublishAsAzureAIInference(this IResourceBuilder<AIModel> builder, string modelName, IResourceBuilder<ParameterResource> endpoint, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
|
|
{
|
|
return builder.AsAzureAIInference(modelName, endpoint, apiKey);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> AsAzureAIInference(this IResourceBuilder<AIModel> builder, string modelName, IResourceBuilder<ParameterResource> endpoint, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
builder.Reset();
|
|
|
|
// See: https://github.com/dotnet/aspire/issues/7641
|
|
var csb = new ReferenceExpressionBuilder();
|
|
csb.Append($"Endpoint={endpoint.Resource};");
|
|
csb.Append($"AccessKey={apiKey.Resource};");
|
|
csb.Append($"Model={modelName}");
|
|
var cs = csb.Build();
|
|
|
|
builder.ApplicationBuilder.AddResource(builder.Resource);
|
|
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
var csTask = cs.GetValueAsync(default).AsTask();
|
|
if (!csTask.IsCompletedSuccessfully)
|
|
{
|
|
throw new InvalidOperationException("Connection string could not be resolved!");
|
|
}
|
|
|
|
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
|
|
builder.WithInitialState(new CustomResourceSnapshot
|
|
{
|
|
ResourceType = "Azure AI Inference Model",
|
|
State = KnownResourceStates.Running,
|
|
Properties = [
|
|
new("ConnectionString", csTask.Result ) { IsSensitive = true }
|
|
]
|
|
});
|
|
#pragma warning restore VSTHRD002
|
|
}
|
|
|
|
builder.Resource.UnderlyingResource = builder.Resource;
|
|
builder.Resource.ConnectionString = cs;
|
|
builder.Resource.Provider = "AzureAIInference";
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> RunAsAzureAIInference(this IResourceBuilder<AIModel> builder, string modelName, string endpoint, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
return builder.AsAzureAIInference(modelName, endpoint, apiKey);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> PublishAsAzureAIInference(this IResourceBuilder<AIModel> builder, string modelName, string endpoint, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
|
|
{
|
|
return builder.AsAzureAIInference(modelName, endpoint, apiKey);
|
|
}
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> AsAzureAIInference(this IResourceBuilder<AIModel> builder, string modelName, string endpoint, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
builder.Reset();
|
|
|
|
// See: https://github.com/dotnet/aspire/issues/7641
|
|
var csb = new ReferenceExpressionBuilder();
|
|
csb.Append($"Endpoint={endpoint};");
|
|
csb.Append($"AccessKey={apiKey.Resource};");
|
|
csb.Append($"Model={modelName}");
|
|
var cs = csb.Build();
|
|
|
|
builder.ApplicationBuilder.AddResource(builder.Resource);
|
|
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
var csTask = cs.GetValueAsync(default).AsTask();
|
|
if (!csTask.IsCompletedSuccessfully)
|
|
{
|
|
throw new InvalidOperationException("Connection string could not be resolved!");
|
|
}
|
|
|
|
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
|
|
builder.WithInitialState(new CustomResourceSnapshot
|
|
{
|
|
ResourceType = "Azure AI Inference Model",
|
|
State = KnownResourceStates.Running,
|
|
Properties = [
|
|
new("ConnectionString", csTask.Result ) { IsSensitive = true }
|
|
]
|
|
});
|
|
#pragma warning restore VSTHRD002
|
|
}
|
|
|
|
builder.Resource.UnderlyingResource = builder.Resource;
|
|
builder.Resource.ConnectionString = cs;
|
|
builder.Resource.Provider = "AzureAIInference";
|
|
|
|
return builder;
|
|
}
|
|
|
|
public static IResourceBuilder<AIModel> AsOpenAI(this IResourceBuilder<AIModel> builder, string modelName, IResourceBuilder<ParameterResource> apiKey)
|
|
{
|
|
builder.Reset();
|
|
|
|
// See: https://github.com/dotnet/aspire/issues/7641
|
|
var csb = new ReferenceExpressionBuilder();
|
|
csb.Append($"AccessKey={apiKey.Resource};");
|
|
csb.Append($"Model={modelName}");
|
|
var cs = csb.Build();
|
|
|
|
builder.ApplicationBuilder.AddResource(builder.Resource);
|
|
|
|
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
|
|
{
|
|
var csTask = cs.GetValueAsync(default).AsTask();
|
|
if (!csTask.IsCompletedSuccessfully)
|
|
{
|
|
throw new InvalidOperationException("Connection string could not be resolved!");
|
|
}
|
|
|
|
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
|
|
builder.WithInitialState(new CustomResourceSnapshot
|
|
{
|
|
ResourceType = "OpenAI Model",
|
|
State = KnownResourceStates.Running,
|
|
Properties = [
|
|
new("ConnectionString", csTask.Result ) { IsSensitive = true }
|
|
]
|
|
});
|
|
#pragma warning restore VSTHRD002
|
|
}
|
|
|
|
builder.Resource.UnderlyingResource = builder.Resource;
|
|
builder.Resource.ConnectionString = cs;
|
|
builder.Resource.Provider = "OpenAI";
|
|
|
|
return builder;
|
|
}
|
|
|
|
private static void Reset(this IResourceBuilder<AIModel> builder)
|
|
{
|
|
// Reset the properties of the AIModel resource
|
|
if (builder.Resource.UnderlyingResource is { } underlyingResource)
|
|
{
|
|
builder.ApplicationBuilder.Resources.Remove(underlyingResource);
|
|
|
|
if (underlyingResource is IResourceWithParent resourceWithParent)
|
|
{
|
|
builder.ApplicationBuilder.Resources.Remove(resourceWithParent.Parent);
|
|
}
|
|
}
|
|
|
|
builder.Resource.ConnectionString = null;
|
|
builder.Resource.Provider = null;
|
|
}
|
|
}
|
|
|
|
// A resource representing an AI model.
|
|
public class AIModel(string name) : Resource(name), IResourceWithConnectionString
|
|
{
|
|
internal string? Provider { get; set; }
|
|
internal IResourceWithConnectionString? UnderlyingResource { get; set; }
|
|
internal ReferenceExpression? ConnectionString { get; set; }
|
|
|
|
public ReferenceExpression ConnectionStringExpression =>
|
|
this.Build();
|
|
|
|
public ReferenceExpression Build()
|
|
{
|
|
var connectionString = this.ConnectionString ?? throw new InvalidOperationException("No connection string available.");
|
|
|
|
if (this.Provider is null)
|
|
{
|
|
throw new InvalidOperationException("No provider configured.");
|
|
}
|
|
|
|
return ReferenceExpression.Create($"{connectionString};Provider={this.Provider}");
|
|
}
|
|
}
|