Browse Source

feat(ai): Add the AI tools module

pull/1454/head
colin 6 months ago
parent
commit
1307449658
  1. 2
      Directory.Packages.props
  2. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/FodyWeavers.xml
  3. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/FodyWeavers.xsd
  4. 26
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN.Abp.AI.Tools.csproj
  5. 55
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinition.cs
  6. 37
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinitionContext.cs
  7. 52
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinitionManager.cs
  8. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinitionProvider.cs
  9. 55
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolFactory.cs
  10. 45
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolProviderManager.cs
  11. 80
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs
  12. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsOptions.cs
  13. 34
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/FunctionAIToolDefinitionExtenssions.cs
  14. 48
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/FunctionAIToolProvider.cs
  15. 41
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/GlobalAIToolDefinitionProvider.cs
  16. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolDefinitionContext.cs
  17. 16
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolDefinitionManager.cs
  18. 5
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolDefinitionProvider.cs
  19. 10
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolFactory.cs
  20. 9
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolProvider.cs
  21. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolProviderManager.cs
  22. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IDynamicAIToolDefinitionStore.cs
  23. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IStaticAIToolDefinitionStore.cs
  24. 10
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Localization/Resources/en.json
  25. 10
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Localization/Resources/zh-Hans.json
  26. 32
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/NullDynamicAIToolDefinitionStore.cs
  27. 20
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Settings/GetSettingTool.cs
  28. 20
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Settings/GetSettingsTool.cs
  29. 80
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/StaticAIToolDefinitionStore.cs
  30. 19
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Timing/NowTimeTool.cs
  31. 21
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Users/CurrentUserTool.cs
  32. 79
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/README.md

2
Directory.Packages.props

@ -348,6 +348,8 @@
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="8.19.4" />
<PackageVersion Include="NRules" Version="0.9.2" />
<PackageVersion Include="Ocelot.Provider.Polly" Version="20.0.0" />
<PackageVersion Include="OllamaSharp" Version="5.4.20" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.74.0-alpha" />
<PackageVersion Include="OpenIddict.Server.DataProtection" Version="7.2.0" />
<PackageVersion Include="OpenIddict.Validation.DataProtection" Version="7.2.0" />
<PackageVersion Include="Polly" Version="8.6.3" />

3
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/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.Tools/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>

26
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN.Abp.AI.Tools.csproj

@ -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>

55
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinition.cs

@ -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}]";
}
}

37
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinitionContext.cs

@ -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;
}
}
}

52
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinitionManager.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.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();
}
}

7
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolDefinitionProvider.cs

@ -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);
}

55
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolFactory.cs

@ -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();
}
}

45
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolProviderManager.cs

@ -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;
}
}

80
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs

@ -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);
});
}
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsOptions.cs

@ -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>();
}
}

34
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/FunctionAIToolDefinitionExtenssions.cs

@ -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;
}
}

48
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/FunctionAIToolProvider.cs

@ -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,
});
}
}

41
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/GlobalAIToolDefinitionProvider.cs

@ -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);
}
}

11
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolDefinitionContext.cs

@ -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);
}

16
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolDefinitionManager.cs

@ -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);
}

5
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolDefinitionProvider.cs

@ -0,0 +1,5 @@
namespace LINGYUN.Abp.AI.Tools;
public interface IAIToolDefinitionProvider
{
void Define(IAIToolDefinitionContext context);
}

10
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolFactory.cs

@ -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();
}

9
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolProvider.cs

@ -0,0 +1,9 @@
using Microsoft.Extensions.AI;
namespace LINGYUN.Abp.AI.Tools;
public interface IAIToolProvider
{
string Name { get; }
AITool CreateTool(AIToolDefinition definition);
}

7
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolProviderManager.cs

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

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IDynamicAIToolDefinitionStore.cs

@ -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);
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IStaticAIToolDefinitionStore.cs

@ -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);
}

10
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Localization/Resources/en.json

@ -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"
}
}

10
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Localization/Resources/zh-Hans.json

@ -0,0 +1,10 @@
{
"culture": "zh-Hans",
"texts": {
"Tools": "工具列表",
"Tools:GetNowTime": "获取当前时间",
"Tools:GetUserInfo": "获取当前用户信息",
"Tools:GetSetting": "获取设置值",
"Tools:GetSettings": "获取所有设置"
}
}

32
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/NullDynamicAIToolDefinitionStore.cs

@ -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;
}
}

20
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Settings/GetSettingTool.cs

@ -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);
}
}

20
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Settings/GetSettingsTool.cs

@ -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();
}
}

80
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/StaticAIToolDefinitionStore.cs

@ -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);
}
}

19
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Timing/NowTimeTool.cs

@ -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;
}
}

21
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/Users/CurrentUserTool.cs

@ -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;
}
}

79
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/README.md

@ -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…
Cancel
Save