Browse Source

Merge pull request #1418 from colinin/ai

feat(ai): Add an AI integration module
pull/1361/merge
yx lin 3 weeks ago
committed by GitHub
parent
commit
9e5fab7fd1
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      Directory.Packages.props
  2. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/FodyWeavers.xml
  3. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/FodyWeavers.xsd
  4. 25
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN.Abp.AI.Agent.csproj
  5. 9
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AbpAIAgentModule.cs
  6. 80
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/ChatClientAgentFactory.cs
  7. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IChatClientAgentFactory.cs
  8. 98
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/README.md
  9. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/FodyWeavers.xml
  10. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/FodyWeavers.xsd
  11. 22
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN.Abp.AI.Core.csproj
  12. 52
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAICoreModule.cs
  13. 22
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAICoreOptions.cs
  14. 82
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientFactory.cs
  15. 45
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientProviderManager.cs
  16. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IChatClientFactory.cs
  17. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IChatClientProvider.cs
  18. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IChatClientProviderManager.cs
  19. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IKernelFactory.cs
  20. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IKernelProvider.cs
  21. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IKernelProviderManager.cs
  22. 82
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelFactory.cs
  23. 44
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelProviderManager.cs
  24. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Localization/AbpAIResource.cs
  25. 36
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/OpenAIChatClientProvider.cs
  26. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IDynamicWorkspaceDefinitionStore.cs
  27. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IStaticWorkspaceDefinitionStore.cs
  28. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IWorkspaceDefinitionContext.cs
  29. 16
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IWorkspaceDefinitionManager.cs
  30. 5
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IWorkspaceDefinitionProvider.cs
  31. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/NullDynamicWorkspaceDefinitionStore.cs
  32. 79
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/StaticWorkspaceDefinitionStore.cs
  33. 104
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs
  34. 37
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinitionContext.cs
  35. 52
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinitionManager.cs
  36. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinitionProvider.cs
  37. 164
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/README.md

6
Directory.Packages.props

@ -14,6 +14,7 @@
<!-- Abp Framework -->
<ItemGroup>
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="5.0.2" />
<PackageVersion Include="Volo.Abp.AI" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Core" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
@ -105,6 +106,7 @@
<PackageVersion Include="Volo.Abp.Imaging.ImageSharp" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Json" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Json.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Localization.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Localization" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.MailKit" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Mapperly" Version="$(VoloAbpPackageVersion)" />
@ -277,6 +279,10 @@
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.14.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.14.0-beta.1" />
</ItemGroup>
<!-- AI -->
<ItemGroup>
<PackageVersion Include="Microsoft.Agents.AI" Version="1.0.0-preview.260108.1" />
</ItemGroup>
<!-- Rebus-->
<ItemGroup>
<PackageVersion Include="Rebus.Microsoft.Extensions.Logging" Version="5.2.0" />

3
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

25
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN.Abp.AI.Agent.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AI.Agent</AssemblyName>
<PackageId>LINGYUN.Abp.AI.Agent</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Agents.AI" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.AI.Core\LINGYUN.Abp.AI.Core.csproj" />
</ItemGroup>
</Project>

9
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AbpAIAgentModule.cs

@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AI.Agent;
[DependsOn(typeof(AbpAICoreModule))]
public class AbpAIAgentModule : AbpModule
{
}

80
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/ChatClientAgentFactory.cs

@ -0,0 +1,80 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Localization;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Volo.Abp.AI;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Agent;
public class ChatClientAgentFactory : IChatClientAgentFactory, ISingletonDependency
{
private readonly static ConcurrentDictionary<string, ChatClientAgent> _chatClientAgentCache = new();
private readonly IChatClientFactory _chatClientFactory;
private readonly IStringLocalizerFactory _stringLocalizerFactory;
private readonly IWorkspaceDefinitionManager _workspaceDefinitionManager;
public ChatClientAgentFactory(
IChatClientFactory chatClientFactory,
IStringLocalizerFactory stringLocalizerFactory,
IWorkspaceDefinitionManager workspaceDefinitionManager)
{
_chatClientFactory = chatClientFactory;
_stringLocalizerFactory = stringLocalizerFactory;
_workspaceDefinitionManager = workspaceDefinitionManager;
}
public async virtual Task<ChatClientAgent> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
if (_chatClientAgentCache.TryGetValue(workspace, out var chatClientAgent))
{
return chatClientAgent;
}
var chatClient = await _chatClientFactory.CreateAsync<TWorkspace>();
var workspaceDefine = await _workspaceDefinitionManager.GetOrNullAsync(workspace);
string? description = null;
if (workspaceDefine?.Description != null)
{
description = workspaceDefine.Description.Localize(_stringLocalizerFactory);
}
chatClientAgent = chatClient.CreateAIAgent(
instructions: workspaceDefine?.SystemPrompt,
name: workspaceDefine?.Name,
description: description);
_chatClientAgentCache.TryAdd(workspace, chatClientAgent);
return chatClientAgent;
}
public async virtual Task<ChatClientAgent> CreateAsync(string workspace)
{
if (_chatClientAgentCache.TryGetValue(workspace, out var chatClientAgent))
{
return chatClientAgent;
}
var workspaceDefine = await _workspaceDefinitionManager.GetAsync(workspace);
var chatClient = await _chatClientFactory.CreateAsync(workspace);
string? description = null;
if (workspaceDefine.Description != null)
{
description = workspaceDefine.Description.Localize(_stringLocalizerFactory);
}
chatClientAgent = chatClient.CreateAIAgent(
instructions: workspaceDefine.SystemPrompt,
name: workspaceDefine.Name,
description: description);
_chatClientAgentCache.TryAdd(workspace, chatClientAgent);
return chatClientAgent;
}
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IChatClientAgentFactory.cs

@ -0,0 +1,13 @@
using JetBrains.Annotations;
using Microsoft.Agents.AI;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Agent;
public interface IChatClientAgentFactory
{
[NotNull]
Task<ChatClientAgent> CreateAsync<TWorkspace>();
[NotNull]
Task<ChatClientAgent> CreateAsync(string workspace);
}

98
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/README.md

@ -0,0 +1,98 @@
# LINGYUN.Abp.AI.Agent
[Abp AI Module](https://abp.io/docs/latest/framework/infrastructure/artificial-intelligence) 扩展.
## 功能特性
## 模块引用
```csharp
[DependsOn(typeof(AbpAIAgentModule))]
public class YouProjectModule : AbpModule
{
// other
}
```
## 依赖模块
* [AbpAIModule](https://abp.io/docs/latest/framework/infrastructure/artificial-intelligence)
* [AbpLocalizationModule](https://abp.io/docs/latest/framework/fundamentals/localization)
## 基本用法
> 兼容 `IKernelAccessor``IChatClientAccessor` 的语法.
```csharp
using LINGYUN.Abp.AI;
using LINGYUN.Abp.AI.Agent;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Volo.Abp;
var application = await AbpApplicationFactory.CreateAsync<YouProjectModule>(options =>
{
options.UseAutofac();
});
await application.InitializeAsync();
var chatClientAgentFactory = application.ServiceProvider.GetRequiredService<IChatClientAgentFactory>();
var agent = await chatClientAgentFactory.CreateAsync<YouWorkspace>();
var agentResponse = agent.RunStreamingAsync("解释一下线性代数");
await foreach (var item in agentResponse)
{
Console.Write(item);
}
Console.WriteLine();
await application.ShutdownAsync();
Console.WriteLine();
Console.WriteLine("AI Console completed!");
Console.ReadKey();
```
> 支持动态工作区语法.
```csharp
using LINGYUN.Abp.AI;
using LINGYUN.Abp.AI.Agent;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Volo.Abp;
var application = await AbpApplicationFactory.CreateAsync<YouProjectModule>(options =>
{
options.UseAutofac();
});
await application.InitializeAsync();
var chatClientAgentFactory = application.ServiceProvider.GetRequiredService<IChatClientAgentFactory>();
var agent = await chatClientAgentFactory.CreateAsync("YouWorkspace");
var agentResponse = agent.RunStreamingAsync("解释一下线性代数");
await foreach (var item in agentResponse)
{
Console.Write(item);
}
Console.WriteLine();
await application.ShutdownAsync();
Console.WriteLine();
Console.WriteLine("AI Console completed!");
Console.ReadKey();
```

3
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

22
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN.Abp.AI.Core.csproj

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AI.Core</AssemblyName>
<PackageId>LINGYUN.Abp.AI.Core</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AI" />
<PackageReference Include="Volo.Abp.Localization" />
</ItemGroup>
</Project>

52
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAICoreModule.cs

@ -0,0 +1,52 @@
using LINGYUN.Abp.AI.Localization;
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using Volo.Abp.AI;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AI;
[DependsOn(
typeof(AbpAIModule),
typeof(AbpLocalizationModule))]
public class AbpAICoreModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddDefinitionProviders(context.Services);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources.Add<AbpAIResource>();
});
Configure<AbpAICoreOptions>(options =>
{
options.ChatClientProviders.Add<OpenAIChatClientProvider>();
});
}
private static void AutoAddDefinitionProviders(IServiceCollection services)
{
var definitionProviders = new List<Type>();
services.OnRegistered(context =>
{
if (typeof(IWorkspaceDefinitionProvider).IsAssignableFrom(context.ImplementationType))
{
definitionProviders.Add(context.ImplementationType);
}
});
services.Configure<AbpAICoreOptions>(options =>
{
options.DefinitionProviders.AddIfNotContains(definitionProviders);
});
}
}

22
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAICoreOptions.cs

@ -0,0 +1,22 @@
using LINGYUN.Abp.AI.Workspaces;
using System.Collections.Generic;
using Volo.Abp.Collections;
namespace LINGYUN.Abp.AI;
public class AbpAICoreOptions
{
public ITypeList<IWorkspaceDefinitionProvider> DefinitionProviders { get; }
public ITypeList<IChatClientProvider> ChatClientProviders { get; }
public ITypeList<IKernelProvider> KernelProviders { get; }
public HashSet<string> DeletedWorkspaces { get; }
public AbpAICoreOptions()
{
DefinitionProviders = new TypeList<IWorkspaceDefinitionProvider>();
ChatClientProviders = new TypeList<IChatClientProvider>();
KernelProviders = new TypeList<IKernelProvider>();
DeletedWorkspaces = new HashSet<string>();
}
}

82
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientFactory.cs

@ -0,0 +1,82 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.AI;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AI;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public class ChatClientFactory : IChatClientFactory, ISingletonDependency
{
private readonly static ConcurrentDictionary<string, IChatClient> _chatClientCache = new();
protected IWorkspaceDefinitionManager WorkspaceDefinitionManager { get; }
protected IChatClientProviderManager ChatClientProviderManager { get; }
protected IServiceProvider ServiceProvider { get; }
public ChatClientFactory(
IWorkspaceDefinitionManager workspaceDefinitionManager,
IChatClientProviderManager chatClientProviderManager,
IServiceProvider serviceProvider)
{
WorkspaceDefinitionManager = workspaceDefinitionManager;
ChatClientProviderManager = chatClientProviderManager;
ServiceProvider = serviceProvider;
}
public async virtual Task<IChatClient> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
if (_chatClientCache.TryGetValue(workspace, out var chatClient))
{
return chatClient;
}
var chatClientAccessorType = typeof(IChatClientAccessor<>).MakeGenericType(typeof(TWorkspace));
var chatClientAccessor = ServiceProvider.GetService(chatClientAccessorType);
if (chatClientAccessor != null &&
chatClientAccessor is IChatClientAccessor accessor &&
accessor.ChatClient != null)
{
chatClient = accessor.ChatClient;
_chatClientCache.TryAdd(workspace, chatClient);
}
else
{
chatClient = await CreateAsync(workspace);
}
return chatClient;
}
public async virtual Task<IChatClient> CreateAsync(string workspace)
{
if (_chatClientCache.TryGetValue(workspace, out var chatClient))
{
return chatClient;
}
var workspaceDefine = await WorkspaceDefinitionManager.GetAsync(workspace);
chatClient = await CreateChatClientAsync(workspaceDefine);
_chatClientCache.TryAdd(workspace, chatClient);
return chatClient;
}
protected async virtual Task<IChatClient> CreateChatClientAsync(WorkspaceDefinition workspace)
{
foreach (var provider in ChatClientProviderManager.Providers)
{
if (!string.Equals(provider.Name, workspace.Provider))
{
continue;
}
return await provider.CreateAsync(workspace);
}
throw new AbpException($"The ChatClient provider implementation named {workspace.Provider} was not found");
}
}

45
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientProviderManager.cs

@ -0,0 +1,45 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public class ChatClientProviderManager : IChatClientProviderManager, ISingletonDependency
{
public List<IChatClientProvider> Providers => _lazyProviders.Value;
protected AbpAICoreOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
private readonly Lazy<List<IChatClientProvider>> _lazyProviders;
public ChatClientProviderManager(
IServiceProvider serviceProvider,
IOptions<AbpAICoreOptions> options)
{
Options = options.Value;
ServiceProvider = serviceProvider;
_lazyProviders = new Lazy<List<IChatClientProvider>>(GetProviders, true);
}
protected virtual List<IChatClientProvider> GetProviders()
{
var providers = Options
.ChatClientProviders
.Select(type => (ServiceProvider.GetRequiredService(type) as IChatClientProvider)!)
.ToList();
var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1);
if (multipleProviders != null)
{
throw new AbpException($"Duplicate ChatClient provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}");
}
return providers;
}
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IChatClientFactory.cs

@ -0,0 +1,13 @@
using JetBrains.Annotations;
using Microsoft.Extensions.AI;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI;
public interface IChatClientFactory
{
[NotNull]
Task<IChatClient> CreateAsync<TWorkspace>();
[NotNull]
Task<IChatClient> CreateAsync(string workspace);
}

11
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IChatClientProvider.cs

@ -0,0 +1,11 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.AI;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI;
public interface IChatClientProvider
{
string Name { get; }
Task<IChatClient> CreateAsync(WorkspaceDefinition workspace);
}

7
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IChatClientProviderManager.cs

@ -0,0 +1,7 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.AI;
public interface IChatClientProviderManager
{
List<IChatClientProvider> Providers { get; }
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IKernelFactory.cs

@ -0,0 +1,13 @@
using JetBrains.Annotations;
using Microsoft.SemanticKernel;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI;
public interface IKernelFactory
{
[NotNull]
Task<Kernel> CreateAsync<TWorkspace>();
[NotNull]
Task<Kernel> CreateAsync(string workspace);
}

11
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IKernelProvider.cs

@ -0,0 +1,11 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.SemanticKernel;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI;
public interface IKernelProvider
{
string Name { get; }
Task<Kernel> CreateAsync(WorkspaceDefinition workspace);
}

7
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/IKernelProviderManager.cs

@ -0,0 +1,7 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.AI;
public interface IKernelProviderManager
{
List<IKernelProvider> Providers { get; }
}

82
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelFactory.cs

@ -0,0 +1,82 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.SemanticKernel;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AI;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public class KernelFactory : IKernelFactory, ISingletonDependency
{
private readonly static ConcurrentDictionary<string, Kernel> _kernelCache = new();
protected IWorkspaceDefinitionManager WorkspaceDefinitionManager { get; }
protected IKernelProviderManager KernelProviderManager { get; }
protected IServiceProvider ServiceProvider { get; }
public KernelFactory(
IWorkspaceDefinitionManager workspaceDefinitionManager,
IKernelProviderManager kernelProviderManager,
IServiceProvider serviceProvider)
{
WorkspaceDefinitionManager = workspaceDefinitionManager;
KernelProviderManager = kernelProviderManager;
ServiceProvider = serviceProvider;
}
public async virtual Task<Kernel> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
if (_kernelCache.TryGetValue(workspace, out var kernel))
{
return kernel;
}
var kernelAccessorType = typeof(IKernelAccessor<>).MakeGenericType(typeof(TWorkspace));
var kernelAccessor = ServiceProvider.GetService(kernelAccessorType);
if (kernelAccessor != null &&
kernelAccessor is IKernelAccessor accessor
&& accessor.Kernel != null)
{
kernel = accessor.Kernel;
_kernelCache.TryAdd(workspace, kernel);
}
else
{
kernel = await CreateAsync(workspace);
}
return kernel;
}
public async virtual Task<Kernel> CreateAsync(string workspace)
{
if (_kernelCache.TryGetValue(workspace, out var kernel))
{
return kernel;
}
var workspaceDefine = await WorkspaceDefinitionManager.GetAsync(workspace);
kernel = await CreateKernelAsync(workspaceDefine);
_kernelCache.TryAdd(workspace, kernel);
return kernel;
}
protected async virtual Task<Kernel> CreateKernelAsync(WorkspaceDefinition workspace)
{
foreach (var provider in KernelProviderManager.Providers)
{
if (!string.Equals(provider.Name, workspace.Provider))
{
continue;
}
return await provider.CreateAsync(workspace);
}
throw new AbpException($"The Kernel provider implementation named {workspace.Provider} was not found");
}
}

44
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelProviderManager.cs

@ -0,0 +1,44 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public class KernelProviderManager : IKernelProviderManager, ISingletonDependency
{
public List<IKernelProvider> Providers => _lazyProviders.Value;
protected AbpAICoreOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
private readonly Lazy<List<IKernelProvider>> _lazyProviders;
public KernelProviderManager(
IServiceProvider serviceProvider,
IOptions<AbpAICoreOptions> options)
{
Options = options.Value;
ServiceProvider = serviceProvider;
_lazyProviders = new Lazy<List<IKernelProvider>>(GetProviders, true);
}
protected virtual List<IKernelProvider> GetProviders()
{
var providers = Options
.ChatClientProviders
.Select(type => (ServiceProvider.GetRequiredService(type) as IKernelProvider)!)
.ToList();
var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1);
if (multipleProviders != null)
{
throw new AbpException($"Duplicate Kernel provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}");
}
return providers;
}
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Localization/AbpAIResource.cs

@ -0,0 +1,8 @@
using Volo.Abp.Localization;
namespace LINGYUN.Abp.AI.Localization;
[LocalizationResourceName("AbpAI")]
public class AbpAIResource
{
}

36
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/OpenAIChatClientProvider.cs

@ -0,0 +1,36 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.AI;
using OpenAI;
using System;
using System.ClientModel;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public class OpenAIChatClientProvider : IChatClientProvider, ITransientDependency
{
private const string DefaultEndpoint = "https://api.openai.com/v1";
public const string ProviderName = "OpenAI";
public virtual string Name => ProviderName;
public virtual Task<IChatClient> CreateAsync(WorkspaceDefinition workspace)
{
Check.NotNull(workspace, nameof(workspace));
Check.NotNullOrWhiteSpace(workspace.ApiKey, nameof(WorkspaceDefinition.ApiKey));
var openAIClient = new OpenAIClient(
new ApiKeyCredential(workspace.ApiKey),
new OpenAIClientOptions
{
Endpoint = new Uri(workspace.ApiBaseUrl ?? DefaultEndpoint),
});
var chatClient = openAIClient
.GetChatClient(workspace.ModelName)
.AsIChatClient();
return Task.FromResult(chatClient);
}
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IDynamicWorkspaceDefinitionStore.cs

@ -0,0 +1,13 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Workspaces;
public interface IDynamicWorkspaceDefinitionStore
{
Task<WorkspaceDefinition> GetAsync([NotNull] string name);
Task<IReadOnlyList<WorkspaceDefinition>> GetAllAsync();
Task<WorkspaceDefinition?> GetOrNullAsync([NotNull] string name);
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IStaticWorkspaceDefinitionStore.cs

@ -0,0 +1,13 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Workspaces;
public interface IStaticWorkspaceDefinitionStore
{
Task<WorkspaceDefinition> GetAsync([NotNull] string name);
Task<IReadOnlyList<WorkspaceDefinition>> GetAllAsync();
Task<WorkspaceDefinition?> GetOrNullAsync([NotNull] string name);
}

11
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IWorkspaceDefinitionContext.cs

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.AI.Workspaces;
public interface IWorkspaceDefinitionContext
{
WorkspaceDefinition? GetOrNull(string name);
IReadOnlyList<WorkspaceDefinition> GetAll();
void Add(params WorkspaceDefinition[] definitions);
}

16
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IWorkspaceDefinitionManager.cs

@ -0,0 +1,16 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Workspaces;
public interface IWorkspaceDefinitionManager
{
[ItemNotNull]
Task<WorkspaceDefinition> GetAsync([NotNull] string name);
[ItemNotNull]
Task<IReadOnlyList<WorkspaceDefinition>> GetAllAsync();
[ItemCanBeNull]
Task<WorkspaceDefinition?> GetOrNullAsync([NotNull] string name);
}

5
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/IWorkspaceDefinitionProvider.cs

@ -0,0 +1,5 @@
namespace LINGYUN.Abp.AI.Workspaces;
public interface IWorkspaceDefinitionProvider
{
void Define(IWorkspaceDefinitionContext context);
}

30
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/NullDynamicWorkspaceDefinitionStore.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Workspaces;
public class NullDynamicWorkspaceDefinitionStore : IDynamicWorkspaceDefinitionStore, ISingletonDependency
{
private readonly static Task<WorkspaceDefinition?> CachedNullableWorkspaceResult = Task.FromResult((WorkspaceDefinition?)null);
private readonly static Task<WorkspaceDefinition> CachedWorkspaceResult = Task.FromResult((WorkspaceDefinition)null!);
private readonly static Task<IReadOnlyList<WorkspaceDefinition>> CachedWorkspacesResult = Task.FromResult(
(IReadOnlyList<WorkspaceDefinition>)Array.Empty<WorkspaceDefinition>().ToImmutableList());
public Task<WorkspaceDefinition> GetAsync(string name)
{
return CachedWorkspaceResult;
}
public Task<IReadOnlyList<WorkspaceDefinition>> GetAllAsync()
{
return CachedWorkspacesResult;
}
public Task<WorkspaceDefinition?> GetOrNullAsync(string name)
{
return CachedNullableWorkspaceResult;
}
}

79
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/StaticWorkspaceDefinitionStore.cs

@ -0,0 +1,79 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.StaticDefinitions;
namespace LINGYUN.Abp.AI.Workspaces;
public class StaticWorkspaceDefinitionStore : IStaticWorkspaceDefinitionStore, ISingletonDependency
{
protected IServiceProvider ServiceProvider { get; }
protected AbpAICoreOptions Options { get; }
protected IStaticDefinitionCache<WorkspaceDefinition, Dictionary<string, WorkspaceDefinition>> DefinitionCache { get; }
public StaticWorkspaceDefinitionStore(
IServiceProvider serviceProvider,
IOptions<AbpAICoreOptions> options,
IStaticDefinitionCache<WorkspaceDefinition, Dictionary<string, WorkspaceDefinition>> definitionCache)
{
ServiceProvider = serviceProvider;
Options = options.Value;
DefinitionCache = definitionCache;
}
public virtual async Task<WorkspaceDefinition> GetAsync(string name)
{
Check.NotNull(name, nameof(name));
var workspace = await GetOrNullAsync(name);
if (workspace == null)
{
throw new AbpException("Undefined workspace: " + name);
}
return workspace;
}
public virtual async Task<IReadOnlyList<WorkspaceDefinition>> GetAllAsync()
{
var defs = await GetWorkspaceDefinitionsAsync();
return defs.Values.ToImmutableList();
}
public virtual async Task<WorkspaceDefinition?> GetOrNullAsync(string name)
{
var defs = await GetWorkspaceDefinitionsAsync();
return defs.GetOrDefault(name);
}
protected virtual async Task<Dictionary<string, WorkspaceDefinition>> GetWorkspaceDefinitionsAsync()
{
return await DefinitionCache.GetOrCreateAsync(CreateWorkspaceDefinitionsAsync);
}
protected virtual Task<Dictionary<string, WorkspaceDefinition>> CreateWorkspaceDefinitionsAsync()
{
var workspaces = new Dictionary<string, WorkspaceDefinition>();
using (var scope = ServiceProvider.CreateScope())
{
var providers = Options
.DefinitionProviders
.Select(p => scope.ServiceProvider.GetRequiredService(p) as IWorkspaceDefinitionProvider)
.ToList();
foreach (var provider in providers)
{
provider?.Define(new WorkspaceDefinitionContext(workspaces));
}
}
return Task.FromResult(workspaces);
}
}

104
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs

@ -0,0 +1,104 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Localization;
using Volo.Abp.SimpleStateChecking;
namespace LINGYUN.Abp.AI.Workspaces;
/// <summary>
/// 工作区定义
/// </summary>
public class WorkspaceDefinition : IHasSimpleStateCheckers<WorkspaceDefinition>
{
/// <summary>
/// 名称
/// </summary>
[NotNull]
public string Name { get; }
/// <summary>
/// AI提供者名称
/// </summary>
[NotNull]
public string Provider { get; }
/// <summary>
/// 模型名称
/// </summary>
[NotNull]
public string ModelName { get; }
/// <summary>
/// 显示名称
/// </summary>
[NotNull]
public ILocalizableString DisplayName {
get => _displayName;
set => _displayName = Check.NotNull(value, nameof(value));
}
private ILocalizableString _displayName = default!;
/// <summary>
/// 描述
/// </summary>
public ILocalizableString? Description { get; set; }
/// <summary>
/// API 身份验证密钥
/// </summary>
public string? ApiKey { get; set; }
/// <summary>
/// 自定义端点 URL
/// </summary>
public string? ApiBaseUrl { get; set; }
/// <summary>
/// 系统提示词
/// </summary>
public string? SystemPrompt { get; set; }
/// <summary>
/// 启用/禁用工作区
/// </summary>
public bool IsEnabled { get; set; }
[NotNull]
public Dictionary<string, object> Properties { get; }
public List<ISimpleStateChecker<WorkspaceDefinition>> StateCheckers { get; }
public WorkspaceDefinition(
string name,
string provider,
string modelName,
ILocalizableString displayName,
ILocalizableString? description = null)
{
Name = name;
Provider = provider;
ModelName = modelName;
_displayName = displayName;
_displayName = displayName;
Description = description;
IsEnabled = true;
Properties = new Dictionary<string, object>();
StateCheckers = new List<ISimpleStateChecker<WorkspaceDefinition>>();
}
public virtual WorkspaceDefinition WithApiBaseUrl(string apiBaseUrl)
{
ApiBaseUrl = apiBaseUrl;
return this;
}
public virtual WorkspaceDefinition WithApiKey(string apiKey)
{
ApiKey = apiKey;
return this;
}
public virtual WorkspaceDefinition WithProperty(string key, object value)
{
Properties[key] = value;
return this;
}
public override string ToString()
{
return $"[{nameof(WorkspaceDefinition)} {Name}]";
}
}

37
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinitionContext.cs

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace LINGYUN.Abp.AI.Workspaces;
public class WorkspaceDefinitionContext : IWorkspaceDefinitionContext
{
protected Dictionary<string, WorkspaceDefinition> Workspaces { get; }
public WorkspaceDefinitionContext(Dictionary<string, WorkspaceDefinition> workspaces)
{
Workspaces = workspaces;
}
public virtual WorkspaceDefinition? GetOrNull(string name)
{
return Workspaces.GetOrDefault(name);
}
public virtual IReadOnlyList<WorkspaceDefinition> GetAll()
{
return Workspaces.Values.ToImmutableList();
}
public virtual void Add(params WorkspaceDefinition[] definitions)
{
if (definitions.IsNullOrEmpty())
{
return;
}
foreach (var definition in definitions)
{
Workspaces[definition.Name] = definition;
}
}
}

52
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinitionManager.cs

@ -0,0 +1,52 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Workspaces;
public class WorkspaceDefinitionManager : IWorkspaceDefinitionManager, ISingletonDependency
{
protected readonly IStaticWorkspaceDefinitionStore StaticStore;
protected readonly IDynamicWorkspaceDefinitionStore DynamicStore;
public WorkspaceDefinitionManager(
IStaticWorkspaceDefinitionStore staticStore,
IDynamicWorkspaceDefinitionStore dynamicStore)
{
StaticStore = staticStore;
DynamicStore = dynamicStore;
}
public virtual async Task<WorkspaceDefinition> GetAsync(string name)
{
var workspace = await GetOrNullAsync(name);
if (workspace == null)
{
throw new AbpException("Undefined Workspace: " + name);
}
return workspace;
}
public virtual async Task<WorkspaceDefinition?> GetOrNullAsync(string name)
{
Check.NotNull(name, nameof(name));
return await StaticStore.GetOrNullAsync(name) ?? await DynamicStore.GetOrNullAsync(name);
}
public virtual async Task<IReadOnlyList<WorkspaceDefinition>> GetAllAsync()
{
var staticWorkspaces = await StaticStore.GetAllAsync();
var staticWorkspaceNames = staticWorkspaces
.Select(p => p.Name)
.ToImmutableHashSet();
var dynamicWorkspaces = await DynamicStore.GetAllAsync();
return staticWorkspaces.Concat(dynamicWorkspaces.Where(d => !staticWorkspaceNames.Contains(d.Name)))
.ToImmutableList();
}
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinitionProvider.cs

@ -0,0 +1,8 @@
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Workspaces;
public abstract class WorkspaceDefinitionProvider : IWorkspaceDefinitionProvider, ITransientDependency
{
public abstract void Define(IWorkspaceDefinitionContext context);
}

164
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/README.md

@ -0,0 +1,164 @@
# LINGYUN.Abp.AI.Core
[Abp AI Module](https://abp.io/docs/latest/framework/infrastructure/artificial-intelligence) 扩展.
## 功能特性
## 模块引用
```csharp
[DependsOn(typeof(AbpAICoreModule))]
public class YouProjectModule : AbpModule
{
// other
}
```
## 依赖模块
* [AbpAIModule](https://abp.io/docs/latest/framework/infrastructure/artificial-intelligence)
* [AbpLocalizationModule](https://abp.io/docs/latest/framework/fundamentals/localization)
## 基本用法
> 定义系统工作区
```csharp
[DependsOn(typeof(AbpAICoreModule))]
public class YouProjectModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpAIWorkspaceOptions>(options =>
{
options.Workspaces.Configure<YouWorkspace>(workspace =>
{
workspace.ConfigureChatClient(config =>
{
config.Builder = new ChatClientBuilder(
sp => new OpenAIClient(
new ApiKeyCredential("YouApiKey"),
new OpenAIClientOptions
{
Endpoint = new Uri("https://api.openai.com/v1"),
}).GetChatClient("GPT-4").AsIChatClient());
});
workspace.ConfigureKernel(config =>
{
config.Builder = Kernel.CreateBuilder()
.AddOpenAIChatClient(
modelId: "GPT-4",
openAIClient: new OpenAIClient(
new ApiKeyCredential("YouApiKey"),
new OpenAIClientOptions
{
Endpoint = new Uri("https://api.openai.com/v1"),
}));
});
});
});
}
}
```
> 兼容 `IKernelAccessor``IChatClientAccessor` 的语法.
```csharp
using LINGYUN.Abp.AI;
using LINGYUN.Abp.AI.Agent;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Volo.Abp;
var application = await AbpApplicationFactory.CreateAsync<YouProjectModule>(options =>
{
options.UseAutofac();
});
await application.InitializeAsync();
// 使用 IKernelFactory
Console.WriteLine("Use Microsoft.SemanticKernel:");
var kernelFactory = application.ServiceProvider.GetRequiredService<IKernelFactory>();
var kernel = await kernelFactory.CreateAsync<YouWorkspace>();
var kernelResponse = kernel.InvokePromptStreamingAsync("如何优化 C# 代码性能?");
await foreach (var item in kernelResponse)
{
Console.Write(item);
}
Console.WriteLine();
// 使用 IKernelAccessor
var kernelWithAbp = application.ServiceProvider.GetRequiredService<IKernelAccessor<YouWorkspace>>();
var kernelWithAbpResponse = kernelWithAbp.InvokePromptStreamingAsync("如何优化 C# 代码性能?");
await foreach (var item in kernelWithAbpResponse)
{
Console.Write(item);
}
Console.WriteLine();
await application.ShutdownAsync();
Console.WriteLine();
Console.WriteLine("AI Console completed!");
Console.ReadKey();
```
> 定义动态工作区
```csharp
public class YouWorkspaceDefinitionProvider : WorkspaceDefinitionProvider
{
public override void Define(IWorkspaceDefinitionContext context)
{
context.Add(
new WorkspaceDefinition(
"YouWorkspace",
OpenAIChatClientProvider.ProviderName,
"GPT-4",
new FixedLocalizableString("YouWorkspace"))
.WithApiKey("YouApiKey")
.WithApiBaseUrl("https://api.openai.com/v1"));
}
}
```
> 支持动态工作区语法.
```csharp
using LINGYUN.Abp.AI;
using LINGYUN.Abp.AI.Agent;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Volo.Abp;
var application = await AbpApplicationFactory.CreateAsync<YouProjectModule>(options =>
{
options.UseAutofac();
});
await application.InitializeAsync();
// Microsoft.SemanticKernel
Console.WriteLine("Use Microsoft.SemanticKernel:");
var kernelFactory = application.ServiceProvider.GetRequiredService<IKernelFactory>();
var kernel = await kernelFactory.CreateAsync("YouWorkspace");
var kernelResponse = kernel.InvokePromptStreamingAsync("如何优化 C# 代码性能?");
await foreach (var item in kernelResponse)
{
Console.Write(item);
}
Console.WriteLine();
await application.ShutdownAsync();
Console.WriteLine();
Console.WriteLine("AI Console completed!");
Console.ReadKey();
```
Loading…
Cancel
Save