committed by
GitHub
37 changed files with 1284 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -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> |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.AI.Agent; |
|||
|
|||
[DependsOn(typeof(AbpAICoreModule))] |
|||
public class AbpAIAgentModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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(); |
|||
|
|||
``` |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -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> |
|||
@ -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); |
|||
}); |
|||
} |
|||
} |
|||
@ -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>(); |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Abp.AI; |
|||
public interface IChatClientProviderManager |
|||
{ |
|||
List<IChatClientProvider> Providers { get; } |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Abp.AI; |
|||
public interface IKernelProviderManager |
|||
{ |
|||
List<IKernelProvider> Providers { get; } |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.AI.Localization; |
|||
|
|||
[LocalizationResourceName("AbpAI")] |
|||
public class AbpAIResource |
|||
{ |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
namespace LINGYUN.Abp.AI.Workspaces; |
|||
public interface IWorkspaceDefinitionProvider |
|||
{ |
|||
void Define(IWorkspaceDefinitionContext context); |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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}]"; |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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(); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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…
Reference in new issue