committed by
GitHub
49 changed files with 1152 additions and 25 deletions
@ -0,0 +1,16 @@ |
|||||
|
using LINGYUN.Abp.AI.Workspaces; |
||||
|
using Microsoft.Agents.AI; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Agent; |
||||
|
public class AbpAIAgentOptions |
||||
|
{ |
||||
|
public List<Action<WorkspaceDefinition?, AIAgentBuilder>> AgentBuildActions { get; } |
||||
|
public List<Action<WorkspaceDefinition?, ChatClientAgentOptions>> AgentOptionActions { get; } |
||||
|
public AbpAIAgentOptions() |
||||
|
{ |
||||
|
AgentBuildActions = new List<Action<WorkspaceDefinition?, AIAgentBuilder>>(); |
||||
|
AgentOptionActions = new List<Action<WorkspaceDefinition?, ChatClientAgentOptions>>(); |
||||
|
} |
||||
|
} |
||||
@ -1,11 +0,0 @@ |
|||||
using Microsoft.Extensions.AI; |
|
||||
using System; |
|
||||
|
|
||||
namespace LINGYUN.Abp.AI.Tools; |
|
||||
public static class GlobalFunctions |
|
||||
{ |
|
||||
public static AITool Now => AIFunctionFactory.Create( |
|
||||
() => DateTime.Now, |
|
||||
nameof(Now), |
|
||||
"Get now time"); |
|
||||
} |
|
||||
@ -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,27 @@ |
|||||
|
<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.Ollama</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.AI.Ollama</PackageId> |
||||
|
<NoWarn>$(NoWarn);SKEXP0001,SKEXP0010,SKEXP0070</NoWarn> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="OllamaSharp" /> |
||||
|
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Ollama" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.AI.Core\LINGYUN.Abp.AI.Core.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Ollama; |
||||
|
|
||||
|
[DependsOn(typeof(AbpAICoreModule))] |
||||
|
public class AbpAIOllamaModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpAICoreOptions>(options => |
||||
|
{ |
||||
|
options.ChatClientProviders.Add<OllamaChatClientProvider>(); |
||||
|
|
||||
|
options.KernelProviders.Add<OllamaKernelProvider>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
using LINGYUN.Abp.AI.Models; |
||||
|
using LINGYUN.Abp.AI.Workspaces; |
||||
|
using Microsoft.Extensions.AI; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using OllamaSharp; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Ollama; |
||||
|
public class OllamaChatClientProvider : ChatClientProvider |
||||
|
{ |
||||
|
public const string DefaultEndpoint = "http://localhost:11434"; |
||||
|
|
||||
|
public const string ProviderName = "Ollama"; |
||||
|
public override string Name => ProviderName; |
||||
|
|
||||
|
public OllamaChatClientProvider( |
||||
|
IServiceProvider serviceProvider) : base(serviceProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async override Task<IChatClient> CreateAsync(WorkspaceDefinition workspace) |
||||
|
{ |
||||
|
Check.NotNull(workspace, nameof(workspace)); |
||||
|
|
||||
|
var options = ServiceProvider.GetRequiredService<IOptions<AbpAICoreOptions>>().Value; |
||||
|
|
||||
|
var ollamaApiClient = new OllamaApiClient(workspace.ApiBaseUrl ?? DefaultEndpoint); |
||||
|
|
||||
|
var chatClientBuilder = ChatClientBuilderChatClientExtensions.AsBuilder(ollamaApiClient); |
||||
|
|
||||
|
foreach (var handlerAction in options.ChatClientBuildActions) |
||||
|
{ |
||||
|
await handlerAction(workspace, ServiceProvider, chatClientBuilder); |
||||
|
} |
||||
|
|
||||
|
return chatClientBuilder |
||||
|
.UseLogging() |
||||
|
.UseOpenTelemetry() |
||||
|
.UseFunctionInvocation() |
||||
|
.UseDistributedCache() |
||||
|
.Build(ServiceProvider); |
||||
|
} |
||||
|
|
||||
|
public override ChatModel[] GetModels() |
||||
|
{ |
||||
|
return []; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using LINGYUN.Abp.AI.Workspaces; |
||||
|
using Microsoft.Extensions.AI; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.SemanticKernel; |
||||
|
using OllamaSharp; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Ollama; |
||||
|
public class OllamaKernelProvider : KernelProvider |
||||
|
{ |
||||
|
public const string ProviderName = "Ollama"; |
||||
|
public override string Name => ProviderName; |
||||
|
|
||||
|
public OllamaKernelProvider(IServiceProvider serviceProvider) : base(serviceProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override Task<Kernel> CreateAsync(WorkspaceDefinition workspace) |
||||
|
{ |
||||
|
Check.NotNull(workspace, nameof(workspace)); |
||||
|
|
||||
|
var options = ServiceProvider.GetRequiredService<IOptions<AbpAICoreOptions>>().Value; |
||||
|
|
||||
|
var ollamaApiClient = new OllamaApiClient(workspace.ApiBaseUrl ?? OllamaChatClientProvider.DefaultEndpoint); |
||||
|
|
||||
|
var kernelBuilder = Kernel.CreateBuilder() |
||||
|
.AddOllamaChatClient(ollamaApiClient); |
||||
|
|
||||
|
foreach (var handlerAction in options.KernelBuildActions) |
||||
|
{ |
||||
|
handlerAction(workspace, kernelBuilder); |
||||
|
} |
||||
|
|
||||
|
return Task.FromResult(kernelBuilder.Build()); |
||||
|
} |
||||
|
} |
||||
@ -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,26 @@ |
|||||
|
<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.Tools</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.AI.Tools</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Remove="LINGYUN\Abp\AI\Tools\Localization\Resources\*.json" /> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\AI\Tools\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.AI.Core\LINGYUN.Abp.AI.Core.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,55 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.SimpleStateChecking; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
|
||||
|
public class AIToolDefinition : IHasSimpleStateCheckers<AIToolDefinition> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 名称
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Name { get; } |
||||
|
/// <summary>
|
||||
|
/// 提供者
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Provider { get; } |
||||
|
/// <summary>
|
||||
|
/// 描述
|
||||
|
/// </summary>
|
||||
|
public ILocalizableString? Description { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 属性
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public Dictionary<string, object?> Properties { get; } |
||||
|
|
||||
|
public List<ISimpleStateChecker<AIToolDefinition>> StateCheckers { get; } |
||||
|
|
||||
|
public AIToolDefinition( |
||||
|
[NotNull] string name, |
||||
|
[NotNull] string provider, |
||||
|
ILocalizableString? description = null) |
||||
|
{ |
||||
|
Name = name; |
||||
|
Provider = provider; |
||||
|
Description = description; |
||||
|
|
||||
|
Properties = new Dictionary<string, object?>(); |
||||
|
StateCheckers = new List<ISimpleStateChecker<AIToolDefinition>>(); |
||||
|
} |
||||
|
|
||||
|
public virtual AIToolDefinition WithProperty(string key, object? value) |
||||
|
{ |
||||
|
Properties[key] = value; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
return $"[{nameof(AIToolDefinition)} {Name}]"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public class AIToolDefinitionContext : IAIToolDefinitionContext |
||||
|
{ |
||||
|
protected Dictionary<string, AIToolDefinition> Tools { get; } |
||||
|
|
||||
|
public AIToolDefinitionContext(Dictionary<string, AIToolDefinition> tools) |
||||
|
{ |
||||
|
Tools = tools; |
||||
|
} |
||||
|
|
||||
|
public virtual AIToolDefinition? GetOrNull(string name) |
||||
|
{ |
||||
|
return Tools.GetOrDefault(name); |
||||
|
} |
||||
|
|
||||
|
public virtual IReadOnlyList<AIToolDefinition> GetAll() |
||||
|
{ |
||||
|
return Tools.Values.ToImmutableList(); |
||||
|
} |
||||
|
|
||||
|
public virtual void Add(params AIToolDefinition[] definitions) |
||||
|
{ |
||||
|
if (definitions.IsNullOrEmpty()) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
foreach (var definition in definitions) |
||||
|
{ |
||||
|
Tools[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.Tools; |
||||
|
public class AIToolDefinitionManager : IAIToolDefinitionManager, ISingletonDependency |
||||
|
{ |
||||
|
protected readonly IStaticAIToolDefinitionStore StaticStore; |
||||
|
protected readonly IDynamicAIToolDefinitionStore DynamicStore; |
||||
|
|
||||
|
public AIToolDefinitionManager( |
||||
|
IStaticAIToolDefinitionStore staticStore, |
||||
|
IDynamicAIToolDefinitionStore dynamicStore) |
||||
|
{ |
||||
|
StaticStore = staticStore; |
||||
|
DynamicStore = dynamicStore; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<AIToolDefinition> GetAsync(string name) |
||||
|
{ |
||||
|
var workspace = await GetOrNullAsync(name); |
||||
|
if (workspace == null) |
||||
|
{ |
||||
|
throw new AbpException("Undefined AITool: " + name); |
||||
|
} |
||||
|
|
||||
|
return workspace; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<AIToolDefinition?> GetOrNullAsync(string name) |
||||
|
{ |
||||
|
Check.NotNull(name, nameof(name)); |
||||
|
|
||||
|
return await StaticStore.GetOrNullAsync(name) ?? await DynamicStore.GetOrNullAsync(name); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IReadOnlyList<AIToolDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticAITools = await StaticStore.GetAllAsync(); |
||||
|
var staticAIToolNames = staticAITools |
||||
|
.Select(p => p.Name) |
||||
|
.ToImmutableHashSet(); |
||||
|
|
||||
|
var dynamicAITools = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
return staticAITools.Concat(dynamicAITools.Where(d => !staticAIToolNames.Contains(d.Name))) |
||||
|
.ToImmutableList(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public abstract class AIToolDefinitionProvider : IAIToolDefinitionProvider, ITransientDependency |
||||
|
{ |
||||
|
public abstract void Define(IAIToolDefinitionContext context); |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
using Microsoft.Extensions.AI; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.SimpleStateChecking; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public class AIToolFactory : IAIToolFactory, ITransientDependency |
||||
|
{ |
||||
|
protected ISimpleStateCheckerManager<AIToolDefinition> StateCheckerManager { get; } |
||||
|
protected IAIToolDefinitionManager AIToolDefinitionManager { get; } |
||||
|
protected IAIToolProviderManager AIToolProviderManager { get; } |
||||
|
|
||||
|
public AIToolFactory( |
||||
|
ISimpleStateCheckerManager<AIToolDefinition> stateCheckerManager, |
||||
|
IAIToolDefinitionManager aIToolDefinitionManager, |
||||
|
IAIToolProviderManager aIToolProviderManager) |
||||
|
{ |
||||
|
StateCheckerManager = stateCheckerManager; |
||||
|
AIToolDefinitionManager = aIToolDefinitionManager; |
||||
|
AIToolProviderManager = aIToolProviderManager; |
||||
|
} |
||||
|
|
||||
|
public virtual AITool CreateTool(AIToolDefinition definition) |
||||
|
{ |
||||
|
foreach (var provider in AIToolProviderManager.Providers) |
||||
|
{ |
||||
|
if (!string.Equals(provider.Name, definition.Provider)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
return provider.CreateTool(definition); |
||||
|
} |
||||
|
|
||||
|
throw new AbpException($"The AITool provider implementation named {definition.Provider} was not found!"); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<AITool[]> CreateAllTools() |
||||
|
{ |
||||
|
var aiTools = new List<AITool>(); |
||||
|
var toolDefines = await AIToolDefinitionManager.GetAllAsync(); |
||||
|
|
||||
|
foreach (var toolDefine in toolDefines) |
||||
|
{ |
||||
|
if (await StateCheckerManager.IsEnabledAsync(toolDefine)) |
||||
|
{ |
||||
|
aiTools.Add(CreateTool(toolDefine)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return aiTools.ToArray(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
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.Tools; |
||||
|
public class AIToolProviderManager : IAIToolProviderManager, ISingletonDependency |
||||
|
{ |
||||
|
public List<IAIToolProvider> Providers => _lazyProviders.Value; |
||||
|
|
||||
|
protected AbpAIToolsOptions Options { get; } |
||||
|
protected IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
private readonly Lazy<List<IAIToolProvider>> _lazyProviders; |
||||
|
|
||||
|
public AIToolProviderManager( |
||||
|
IServiceProvider serviceProvider, |
||||
|
IOptions<AbpAIToolsOptions> options) |
||||
|
{ |
||||
|
|
||||
|
Options = options.Value; |
||||
|
ServiceProvider = serviceProvider; |
||||
|
|
||||
|
_lazyProviders = new Lazy<List<IAIToolProvider>>(GetProviders, true); |
||||
|
} |
||||
|
|
||||
|
protected virtual List<IAIToolProvider> GetProviders() |
||||
|
{ |
||||
|
var providers = Options |
||||
|
.AIToolProviders |
||||
|
.Select(type => (ServiceProvider.GetRequiredService(type) as IAIToolProvider)!) |
||||
|
.ToList(); |
||||
|
|
||||
|
var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); |
||||
|
if (multipleProviders != null) |
||||
|
{ |
||||
|
throw new AbpException($"Duplicate AITool provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); |
||||
|
} |
||||
|
|
||||
|
return providers; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
using LINGYUN.Abp.AI.Localization; |
||||
|
using Microsoft.Extensions.AI; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
|
||||
|
[DependsOn(typeof(AbpAICoreModule))] |
||||
|
public class AbpAIToolsModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
AutoAddDefinitionProviders(context.Services); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpAIToolsModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpAIToolsOptions>(options => |
||||
|
{ |
||||
|
// 自定义函数工具
|
||||
|
options.AIToolProviders.Add<FunctionAIToolProvider>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpAICoreOptions>(options => |
||||
|
{ |
||||
|
options.ChatClientBuildActions.Add(async (_, sp, builder) => |
||||
|
{ |
||||
|
var aiToolFactory = sp.GetRequiredService<IAIToolFactory>(); |
||||
|
var aiTools = await aiToolFactory.CreateAllTools(); |
||||
|
|
||||
|
builder.ConfigureOptions(ai => |
||||
|
{ |
||||
|
ai.ToolMode = ChatToolMode.Auto; |
||||
|
ai.AllowMultipleToolCalls = true; |
||||
|
|
||||
|
ai.Tools ??= []; |
||||
|
|
||||
|
foreach (var aiTool in aiTools) |
||||
|
{ |
||||
|
ai.Tools.Add(aiTool); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<AbpAIResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/AI/Tools/Localization/Resources"); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private static void AutoAddDefinitionProviders(IServiceCollection services) |
||||
|
{ |
||||
|
var definitionProviders = new List<Type>(); |
||||
|
|
||||
|
services.OnRegistered(context => |
||||
|
{ |
||||
|
if (typeof(IAIToolDefinitionProvider).IsAssignableFrom(context.ImplementationType)) |
||||
|
{ |
||||
|
definitionProviders.Add(context.ImplementationType); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
services.Configure<AbpAIToolsOptions>(options => |
||||
|
{ |
||||
|
options.DefinitionProviders.AddIfNotContains(definitionProviders); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.Abp.Collections; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public class AbpAIToolsOptions |
||||
|
{ |
||||
|
public ITypeList<IAIToolDefinitionProvider> DefinitionProviders { get; } |
||||
|
public ITypeList<IAIToolProvider> AIToolProviders { get; } |
||||
|
public AbpAIToolsOptions() |
||||
|
{ |
||||
|
DefinitionProviders = new TypeList<IAIToolDefinitionProvider>(); |
||||
|
AIToolProviders = new TypeList<IAIToolProvider>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public static class FunctionAIToolDefinitionExtenssions |
||||
|
{ |
||||
|
private const string FunctionType = "Function"; |
||||
|
public static AIToolDefinition WithFunction<TFunc>(this AIToolDefinition definition) |
||||
|
{ |
||||
|
return definition.WithFunction(typeof(TFunc)); |
||||
|
} |
||||
|
|
||||
|
public static AIToolDefinition WithFunction(this AIToolDefinition definition, Type funcType) |
||||
|
{ |
||||
|
Check.NotNull(funcType, nameof(funcType)); |
||||
|
|
||||
|
definition.WithProperty(FunctionType, funcType); |
||||
|
|
||||
|
return definition; |
||||
|
} |
||||
|
|
||||
|
public static Type GetFunction(this AIToolDefinition definition) |
||||
|
{ |
||||
|
var funcTypeSet = definition.Properties.GetOrDefault(FunctionType); |
||||
|
Check.NotNull(funcTypeSet, nameof(FunctionType)); |
||||
|
|
||||
|
var funcType = Type.GetType(funcTypeSet.ToString()!); |
||||
|
|
||||
|
Check.NotNull(funcType, nameof(funcType)); |
||||
|
|
||||
|
return funcType; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using Microsoft.Extensions.AI; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public class FunctionAIToolProvider : IAIToolProvider, ITransientDependency |
||||
|
{ |
||||
|
public const string ProviderName = "Function"; |
||||
|
public string Name => ProviderName; |
||||
|
|
||||
|
protected IServiceProvider ServiceProvider { get; } |
||||
|
public FunctionAIToolProvider(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public virtual AITool CreateTool(AIToolDefinition definition) |
||||
|
{ |
||||
|
var aiToolType = definition.GetFunction(); |
||||
|
// 框架约定, 自定义Tool只需要定义同步方法(Invoke)或异步方法(InvokeAsync)即可
|
||||
|
var aiToolMethodInfo = aiToolType.GetMethod("Invoke") ?? aiToolType.GetMethod("InvokeAsync"); |
||||
|
|
||||
|
Check.NotNull(aiToolMethodInfo, nameof(aiToolMethodInfo)); |
||||
|
|
||||
|
string? description = null; |
||||
|
if (definition.Description != null) |
||||
|
{ |
||||
|
var localizerFactory = ServiceProvider.GetRequiredService<IStringLocalizerFactory>(); |
||||
|
description = definition.Description.Localize(localizerFactory)?.Value; |
||||
|
} |
||||
|
|
||||
|
return AIFunctionFactory.Create( |
||||
|
method: aiToolMethodInfo, |
||||
|
createInstanceFunc: (AIFunctionArguments args) => |
||||
|
{ |
||||
|
return ActivatorUtilities.CreateInstance(args.Services ?? ServiceProvider, aiToolType); |
||||
|
}, |
||||
|
options: new AIFunctionFactoryOptions |
||||
|
{ |
||||
|
Name = definition.Name, |
||||
|
Description = description, |
||||
|
AdditionalProperties = definition.Properties, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
using LINGYUN.Abp.AI.Localization; |
||||
|
using LINGYUN.Abp.AI.Tools.Settings; |
||||
|
using LINGYUN.Abp.AI.Tools.Timing; |
||||
|
using LINGYUN.Abp.AI.Tools.Users; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public class GlobalAIToolDefinitionProvider : AIToolDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IAIToolDefinitionContext context) |
||||
|
{ |
||||
|
context.Add( |
||||
|
new AIToolDefinition( |
||||
|
NowTimeTool.Name, |
||||
|
FunctionAIToolProvider.ProviderName, |
||||
|
L("Tools:GetNowTime")) |
||||
|
.WithFunction<NowTimeTool>(), |
||||
|
|
||||
|
new AIToolDefinition( |
||||
|
CurrentUserTool.Name, |
||||
|
FunctionAIToolProvider.ProviderName, |
||||
|
L("Tools:GetUserInfo")) |
||||
|
.WithFunction<CurrentUserTool>(), |
||||
|
|
||||
|
new AIToolDefinition( |
||||
|
GetSettingTool.Name, |
||||
|
FunctionAIToolProvider.ProviderName, |
||||
|
L("Tools:GetSetting")) |
||||
|
.WithFunction<GetSettingTool>(), |
||||
|
new AIToolDefinition( |
||||
|
GetSettingsTool.Name, |
||||
|
FunctionAIToolProvider.ProviderName, |
||||
|
L("Tools:GetSettings")) |
||||
|
.WithFunction<GetSettingsTool>()); |
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<AbpAIResource>(name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IAIToolDefinitionContext |
||||
|
{ |
||||
|
AIToolDefinition? GetOrNull(string name); |
||||
|
|
||||
|
IReadOnlyList<AIToolDefinition> GetAll(); |
||||
|
|
||||
|
void Add(params AIToolDefinition[] definitions); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IAIToolDefinitionManager |
||||
|
{ |
||||
|
[NotNull] |
||||
|
Task<AIToolDefinition> GetAsync([NotNull] string name); |
||||
|
|
||||
|
[ItemNotNull] |
||||
|
Task<IReadOnlyList<AIToolDefinition>> GetAllAsync(); |
||||
|
|
||||
|
[CanBeNull] |
||||
|
Task<AIToolDefinition?> GetOrNullAsync([NotNull] string name); |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IAIToolDefinitionProvider |
||||
|
{ |
||||
|
void Define(IAIToolDefinitionContext context); |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Microsoft.Extensions.AI; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IAIToolFactory |
||||
|
{ |
||||
|
AITool CreateTool(AIToolDefinition definition); |
||||
|
|
||||
|
Task<AITool[]> CreateAllTools(); |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Microsoft.Extensions.AI; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IAIToolProvider |
||||
|
{ |
||||
|
string Name { get; } |
||||
|
|
||||
|
AITool CreateTool(AIToolDefinition definition); |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IAIToolProviderManager |
||||
|
{ |
||||
|
List<IAIToolProvider> Providers { get; } |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IDynamicAIToolDefinitionStore |
||||
|
{ |
||||
|
Task<AIToolDefinition> GetAsync([NotNull] string name); |
||||
|
|
||||
|
Task<IReadOnlyList<AIToolDefinition>> GetAllAsync(); |
||||
|
|
||||
|
Task<AIToolDefinition?> GetOrNullAsync([NotNull] string name); |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
public interface IStaticAIToolDefinitionStore |
||||
|
{ |
||||
|
Task<AIToolDefinition> GetAsync([NotNull] string name); |
||||
|
|
||||
|
Task<IReadOnlyList<AIToolDefinition>> GetAllAsync(); |
||||
|
|
||||
|
Task<AIToolDefinition?> GetOrNullAsync([NotNull] string name); |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Tools": "Tools", |
||||
|
"Tools:GetNowTime": "Get now time", |
||||
|
"Tools:GetUserInfo": "Get the current user information", |
||||
|
"Tools:GetSetting": "Get setting value", |
||||
|
"Tools:GetSettings": "Get all settings" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Tools": "工具列表", |
||||
|
"Tools:GetNowTime": "获取当前时间", |
||||
|
"Tools:GetUserInfo": "获取当前用户信息", |
||||
|
"Tools:GetSetting": "获取设置值", |
||||
|
"Tools:GetSettings": "获取所有设置" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools; |
||||
|
|
||||
|
[Dependency(TryRegister = true)] |
||||
|
public class NullDynamicAIToolDefinitionStore : IDynamicAIToolDefinitionStore, ISingletonDependency |
||||
|
{ |
||||
|
private readonly static Task<AIToolDefinition?> CachedNullableAIToolResult = Task.FromResult((AIToolDefinition?)null); |
||||
|
private readonly static Task<AIToolDefinition> CachedAIToolResult = Task.FromResult((AIToolDefinition)null!); |
||||
|
|
||||
|
private readonly static Task<IReadOnlyList<AIToolDefinition>> CachedAIToolsResult = Task.FromResult( |
||||
|
(IReadOnlyList<AIToolDefinition>)Array.Empty<AIToolDefinition>().ToImmutableList()); |
||||
|
|
||||
|
public Task<AIToolDefinition> GetAsync(string name) |
||||
|
{ |
||||
|
return CachedAIToolResult; |
||||
|
} |
||||
|
|
||||
|
public Task<IReadOnlyList<AIToolDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
return CachedAIToolsResult; |
||||
|
} |
||||
|
|
||||
|
public Task<AIToolDefinition?> GetOrNullAsync(string name) |
||||
|
{ |
||||
|
return CachedNullableAIToolResult; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Settings; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools.Settings; |
||||
|
public class GetSettingTool : ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "GetSetting"; |
||||
|
|
||||
|
private readonly ISettingProvider _settingProvider; |
||||
|
public GetSettingTool(ISettingProvider settingProvider) |
||||
|
{ |
||||
|
_settingProvider = settingProvider; |
||||
|
} |
||||
|
|
||||
|
public async Task<object?> InvokeAsync(string name) |
||||
|
{ |
||||
|
return await _settingProvider.GetOrNullAsync(name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Settings; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools.Settings; |
||||
|
public class GetSettingsTool : ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "GetSettings"; |
||||
|
|
||||
|
private readonly ISettingProvider _settingProvider; |
||||
|
public GetSettingsTool(ISettingProvider settingProvider) |
||||
|
{ |
||||
|
_settingProvider = settingProvider; |
||||
|
} |
||||
|
|
||||
|
public async Task<object?> InvokeAsync() |
||||
|
{ |
||||
|
return await _settingProvider.GetAllAsync(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
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.Tools; |
||||
|
public class StaticAIToolDefinitionStore : IStaticAIToolDefinitionStore, ISingletonDependency |
||||
|
{ |
||||
|
protected IServiceProvider ServiceProvider { get; } |
||||
|
protected AbpAIToolsOptions Options { get; } |
||||
|
protected IStaticDefinitionCache<AIToolDefinition, Dictionary<string, AIToolDefinition>> DefinitionCache { get; } |
||||
|
|
||||
|
public StaticAIToolDefinitionStore( |
||||
|
IServiceProvider serviceProvider, |
||||
|
IOptions<AbpAIToolsOptions> options, |
||||
|
IStaticDefinitionCache<AIToolDefinition, Dictionary<string, AIToolDefinition>> definitionCache) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
Options = options.Value; |
||||
|
DefinitionCache = definitionCache; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<AIToolDefinition> GetAsync(string name) |
||||
|
{ |
||||
|
Check.NotNull(name, nameof(name)); |
||||
|
|
||||
|
var workspace = await GetOrNullAsync(name); |
||||
|
|
||||
|
if (workspace == null) |
||||
|
{ |
||||
|
throw new AbpException("Undefined AITool: " + name); |
||||
|
} |
||||
|
|
||||
|
return workspace; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IReadOnlyList<AIToolDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var defs = await GetAIToolDefinitionsAsync(); |
||||
|
return defs.Values.ToImmutableList(); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<AIToolDefinition?> GetOrNullAsync(string name) |
||||
|
{ |
||||
|
var defs = await GetAIToolDefinitionsAsync(); |
||||
|
return defs.GetOrDefault(name); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<Dictionary<string, AIToolDefinition>> GetAIToolDefinitionsAsync() |
||||
|
{ |
||||
|
return await DefinitionCache.GetOrCreateAsync(CreateAIToolDefinitionsAsync); |
||||
|
} |
||||
|
|
||||
|
protected virtual Task<Dictionary<string, AIToolDefinition>> CreateAIToolDefinitionsAsync() |
||||
|
{ |
||||
|
var workspaces = new Dictionary<string, AIToolDefinition>(); |
||||
|
|
||||
|
using (var scope = ServiceProvider.CreateScope()) |
||||
|
{ |
||||
|
var providers = Options |
||||
|
.DefinitionProviders |
||||
|
.Select(p => scope.ServiceProvider.GetRequiredService(p) as IAIToolDefinitionProvider) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var provider in providers) |
||||
|
{ |
||||
|
provider?.Define(new AIToolDefinitionContext(workspaces)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return Task.FromResult(workspaces); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,19 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Timing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools.Timing; |
||||
|
public class NowTimeTool : ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "GetNowTime"; |
||||
|
|
||||
|
private readonly IClock _clock; |
||||
|
public NowTimeTool(IClock clock) |
||||
|
{ |
||||
|
_clock = clock; |
||||
|
} |
||||
|
|
||||
|
public object? Invoke() |
||||
|
{ |
||||
|
return _clock.Now; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AI.Tools.Users; |
||||
|
|
||||
|
public class CurrentUserTool : ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "GetUserInfo"; |
||||
|
|
||||
|
private readonly ICurrentUser _currentUser; |
||||
|
|
||||
|
public CurrentUserTool(ICurrentUser currentUser) |
||||
|
{ |
||||
|
_currentUser = currentUser; |
||||
|
} |
||||
|
|
||||
|
public object? Invoke() |
||||
|
{ |
||||
|
return _currentUser; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,79 @@ |
|||||
|
# LINGYUN.Abp.AI.Tools |
||||
|
|
||||
|
AI 工具模块. |
||||
|
|
||||
|
参考: [AI 工具调用](https://learn.microsoft.com/zh-cn/dotnet/ai/conceptual/ai-tools) |
||||
|
|
||||
|
## 功能特性 |
||||
|
|
||||
|
|
||||
|
## 模块引用 |
||||
|
|
||||
|
```csharp |
||||
|
[DependsOn(typeof(AbpAIToolsModule))] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
// other |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 依赖模块 |
||||
|
|
||||
|
* [AbpAICoreModule](../LINGYUN.Abp.AI.Core) |
||||
|
|
||||
|
## 自定义函数 |
||||
|
|
||||
|
> 注意: 自定义函数遵循一个约定: 同步工具需要定义一个名为 `Invoke` 的函数; 异步工具需要定义一个名为 `InvokeAsync` 的函数, 如需使用DI容器, 需要将工具注入到容器 |
||||
|
|
||||
|
```csharp |
||||
|
|
||||
|
public class NowTimeTool : ITransientDependency |
||||
|
{ |
||||
|
private readonly IClock _clock; |
||||
|
public NowTimeTool(IClock clock) |
||||
|
{ |
||||
|
_clock = clock; |
||||
|
} |
||||
|
|
||||
|
public object? Invoke() |
||||
|
{ |
||||
|
return _clock.Now; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class NowTimeAIToolDefinitionProvider : AIToolDefinitionProvider |
||||
|
{ |
||||
|
context.Add( |
||||
|
new AIToolDefinition( |
||||
|
"GetNowTime", |
||||
|
FunctionAIToolProvider.ProviderName) |
||||
|
.WithFunction<NowTimeTool>()); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 扩展 |
||||
|
|
||||
|
实现 `IAIToolProvider` 接口, 以增加其他工具调用 |
||||
|
实现 `IDynamicAIToolDefinitionStore` 接口, 以增加动态AI工具管理 |
||||
|
|
||||
|
```csharp |
||||
|
public class McpAIToolProvider : IAIToolProvider, ITransientDependency |
||||
|
{ |
||||
|
public virtual AITool CreateTool(AIToolDefinition definition) |
||||
|
{ |
||||
|
// 你的具体实现 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[DependsOn(typeof(AbpAIToolsModule))] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpAIToolsOptions>(options => |
||||
|
{ |
||||
|
options.AIToolProviders.Add<McpAIToolProvider>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
Loading…
Reference in new issue