Skip to content

Commit

Permalink
Allow to reuse KM service Builder and config extensions (#901)
Browse files Browse the repository at this point in the history
Allow to reuse KM configuration utilities in other apps.

* `IConfigurationBuilder.AddKernelMemoryConfigurationSources(...)`: adds
to .NET ConfigurationBuilder the sources used by KM service, such as
`appsettings.json`, `appsettings.<ENV>.json` (not case sensitive), user
secrets and env vars. Extension available in
[Microsoft.KernelMemory.Core](https://www.nuget.org/packages/Microsoft.KernelMemory.Core)
nuget.
* `IKernelMemoryBuilder.ConfigureDependencies(...)`: configures and
wires up all .NET dependencies accordingly to the given configuration.
Extension available in
[Microsoft.KernelMemory](https://www.nuget.org/packages/Microsoft.KernelMemory)
nuget.
  • Loading branch information
dluc authored Nov 19, 2024
1 parent f119e58 commit 6173e9b
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 203 deletions.

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions extensions/KM/KernelMemory/KernelMemoryBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft. All rights reserved.

using Microsoft.Extensions.Configuration;
using Microsoft.KernelMemory.Internals;

// ReSharper disable once CheckNamespace - reduce number of "using" statements
namespace Microsoft.KernelMemory;

/// <summary>
/// Kernel Memory builder extensions for ASP.NET apps using settings in appsettings.json
/// and using IConfiguration. The following methods allow to fully configure KM via
/// IConfiguration, without having to change the code using KernelMemoryBuilder and recompile.
/// </summary>
public static partial class KernelMemoryBuilderExtensions
{
/// <summary>
/// Configure the builder using settings from the given IConfiguration instance.
/// </summary>
/// <param name="builder">KernelMemory builder instance</param>
/// <param name="appSettings">App settings, which might include KM settings</param>
/// <param name="memoryConfig">Optional KM settings, overriding those in appsettings</param>
public static IKernelMemoryBuilder ConfigureDependencies(
this IKernelMemoryBuilder builder,
IConfiguration appSettings,
KernelMemoryConfig? memoryConfig = null)
{
if (appSettings is null)
{
throw new ConfigurationException("The given app settings configuration is NULL");
}

if (memoryConfig is null)
{
memoryConfig = appSettings.GetSection(KernelMemoryComposer.ConfigRoot).Get<KernelMemoryConfig>();
}

if (memoryConfig is null)
{
throw new ConfigurationException($"Unable to load Kernel Memory settings from the given configuration. " +
$"There should be a '{KernelMemoryComposer.ConfigRoot}' root node, " +
$"with data mapping to '{nameof(KernelMemoryConfig)}'");
}

var composer = new KernelMemoryComposer(builder, appSettings, memoryConfig);
composer.ConfigureBuilder();

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,27 @@
using System.Reflection;
using Microsoft.Extensions.Configuration;

namespace Microsoft.KernelMemory.Service;
#pragma warning disable IDE0130 // reduce number of "using" statements
// ReSharper disable once CheckNamespace - reduce number of "using" statements
namespace Microsoft.KernelMemory;

internal static class ConfigurationBuilderExtensions
public static partial class ConfigurationBuilderExtensions
{
// ASP.NET env var
private const string AspnetEnvVar = "ASPNETCORE_ENVIRONMENT";
private const string AspNetCoreEnvVar = "ASPNETCORE_ENVIRONMENT";

public static void AddKMConfigurationSources(
// .NET env var
private const string DotNetEnvVar = "DOTNET_ENVIRONMENT";

public static void AddKernelMemoryConfigurationSources(
this IConfigurationBuilder builder,
bool useAppSettingsFiles = true,
bool useEnvVars = true,
bool useSecretManager = true,
string? settingsDirectory = null)
{
// Load env var name, either Development or Production
var env = Environment.GetEnvironmentVariable(AspnetEnvVar) ?? string.Empty;
// ASPNETCORE_ENVIRONMENT env var takes precedence. Env should be either Development or Production.
var env = Environment.GetEnvironmentVariable(AspNetCoreEnvVar) ?? Environment.GetEnvironmentVariable(DotNetEnvVar) ?? string.Empty;

// Detect the folder containing configuration files
settingsDirectory ??= Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Expand Down
File renamed without changes.
54 changes: 0 additions & 54 deletions service/Service/KernelMemoryBuilderExtensions.cs

This file was deleted.

8 changes: 5 additions & 3 deletions service/Service/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public static void Main(string[] args)

// *************************** CONFIG WIZARD ***************************

// Run `dotnet run setup` to run this code and setup the service
// Run `dotnet run setup` to run this code and set up the service
if (new[] { "setup", "-setup", "config" }.Contains(args.FirstOrDefault(), StringComparer.OrdinalIgnoreCase))
{
InteractiveSetup.Main.InteractiveSetup(args.Skip(1).ToArray());
Expand All @@ -77,7 +77,8 @@ public static void Main(string[] args)
appBuilder.Services.AddApplicationInsightsTelemetry();
}

appBuilder.Configuration.AddKMConfigurationSources();
// Add config files, user secretes, and env vars
appBuilder.Configuration.AddKernelMemoryConfigurationSources();

// Read KM settings, needed before building the app.
KernelMemoryConfig config = appBuilder.Configuration.GetSection("KernelMemory").Get<KernelMemoryConfig>()
Expand All @@ -90,7 +91,8 @@ public static void Main(string[] args)
// Internally build the memory client and make it available for dependency injection
appBuilder.AddKernelMemory(memoryBuilder =>
{
memoryBuilder.FromAppSettings().WithoutDefaultHandlers();
// Prepare the builder with settings from config files
memoryBuilder.ConfigureDependencies(appBuilder.Configuration).WithoutDefaultHandlers();

// When using distributed orchestration, handlers are hosted in the current app and need to be con
asyncHandlersCount = AddHandlersAsHostedServices(config, memoryBuilder, appBuilder);
Expand Down

0 comments on commit 6173e9b

Please sign in to comment.