From b7886427ac07478ab03d847e867ddaf0ca2ec666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 23 Sep 2025 15:16:42 +0300 Subject: [PATCH 1/5] Added TODO --- .../Volo/Abp/AI/AbpAIAbstractionsModule.cs | 9 +++++---- .../Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClient.cs | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs index cc478d8503..486f589ea1 100644 --- a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs @@ -1,10 +1,11 @@ -using Microsoft.Extensions.AI; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Volo.Abp.Modularity; +using Volo.Abp.Modularity; namespace Volo.Abp.AI; public class AbpAIAbstractionsModule : AbpModule { + /* TODO: Null implementations + * NullKernelAccessor + * ChatClientAccessor -> IChatClient + */ } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClient.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClient.cs index e7458af657..8de74390ee 100644 --- a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClient.cs +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClient.cs @@ -5,4 +5,5 @@ namespace Volo.Abp.AI; public interface IChatClient : IChatClient where TWorkSpace : class { + } \ No newline at end of file From ddaffcffb5c001e921cf0a4a36a3a07ef7a24855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 23 Sep 2025 15:38:24 +0300 Subject: [PATCH 2/5] Refactored AI package --- .../Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs | 28 +++++++++++-------- .../Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs | 2 +- .../Volo/Abp/AI/AbpAIWorkspaceOptions.cs | 2 +- .../Volo/Abp/AI/ChatClientConfiguration.cs | 2 -- ...pedKernelAccessor.cs => KernelAccessor.cs} | 4 +-- 5 files changed, 20 insertions(+), 18 deletions(-) rename framework/src/Volo.Abp.AI/Volo/Abp/AI/{TypedKernelAccessor.cs => KernelAccessor.cs} (73%) diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs index f13a6e6f02..7917fc0fbb 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.ChatCompletion; using Volo.Abp.Modularity; namespace Volo.Abp.AI; @@ -17,38 +16,43 @@ public class AbpAIModule : AbpModule { public const string DefaultWorkspaceName = "Default"; - public override void PostConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) { var options = context.Services.ExecutePreConfiguredActions(); context.Services.Configure(workspaceOptions => { - workspaceOptions.ConfiguredWorkspaceNames.UnionWith(options.Workspaces.Select(x => x.Key).ToArray()); + workspaceOptions.ConfiguredWorkspaceNames.AddIfNotContains( + options.Workspaces.Select(x => x.Key) + ); }); + + //TODO: Refactor & merge foreach loops foreach (var workspaceConfig in options.Workspaces.Values) { - if (workspaceConfig.ChatClient?.Builder is null) + if (workspaceConfig.ChatClient.Builder is null) { continue; } foreach (var builderConfigurer in workspaceConfig.ChatClient.BuilderConfigurers) { - builderConfigurer.Action(workspaceConfig.ChatClient.Builder!); + builderConfigurer.Action(workspaceConfig.ChatClient.Builder); } + var serviceName = AbpAIOptions.GetChatClientServiceKeyName(workspaceConfig.Name); + context.Services.AddKeyedChatClient( - AbpAIOptions.GetChatClientServiceKeyName(workspaceConfig.Name), - provider => workspaceConfig.ChatClient.Builder!.Build(provider), + serviceName, + provider => workspaceConfig.ChatClient.Builder.Build(provider), ServiceLifetime.Transient ); if (workspaceConfig.Name == DefaultWorkspaceName) { - context.Services.AddTransient(sp => sp.GetRequiredKeyedService( - AbpAIOptions.GetChatClientServiceKeyName(workspaceConfig.Name) - ) + context.Services.AddTransient( + sp => sp.GetRequiredKeyedService(serviceName) ); } } @@ -57,7 +61,7 @@ public class AbpAIModule : AbpModule foreach (var workspaceConfig in options.Workspaces.Values) { - if (workspaceConfig.Kernel?.Builder is null) + if (workspaceConfig.Kernel.Builder is null) { continue; } @@ -91,6 +95,6 @@ public class AbpAIModule : AbpModule } } - context.Services.TryAddTransient(typeof(IKernelAccessor<>), typeof(TypedKernelAccessor<>)); + context.Services.TryAddTransient(typeof(IKernelAccessor<>), typeof(KernelAccessor<>)); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs index b5639580d7..9fc4ffb979 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs @@ -1,6 +1,6 @@ namespace Volo.Abp.AI; -public class AbpAIOptions +public class AbpAIOptions //TODO: Rename to AbpAIWorkspaceOptions { public const string ChatClientServiceKeyNamePrefix = "Abp.AI.ChatClient_"; public const string KernelServiceKeyNamePrefix = "Abp.AI.Kernel_"; diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs index 1fad742c04..0e5e2c0720 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace Volo.Abp.AI; -public class AbpAIWorkspaceOptions +public class AbpAIWorkspaceOptions //TODO: Rename to AbpAIOptions { public HashSet ConfiguredWorkspaceNames { get; } = new(); } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientConfiguration.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientConfiguration.cs index 830d6fd87c..601a6bbe07 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientConfiguration.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientConfiguration.cs @@ -9,8 +9,6 @@ public class ChatClientConfiguration public BuilderConfigurerList BuilderConfigurers { get; } = new(); - // TODO: Base chat client (for inheriting a chat client configuration from some other one) - public void ConfigureBuilder(Action configureAction) { BuilderConfigurers.Add(configureAction); diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedKernelAccessor.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs similarity index 73% rename from framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedKernelAccessor.cs rename to framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs index 09d0132676..e0bef8c1f8 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedKernelAccessor.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs @@ -4,12 +4,12 @@ using Microsoft.SemanticKernel; namespace Volo.Abp.AI; -public class TypedKernelAccessor : IKernelAccessor +public class KernelAccessor : IKernelAccessor where TWorkSpace : class { public Kernel? Kernel { get; } - public TypedKernelAccessor(IServiceProvider serviceProvider) + public KernelAccessor(IServiceProvider serviceProvider) { Kernel = serviceProvider.GetKeyedService( AbpAIOptions.GetKernelServiceKeyName( From 5d79851c9324b1c43f0c633bc149f0cc13e4315e Mon Sep 17 00:00:00 2001 From: enisn Date: Tue, 23 Sep 2025 16:39:12 +0300 Subject: [PATCH 3/5] Refactor AI workspace options and add chat client accessors Introduces IChatClientAccessor and related implementations for workspace-based chat client resolution. Refactors AbpAIOptions and AbpAIWorkspaceOptions, moving workspace configuration logic and service key generation to AbpAIWorkspaceOptions. Updates AbpAIModule to use new accessors and configuration structure, and adds ChatClientAccessor and NullChatClientAccessor classes for dependency injection. Improves separation of concerns and prepares for more flexible workspace management. --- .../Volo/Abp/AI/IChatClientAccessor.cs | 14 ++ .../Volo/Abp/AI/IKernelAccessor.cs | 2 +- .../Volo/Abp/AI/NullChatClientAccessor.cs | 19 +++ .../Volo/Abp/AI/NullKernelAccessor.cs | 20 +++ .../Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs | 125 +++++++++--------- .../Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs | 19 +-- .../Volo/Abp/AI/AbpAIWorkspaceOptions.cs | 24 +++- .../Volo/Abp/AI/ChatClientAccessor.cs | 35 +++++ .../Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs | 2 +- .../Volo/Abp/AI/TypedChatClient.cs | 2 +- 10 files changed, 179 insertions(+), 83 deletions(-) create mode 100644 framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClientAccessor.cs create mode 100644 framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullChatClientAccessor.cs create mode 100644 framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullKernelAccessor.cs create mode 100644 framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClientAccessor.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClientAccessor.cs new file mode 100644 index 0000000000..b57aeae64d --- /dev/null +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IChatClientAccessor.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.AI; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AI; + +public interface IChatClientAccessor +{ + IChatClient? ChatClient { get; } +} + +public interface IChatClientAccessor : IChatClientAccessor + where TWorkSpace : class +{ +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IKernelAccessor.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IKernelAccessor.cs index 7f55ad9e6f..4aae8fadb0 100644 --- a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IKernelAccessor.cs +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/IKernelAccessor.cs @@ -11,4 +11,4 @@ public interface IKernelAccessor public interface IKernelAccessor : IKernelAccessor where TWorkSpace : class { -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullChatClientAccessor.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullChatClientAccessor.cs new file mode 100644 index 0000000000..0aa1ba52fc --- /dev/null +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullChatClientAccessor.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.AI; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AI; + +[Dependency(TryRegister = true)] +[ExposeServices(typeof(IChatClientAccessor))] +public class NullChatClientAccessor : IChatClientAccessor +{ + public IChatClient? ChatClient => null; +} + +[Dependency(TryRegister = true)] +[ExposeServices(typeof(IChatClientAccessor<>))] +public class NullChatClientAccessor : IChatClientAccessor + where TWorkSpace : class +{ + public IChatClient? ChatClient => null; +} diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullKernelAccessor.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullKernelAccessor.cs new file mode 100644 index 0000000000..e05ad69553 --- /dev/null +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/NullKernelAccessor.cs @@ -0,0 +1,20 @@ + +using Microsoft.SemanticKernel; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AI; + +[Dependency(TryRegister = true)] +[ExposeServices(typeof(IKernelAccessor))] +public class NullKernelAccessor : IKernelAccessor +{ + public Kernel? Kernel => null; +} + +[Dependency(TryRegister = true)] +[ExposeServices(typeof(IKernelAccessor<>))] +public class NullKernelAccessor : IKernelAccessor + where TWorkSpace : class +{ + public Kernel? Kernel => null; +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs index 7917fc0fbb..81d3866199 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs @@ -18,83 +18,86 @@ public class AbpAIModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { - var options = context.Services.ExecutePreConfiguredActions(); + var options = context.Services.ExecutePreConfiguredActions(); - context.Services.Configure(workspaceOptions => + context.Services.Configure(workspaceOptions => { workspaceOptions.ConfiguredWorkspaceNames.AddIfNotContains( options.Workspaces.Select(x => x.Key) ); }); - - //TODO: Refactor & merge foreach loops foreach (var workspaceConfig in options.Workspaces.Values) { - if (workspaceConfig.ChatClient.Builder is null) - { - continue; - } - - foreach (var builderConfigurer in workspaceConfig.ChatClient.BuilderConfigurers) - { - builderConfigurer.Action(workspaceConfig.ChatClient.Builder); - } - - var serviceName = AbpAIOptions.GetChatClientServiceKeyName(workspaceConfig.Name); - - context.Services.AddKeyedChatClient( - serviceName, - provider => workspaceConfig.ChatClient.Builder.Build(provider), - ServiceLifetime.Transient + ConfigureChatClient(context, workspaceConfig); + ConfigureKernel(context, workspaceConfig); + } + + context.Services.TryAddTransient(typeof(IChatClient<>), typeof(TypedChatClient<>)); + context.Services.TryAddTransient(typeof(IKernelAccessor<>), typeof(KernelAccessor<>)); + } + + private static void ConfigureKernel(ServiceConfigurationContext context, WorkspaceConfiguration workspaceConfig) + { + if (workspaceConfig.Kernel.Builder is null) + { + return; + } + + foreach (var builderConfigurer in workspaceConfig.Kernel.BuilderConfigurers) + { + builderConfigurer.Action(workspaceConfig.Kernel.Builder!); + } + + // TODO: Check if we can use transient instead of singleton for Kernel + context.Services.AddKeyedTransient( + AbpAIWorkspaceOptions.GetKernelServiceKeyName(workspaceConfig.Name), + (provider, _) => workspaceConfig.Kernel.Builder!.Build()); + + if (workspaceConfig.Name == DefaultWorkspaceName) + { + context.Services.AddTransient(sp => sp.GetRequiredKeyedService( + AbpAIWorkspaceOptions.GetKernelServiceKeyName(workspaceConfig.Name) + ) ); + } - if (workspaceConfig.Name == DefaultWorkspaceName) - { - context.Services.AddTransient( - sp => sp.GetRequiredKeyedService(serviceName) - ); - } + if (workspaceConfig.ChatClient?.Builder is null) + { + context.Services.AddKeyedTransient( + AbpAIWorkspaceOptions.GetChatClientServiceKeyName(workspaceConfig.Name), + (sp, _) => sp.GetKeyedService(AbpAIWorkspaceOptions.GetKernelServiceKeyName(workspaceConfig.Name))? + .GetRequiredService() + ?? throw new InvalidOperationException("Kernel or IChatClient not found with workspace name: " + workspaceConfig.Name) + ); } + } - context.Services.TryAddTransient(typeof(IChatClient<>), typeof(TypedChatClient<>)); + private static void ConfigureChatClient(ServiceConfigurationContext context, WorkspaceConfiguration workspaceConfig) + { + if (workspaceConfig.ChatClient.Builder is null) + { + return; + } - foreach (var workspaceConfig in options.Workspaces.Values) + foreach (var builderConfigurer in workspaceConfig.ChatClient.BuilderConfigurers) { - if (workspaceConfig.Kernel.Builder is null) - { - continue; - } - - foreach (var builderConfigurer in workspaceConfig.Kernel.BuilderConfigurers) - { - builderConfigurer.Action(workspaceConfig.Kernel.Builder!); - } - - // TODO: Check if we can use transient instead of singleton for Kernel - context.Services.AddKeyedTransient( - AbpAIOptions.GetKernelServiceKeyName(workspaceConfig.Name), - (provider, _) => workspaceConfig.Kernel.Builder!.Build()); - - if (workspaceConfig.Name == DefaultWorkspaceName) - { - context.Services.AddTransient(sp => sp.GetRequiredKeyedService( - AbpAIOptions.GetKernelServiceKeyName(workspaceConfig.Name) - ) - ); - } - - if (workspaceConfig.ChatClient?.Builder is null) - { - context.Services.AddKeyedTransient( - AbpAIOptions.GetChatClientServiceKeyName(workspaceConfig.Name), - (sp, _) => sp.GetKeyedService(AbpAIOptions.GetKernelServiceKeyName(workspaceConfig.Name))? - .GetRequiredService() - ?? throw new InvalidOperationException("Kernel or IChatClient not found with workspace name: " + workspaceConfig.Name) - ); - } + builderConfigurer.Action(workspaceConfig.ChatClient.Builder); } - context.Services.TryAddTransient(typeof(IKernelAccessor<>), typeof(KernelAccessor<>)); + var serviceName = AbpAIWorkspaceOptions.GetChatClientServiceKeyName(workspaceConfig.Name); + + context.Services.AddKeyedChatClient( + serviceName, + provider => workspaceConfig.ChatClient.Builder.Build(provider), + ServiceLifetime.Transient + ); + + if (workspaceConfig.Name == DefaultWorkspaceName) + { + context.Services.AddTransient( + sp => sp.GetRequiredKeyedService(serviceName) + ); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs index 9fc4ffb979..4efe59ed5c 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIOptions.cs @@ -1,19 +1,8 @@ +using System.Collections.Generic; + namespace Volo.Abp.AI; -public class AbpAIOptions //TODO: Rename to AbpAIWorkspaceOptions +public class AbpAIOptions { - public const string ChatClientServiceKeyNamePrefix = "Abp.AI.ChatClient_"; - public const string KernelServiceKeyNamePrefix = "Abp.AI.Kernel_"; - - public WorkspaceConfigurationDictionary Workspaces { get; } = new(); - - public static string GetChatClientServiceKeyName(string name) - { - return $"{ChatClientServiceKeyNamePrefix}{name}"; - } - - public static string GetKernelServiceKeyName(string name) - { - return $"{KernelServiceKeyNamePrefix}{name}"; - } + public HashSet ConfiguredWorkspaceNames { get; } = new(); } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs index 0e5e2c0720..e027c185f6 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIWorkspaceOptions.cs @@ -1,8 +1,24 @@ -using System.Collections.Generic; - namespace Volo.Abp.AI; -public class AbpAIWorkspaceOptions //TODO: Rename to AbpAIOptions +/// +/// Pre-configured options for the AI workspaces. Not used via Options pattern. Use it with 'PreConfigure' method in a Module class. +/// In example: +/// PreConfigure<AbpAIWorkspaceOptions>(options => { }); +/// +public class AbpAIWorkspaceOptions { - public HashSet ConfiguredWorkspaceNames { get; } = new(); + public const string ChatClientServiceKeyNamePrefix = "Abp.AI.ChatClient_"; + public const string KernelServiceKeyNamePrefix = "Abp.AI.Kernel_"; + + public WorkspaceConfigurationDictionary Workspaces { get; } = new(); + + public static string GetChatClientServiceKeyName(string name) + { + return $"{ChatClientServiceKeyNamePrefix}{name}"; + } + + public static string GetKernelServiceKeyName(string name) + { + return $"{KernelServiceKeyNamePrefix}{name}"; + } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs new file mode 100644 index 0000000000..1a852838fc --- /dev/null +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs @@ -0,0 +1,35 @@ +using System; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AI; + +[Dependency(ReplaceServices = true, TryRegister = true)] +[ExposeServices(typeof(IChatClientAccessor))] +public class ChatClientAccessor : IChatClientAccessor +{ + public IChatClient? ChatClient { get; } + + public ChatClientAccessor(IServiceProvider serviceProvider) + { + ChatClient = serviceProvider.GetKeyedService( + AbpAIWorkspaceOptions.GetChatClientServiceKeyName( + AbpAIModule.DefaultWorkspaceName)); + } +} + +[Dependency(ReplaceServices = true, TryRegister = true)] +[ExposeServices(typeof(IChatClientAccessor))] +public class ChatClientAccessor : IChatClientAccessor + where TWorkSpace : class +{ + public IChatClient? ChatClient { get; } + + public ChatClientAccessor(IServiceProvider serviceProvider) + { + ChatClient = serviceProvider.GetKeyedService( + AbpAIWorkspaceOptions.GetChatClientServiceKeyName( + WorkspaceNameAttribute.GetWorkspaceName())); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs index e0bef8c1f8..ba9d305312 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/KernelAccessor.cs @@ -12,7 +12,7 @@ public class KernelAccessor : IKernelAccessor public KernelAccessor(IServiceProvider serviceProvider) { Kernel = serviceProvider.GetKeyedService( - AbpAIOptions.GetKernelServiceKeyName( + AbpAIWorkspaceOptions.GetKernelServiceKeyName( WorkspaceNameAttribute.GetWorkspaceName())); } } diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedChatClient.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedChatClient.cs index c75d9b0c97..72ccfdaf38 100644 --- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedChatClient.cs +++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/TypedChatClient.cs @@ -10,7 +10,7 @@ public class TypedChatClient : DelegatingChatClient, IChatClient( - AbpAIOptions.GetChatClientServiceKeyName( + AbpAIWorkspaceOptions.GetChatClientServiceKeyName( WorkspaceNameAttribute.GetWorkspaceName())) ) { From a2d72c8dd9b5cc815c12dd5825912806f3567d7a Mon Sep 17 00:00:00 2001 From: enisn Date: Tue, 23 Sep 2025 16:42:43 +0300 Subject: [PATCH 4/5] Update AbpAIAbstractionsModule.cs --- .../Volo/Abp/AI/AbpAIAbstractionsModule.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs index 486f589ea1..b535cf3235 100644 --- a/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs +++ b/framework/src/Volo.Abp.AI.Abstractions/Volo/Abp/AI/AbpAIAbstractionsModule.cs @@ -4,8 +4,4 @@ namespace Volo.Abp.AI; public class AbpAIAbstractionsModule : AbpModule { - /* TODO: Null implementations - * NullKernelAccessor - * ChatClientAccessor -> IChatClient - */ } \ No newline at end of file From fe92be0c649e8087ea5e61737b0558f70f52a452 Mon Sep 17 00:00:00 2001 From: enisn Date: Wed, 24 Sep 2025 10:36:34 +0300 Subject: [PATCH 5/5] Remove unused package versions from Directory.Packages.props --- Directory.Packages.props | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 72bd640a02..f7f6fe8b03 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -86,9 +86,7 @@ - - - +