Browse Source

Merge pull request #1456 from colinin/ai

Support AI Tools
pull/1467/head
yx lin 6 months ago
committed by GitHub
parent
commit
70f4f66d72
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      Directory.Packages.props
  2. 3
      aspnet-core/LINGYUN.MicroService.Aspire.slnx
  3. 8
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs
  4. 3
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/LINGYUN.Abp.MicroService.AIService.csproj
  5. 8
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json
  6. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/FodyWeavers.xml
  7. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/FodyWeavers.xsd
  8. 31
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN.Abp.AI.Tools.Http.csproj
  9. 42
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/AbpAIToolsHttpModule.cs
  10. 31
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/AbpAIToolsHttpOptiions.cs
  11. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/ApplicationConfigurations/AbpAIToolsApplicationConfigurationOptions.cs
  12. 36
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/GlobalHttpAIToolDefinitionProvider.cs
  13. 136
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAITool.cs
  14. 150
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolDefinitionExtenssions.cs
  15. 15
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolInvokeContext.cs
  16. 47
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolProvider.cs
  17. 6
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/Localization/Resources/en.json
  18. 6
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/Localization/Resources/zh-Hans.json
  19. 48
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/Microsoft/Extensions/DependencyInjection/HttpClientHttpAIToolExtenssions.cs
  20. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/FodyWeavers.xml
  21. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/FodyWeavers.xsd
  22. 26
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN.Abp.AI.Tools.Mcp.csproj
  23. 22
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN/Abp/AI/Tools/Mcp/AbpAIToolsMcpModule.cs
  24. 150
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN/Abp/AI/Tools/Mcp/McpAIToolDefinitionExtenssions.cs
  25. 63
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN/Abp/AI/Tools/Mcp/McpAIToolProvider.cs
  26. 18
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/Microsoft/Extensions/DependencyInjection/HttpClientMcpAIToolExtenssions.cs
  27. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AIToolFactory.cs
  28. 2
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/FunctionAIToolDefinitionExtenssions.cs
  29. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/FunctionAIToolProvider.cs
  30. 2
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/GlobalFunctionAIToolDefinitionProvider.cs
  31. 2
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolFactory.cs
  32. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/IAIToolProvider.cs
  33. 2
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/README.md

1
Directory.Packages.props

@ -349,6 +349,7 @@
<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="ModelContextProtocol" Version="1.1.0" />
<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" />

3
aspnet-core/LINGYUN.MicroService.Aspire.slnx

@ -285,6 +285,9 @@
<Project Path="modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN.Abp.AI.Agent.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AI.Core/LINGYUN.Abp.AI.Core.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AI.Ollama/LINGYUN.Abp.AI.Ollama.csproj" Id="d59e459c-7ca2-4c5b-b981-685af7ad2848" />
<Project Path="modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN.Abp.AI.Tools.Http.csproj" Id="d54a5812-80e1-4269-856b-672c23c0a49b" />
<Project Path="modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN.Abp.AI.Tools.Mcp.csproj" Id="a516491e-0862-49aa-8de9-9e23d7f21d3d" />
<Project Path="modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN.Abp.AI.Tools.csproj" Id="49756a42-07d5-4ddd-948e-1e99894a383a" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN.Abp.AIManagement.Application.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN.Abp.AIManagement.Domain.Shared.csproj" />

8
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs

@ -1,5 +1,7 @@
using LINGYUN.Abp.AI.Ollama;
using LINGYUN.Abp.AI.Tools;
using LINGYUN.Abp.AI.Tools.Http;
using LINGYUN.Abp.AI.Tools.Mcp;
using LINGYUN.Abp.AIManagement;
using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.AspNetCore.Mvc.Localization;
@ -22,7 +24,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Http.Client;
using Volo.Abp.Http.Client.IdentityModel.Web;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.PermissionManagement.OpenIddict;
@ -50,13 +52,15 @@ namespace LINGYUN.Abp.MicroService.AIService;
typeof(AbpAIOllamaModule),
typeof(AbpAIToolsModule),
typeof(AbpAIToolsHttpModule),
typeof(AbpAIToolsMcpModule),
typeof(AbpAIManagementApplicationModule),
typeof(AbpAIManagementHttpApiModule),
typeof(AIServiceMigrationsEntityFrameworkCoreModule),
typeof(AbpDataDbMigratorModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpHttpClientModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpSmsPlatformModule),
typeof(AbpEmailingPlatformModule),
typeof(AbpCachingStackExchangeRedisModule),

3
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/LINGYUN.Abp.MicroService.AIService.csproj

@ -31,6 +31,7 @@
<PackageReference Include="Volo.Abp.FeatureManagement.Application" />
<PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" />
<PackageReference Include="Volo.Abp.Http.Client" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" />
<PackageReference Include="Volo.Abp.PermissionManagement.Application" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Identity" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" />
@ -58,6 +59,8 @@
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore\LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AI.Ollama\LINGYUN.Abp.AI.Ollama.csproj" />
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AI.Tools\LINGYUN.Abp.AI.Tools.csproj" />
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AI.Tools.Http\LINGYUN.Abp.AI.Tools.Http.csproj" />
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AI.Tools.Mcp\LINGYUN.Abp.AI.Tools.Mcp.csproj" />
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AIManagement.Application\LINGYUN.Abp.AIManagement.Application.csproj" />
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AIManagement.HttpApi\LINGYUN.Abp.AIManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj" />

8
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json

@ -7,6 +7,14 @@
"Auditing": {
"AllEntitiesSelector": true
},
"AITools": {
"Http": {
"ApplicationConfiguration": {
"IsEnabled": true,
"EndPoint": "http://localhost:30010/api/abp/application-configuration"
}
}
},
"DistributedCache": {
"HideErrors": true,
"KeyPrefix": "LINGYUN.Abp.Application",

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

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

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AI.Tools.Http</AssemblyName>
<PackageId>LINGYUN.Abp.AI.Tools.Http</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\AI\Tools\Http\Localization\Resources\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\AI\Tools\Http\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Http.Client" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.Contracts" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.AI.Tools\LINGYUN.Abp.AI.Tools.csproj" />
</ItemGroup>
</Project>

42
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/AbpAIToolsHttpModule.cs

@ -0,0 +1,42 @@
using LINGYUN.Abp.AI.Localization;
using LINGYUN.Abp.AI.Tools.Http.ApplicationConfigurations;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.AI.Tools.Http;
[DependsOn(
typeof(AbpAIToolsModule),
typeof(AbpHttpClientModule),
typeof(AbpAspNetCoreMvcContractsModule))]
public class AbpAIToolsHttpModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAIToolsApplicationConfigurationOptions>(context.Configuration.GetSection("AITools:Http:ApplicationConfiguration"));
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAIToolsHttpModule>();
});
Configure<AbpAIToolsOptions>(options =>
{
// Http工具
options.AIToolProviders.Add<HttpAIToolProvider>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpAIResource>()
.AddVirtualJson("/LINGYUN/Abp/AI/Tools/Http/Localization/Resources");
});
context.Services.AddHttpAIToolClient();
}
}

31
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/AbpAIToolsHttpOptiions.cs

@ -0,0 +1,31 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Tools.Http;
public class AbpAIToolsHttpOptiions
{
public List<Action<IHttpClientBuilder>> ClientBuildActions { get; }
public List<Action<IServiceProvider, HttpClient>> ClientActions { get; }
public List<Action<IServiceProvider, HttpClientHandler>> ClientHandlerActions { get; }
/// <summary>
/// 自定义Http请求响应处理
/// </summary>
/// <remarks>
/// 参数1: HttpAITool工具名称
/// 参数2: IServiceProvider
/// 参数3: 请求响应
/// </remarks>
public IDictionary<string, Func<IServiceProvider, HttpResponseMessage, Task<object>>> HttpResponseActions { get; }
public AbpAIToolsHttpOptiions()
{
ClientBuildActions = new List<Action<IHttpClientBuilder>>();
ClientActions = new List<Action<IServiceProvider, HttpClient>>();
ClientHandlerActions = new List<Action<IServiceProvider, HttpClientHandler>>();
HttpResponseActions = new Dictionary<string, Func<IServiceProvider, HttpResponseMessage, Task<object>>>();
}
}

11
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/ApplicationConfigurations/AbpAIToolsApplicationConfigurationOptions.cs

@ -0,0 +1,11 @@
namespace LINGYUN.Abp.AI.Tools.Http.ApplicationConfigurations;
public class AbpAIToolsApplicationConfigurationOptions
{
public bool IsEnabled { get; set; }
public string EndPoint { get; set; }
public AbpAIToolsApplicationConfigurationOptions()
{
IsEnabled = false;
EndPoint = "http://localhost:8080/api/abp/application-configuration";
}
}

36
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/GlobalHttpAIToolDefinitionProvider.cs

@ -0,0 +1,36 @@
using LINGYUN.Abp.AI.Localization;
using LINGYUN.Abp.AI.Tools.Http.ApplicationConfigurations;
using Microsoft.Extensions.Options;
using System.Net.Http;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.AI.Tools.Http;
public class GlobalHttpAIToolDefinitionProvider : AIToolDefinitionProvider
{
protected AbpAIToolsApplicationConfigurationOptions Options { get; }
public GlobalHttpAIToolDefinitionProvider(IOptions<AbpAIToolsApplicationConfigurationOptions> options)
{
Options = options.Value;
}
public override void Define(IAIToolDefinitionContext context)
{
if (Options.IsEnabled)
{
context.Add(
new AIToolDefinition(
"GetApplicationConfiguration",
HttpAIToolProvider.ProviderName,
L("Tools:GetApplicationConfiguration"))
.WithHttpEndpoint(Options.EndPoint)
.WithHttpMethod(HttpMethod.Get)
.WithHttpHeaders("_AbpDontWrapResult", "true")// 无需包装结果
.UseHttpCurrentAccessToken());
}
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<AbpAIResource>(name);
}
}

136
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAITool.cs

@ -0,0 +1,136 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Globalization;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
namespace LINGYUN.Abp.AI.Tools.Http;
public class HttpAITool
{
protected HttpAIToolInvokeContext Context { get; }
public HttpAITool(HttpAIToolInvokeContext context)
{
Context = context;
}
public async virtual Task<object?> InvokeAsync()
{
// Abp远程服务适配
//var remoteService = Context.ToolDefinition.GetRemoteServiceOrNull();
//var remoteMethod = Context.ToolDefinition.GetRemoteMethodOrNull();
//if (!remoteService.IsNullOrWhiteSpace() && !remoteMethod.IsNullOrWhiteSpace())
//{
// var abpHttpClientOptions = Context.ServiceProvider.GetRequiredService<IOptions<AbpHttpClientOptions>>().Value;
// HttpClientProxyConfig? clientProxyConfig = null;
// foreach (var httpClientProxyConfig in abpHttpClientOptions.HttpClientProxies.Values)
// {
// if (httpClientProxyConfig.RemoteServiceName.Equals(remoteService))
// {
// clientProxyConfig = httpClientProxyConfig;
// continue;
// }
// }
// if (clientProxyConfig != null)
// {
// // var serviceType = clientProxyConfig.Type.GetProperty(nameof(IHttpClientProxy<object>.Service));
// var serviceMethod = clientProxyConfig.Type.GetMethod(remoteMethod);
// if (serviceMethod != null)
// {
// var httpClientProxyType = typeof(IHttpClientProxy<>).MakeGenericType(clientProxyConfig.Type);
// var httpClientProxy = Context.ServiceProvider.GetRequiredService(httpClientProxyType);
// var service = httpClientProxyType.GetProperty(nameof(IHttpClientProxy<object>.Service))!.GetValue(httpClientProxy);
// // TODO: 暂不支持有参远程服务调用
// var task = (Task)serviceMethod.Invoke(service, null)!;
// await task;
// // TODO: 必须为Task<XXX>返回结构
// return typeof(Task<>).MakeGenericType(serviceMethod.ReturnType.GenericTypeArguments[0])
// .GetProperty(nameof(Task<object>.Result), BindingFlags.Public | BindingFlags.Instance)!
// .GetValue(task);
// }
// }
//}
var options = Context.ServiceProvider.GetRequiredService<IOptions<AbpAIToolsHttpOptiions>>().Value;
var httpClientFactory = Context.ServiceProvider.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateHttpAIToolClient();
var httpRequestMessage = new HttpRequestMessage(
Context.ToolDefinition.GetHttpMethod(),
Context.ToolDefinition.GetHttpEndpoint());
var headers = Context.ToolDefinition.GetHttpHeaders();
foreach (var header in headers)
{
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
if (Context.ToolDefinition.IsUseHttpCurrentAccessToken())
{
var accessTokenProvider = Context.ServiceProvider.GetRequiredService<IAbpAccessTokenProvider>();
var token = await accessTokenProvider.GetTokenAsync();
if (!token.IsNullOrWhiteSpace())
{
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
}
AddDefaultHeaders(httpRequestMessage);
var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
if (options.HttpResponseActions.TryGetValue(Context.ToolDefinition.Name, out var customHandler))
{
return await customHandler(Context.ServiceProvider, httpResponseMessage);
}
return await httpResponseMessage.Content.ReadAsStringAsync();
}
protected virtual void AddDefaultHeaders(HttpRequestMessage requestMessage)
{
//CorrelationId
var correlationIdProvider = Context.ServiceProvider.GetRequiredService<ICorrelationIdProvider>();
var correlationId = correlationIdProvider.Get();
if (correlationId != null)
{
var correlationIdOptions = Context.ServiceProvider.GetRequiredService<IOptions<AbpCorrelationIdOptions>>();
requestMessage.Headers.Add(correlationIdOptions.Value.HttpHeaderName, correlationId);
}
//TenantId
var currentTenant = Context.ServiceProvider.GetRequiredService<ICurrentTenant>();
if (currentTenant.Id.HasValue)
{
//TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, currentTenant.Id.Value.ToString());
}
//Culture
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
if (!currentCulture.IsNullOrEmpty())
{
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture));
}
//X-Requested-With
requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest");
//Timezone
var currentTimezoneProvider = Context.ServiceProvider.GetRequiredService<ICurrentTimezoneProvider>();
if (!currentTimezoneProvider.TimeZone.IsNullOrWhiteSpace())
{
requestMessage.Headers.Add(TimeZoneConsts.DefaultTimeZoneKey, currentTimezoneProvider.TimeZone);
}
}
}

150
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolDefinitionExtenssions.cs

@ -0,0 +1,150 @@
using System.Collections.Generic;
using System.Net.Http;
using Volo.Abp;
namespace LINGYUN.Abp.AI.Tools.Http;
public static class HttpAIToolDefinitionExtenssions
{
private const string RemoteService = "RemoteService";
private const string RemoteController = "RemoteController";
private const string RemoteMethod = "RemoteMethod";
private const string Endpoint = "HttpEndpoint";
private const string Method = "HttpMethod";
private const string Headers = "HttpHeaders";
private const string CurrentAccessToken = "UseHttpCurrentAccessToken";
public static AIToolDefinition UseHttpCurrentAccessToken(this AIToolDefinition definition, bool useCurrentAccessToken = true)
{
definition.WithProperty(CurrentAccessToken, useCurrentAccessToken);
return definition;
}
public static AIToolDefinition WithRemoteService(this AIToolDefinition definition, string service, string controllerName, string uniqueMethodName)
{
Check.NotNullOrWhiteSpace(service, nameof(service));
Check.NotNullOrWhiteSpace(controllerName, nameof(controllerName));
Check.NotNullOrWhiteSpace(uniqueMethodName, nameof(uniqueMethodName));
definition.WithProperty(RemoteService, service);
definition.WithProperty(RemoteController, controllerName);
definition.WithProperty(RemoteMethod, uniqueMethodName);
return definition;
}
public static AIToolDefinition WithHttpEndpoint(this AIToolDefinition definition, string endPoint)
{
Check.NotNullOrWhiteSpace(endPoint, nameof(endPoint));
definition.WithProperty(Endpoint, endPoint);
return definition;
}
public static AIToolDefinition WithHttpMethod(this AIToolDefinition definition, HttpMethod method)
{
Check.NotNull(method, nameof(method));
definition.WithProperty(Method, method.Method);
return definition;
}
public static AIToolDefinition WithHttpHeaders(this AIToolDefinition definition, IDictionary<string, string> headers)
{
Check.NotNullOrEmpty(headers, nameof(headers));
var currentHeaders = definition.GetHttpHeaders();
currentHeaders.AddIfNotContains(headers);
definition.WithProperty(Headers, currentHeaders);
return definition;
}
public static AIToolDefinition WithHttpHeaders(this AIToolDefinition definition, string key, string value)
{
Check.NotNullOrEmpty(key, nameof(key));
Check.NotNullOrEmpty(value, nameof(value));
var currentHeaders = definition.GetHttpHeaders();
currentHeaders.TryAdd(key, value);
definition.WithProperty(Headers, currentHeaders);
return definition;
}
public static bool IsUseHttpCurrentAccessToken(this AIToolDefinition definition)
{
if (definition.Properties.TryGetValue(CurrentAccessToken, out var useCurrentAccessTokenObj) && useCurrentAccessTokenObj != null
&& bool.TryParse(useCurrentAccessTokenObj.ToString(), out var useCurrentAccessToken))
{
return useCurrentAccessToken;
}
return false;
}
public static string? GetRemoteServiceOrNull(this AIToolDefinition definition)
{
definition.Properties.TryGetValue(RemoteService, out var remoteServiceObj);
return remoteServiceObj?.ToString();
}
public static string? GetRemoteControllerOrNull(this AIToolDefinition definition)
{
definition.Properties.TryGetValue(RemoteController, out var remoteControllerObj);
return remoteControllerObj?.ToString();
}
public static string? GetRemoteMethodOrNull(this AIToolDefinition definition)
{
definition.Properties.TryGetValue(RemoteMethod, out var remoteMethodObj);
return remoteMethodObj?.ToString();
}
public static string GetHttpEndpoint(this AIToolDefinition definition)
{
definition.Properties.TryGetValue(Endpoint, out var endpointObj);
Check.NotNull(endpointObj, nameof(Endpoint));
return endpointObj.ToString()!;
}
public static HttpMethod GetHttpMethod(this AIToolDefinition definition)
{
if (definition.Properties.TryGetValue(Method, out var methodObj) && methodObj != null)
{
try
{
return HttpMethod.Parse(methodObj.ToString());
}
catch { }
}
return HttpMethod.Get;
}
public static IDictionary<string, string> GetHttpHeaders(this AIToolDefinition definition)
{
if (definition.Properties.TryGetValue(Headers, out var headersObj) && headersObj != null)
{
if (headersObj is IDictionary<string, string> h)
{
return h;
}
}
return new Dictionary<string, string>();
}
}

15
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolInvokeContext.cs

@ -0,0 +1,15 @@
using System;
namespace LINGYUN.Abp.AI.Tools.Http;
public class HttpAIToolInvokeContext
{
public IServiceProvider ServiceProvider { get; }
public AIToolDefinition ToolDefinition { get; }
public HttpAIToolInvokeContext(
IServiceProvider serviceProvider,
AIToolDefinition toolDefinition)
{
ServiceProvider = serviceProvider;
ToolDefinition = toolDefinition;
}
}

47
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolProvider.cs

@ -0,0 +1,47 @@
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Tools.Http;
public class HttpAIToolProvider : IAIToolProvider, ITransientDependency
{
public const string ProviderName = "Http";
public string Name => ProviderName;
protected IServiceProvider ServiceProvider { get; }
public HttpAIToolProvider(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public virtual Task<AITool[]> CreateToolsAsync(AIToolDefinition definition)
{
string? description = null;
if (definition.Description != null)
{
var localizerFactory = ServiceProvider.GetRequiredService<IStringLocalizerFactory>();
description = definition.Description.Localize(localizerFactory)?.Value;
}
var httpAITool = AIFunctionFactory.Create(
method: typeof(HttpAITool).GetMethod(nameof(HttpAITool.InvokeAsync))!,
createInstanceFunc: (AIFunctionArguments args) =>
{
var context = new HttpAIToolInvokeContext(
args.Services ?? ServiceProvider,
definition);
return new HttpAITool(context);
},
options: new AIFunctionFactoryOptions
{
Name = definition.Name,
Description = description,
AdditionalProperties = definition.Properties,
});
return Task.FromResult<AITool[]>([httpAITool]);
}
}

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

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"Tools:GetApplicationConfiguration": "Get Application Configuration"
}
}

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

@ -0,0 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"Tools:GetApplicationConfiguration": "获取应用程序配置"
}
}

48
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/Microsoft/Extensions/DependencyInjection/HttpClientHttpAIToolExtenssions.cs

@ -0,0 +1,48 @@
using LINGYUN.Abp.AI.Tools.Http;
using System.Net.Http;
using System.Runtime.InteropServices;
namespace Microsoft.Extensions.DependencyInjection;
internal static class HttpClientHttpAIToolExtenssions
{
private const string HttpAIToolClient = "__AbpAIHttpToolClient";
public static IServiceCollection AddHttpAIToolClient(this IServiceCollection services)
{
var preOptions = services.ExecutePreConfiguredActions<AbpAIToolsHttpOptiions>();
var clientBuilder = services.AddHttpClient(HttpAIToolClient, (provider, client) =>
{
foreach (var clientBuildAction in preOptions.ClientActions)
{
clientBuildAction(provider, client);
}
}).ConfigurePrimaryHttpMessageHandler(provider =>
{
var handler = new HttpClientHandler();
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")))
{
handler.UseCookies = false;
}
foreach (var handlerAction in preOptions.ClientHandlerActions)
{
handlerAction(provider, handler);
}
return handler;
});
foreach (var clientBuildAction in preOptions.ClientBuildActions)
{
clientBuildAction(clientBuilder);
}
return services;
}
public static HttpClient CreateHttpAIToolClient(this IHttpClientFactory httpClientFactory)
{
return httpClientFactory.CreateClient(HttpAIToolClient);
}
}

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

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AI.Tools.Mcp</AssemblyName>
<PackageId>LINGYUN.Abp.AI.Tools.Mcp</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Http.Client" />
<PackageReference Include="ModelContextProtocol" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.AI.Tools\LINGYUN.Abp.AI.Tools.csproj" />
</ItemGroup>
</Project>

22
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN/Abp/AI/Tools/Mcp/AbpAIToolsMcpModule.cs

@ -0,0 +1,22 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AI.Tools.Mcp;
[DependsOn(
typeof(AbpAIToolsModule),
typeof(AbpHttpClientModule))]
public class AbpAIToolsMcpModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMcpAIToolClient();
Configure<AbpAIToolsOptions>(options =>
{
// Mcp工具
options.AIToolProviders.Add<McpAIToolProvider>();
});
}
}

150
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN/Abp/AI/Tools/Mcp/McpAIToolDefinitionExtenssions.cs

@ -0,0 +1,150 @@
using ModelContextProtocol.Client;
using System;
using System.Collections.Generic;
using Volo.Abp;
namespace LINGYUN.Abp.AI.Tools.Mcp;
public static class McpAIToolDefinitionExtenssions
{
private const string Endpoint = "McpEndpoint";
private const string Headers = "McpHeaders";
private const string TransportMode = "McpTransportMode";
private const string ConnectionTimeout = "McpConnectionTimeout";
private const string MaxReconnectionAttempts = "McpMaxReconnectionAttempts";
private const string CurrentAccessToken = "UseMcpCurrentAccessToken";
public static AIToolDefinition UseMcpCurrentAccessToken(this AIToolDefinition definition, bool useCurrentAccessToken = true)
{
definition.WithProperty(CurrentAccessToken, useCurrentAccessToken);
return definition;
}
public static AIToolDefinition WithMcpEndpoint(this AIToolDefinition definition, string endPoint)
{
Check.NotNullOrWhiteSpace(endPoint, nameof(endPoint));
definition.WithProperty(Endpoint, endPoint);
return definition;
}
public static AIToolDefinition WithMcpTransportMode(this AIToolDefinition definition, HttpTransportMode transportMode = HttpTransportMode.AutoDetect)
{
definition.WithProperty(TransportMode, ((int)transportMode).ToString());
return definition;
}
public static AIToolDefinition WithMcpConnectionTimeout(this AIToolDefinition definition, TimeSpan connectionTimeout)
{
definition.WithProperty(ConnectionTimeout, connectionTimeout.ToString());
return definition;
}
public static AIToolDefinition WithMcpMaxReconnectionAttempts(this AIToolDefinition definition, int maxReconnectionAttempts = 5)
{
definition.WithProperty(MaxReconnectionAttempts, maxReconnectionAttempts);
return definition;
}
public static AIToolDefinition WithMcpHeaders(this AIToolDefinition definition, IDictionary<string, string> headers)
{
Check.NotNullOrEmpty(headers, nameof(headers));
var currentHeaders = definition.GetMcpHeaders();
currentHeaders.AddIfNotContains(headers);
definition.WithProperty(Headers, currentHeaders);
return definition;
}
public static AIToolDefinition WithMcpHeaders(this AIToolDefinition definition, string key, string value)
{
Check.NotNullOrEmpty(key, nameof(key));
Check.NotNullOrEmpty(value, nameof(value));
var currentHeaders = definition.GetMcpHeaders();
currentHeaders.TryAdd(key, value);
definition.WithProperty(Headers, currentHeaders);
return definition;
}
public static bool IsUseMcpCurrentAccessToken(this AIToolDefinition definition)
{
if (definition.Properties.TryGetValue(CurrentAccessToken, out var useCurrentAccessTokenObj) && useCurrentAccessTokenObj != null
&& bool.TryParse(useCurrentAccessTokenObj.ToString(), out var useCurrentAccessToken))
{
return useCurrentAccessToken;
}
return false;
}
public static string GetMcpEndpoint(this AIToolDefinition definition)
{
definition.Properties.TryGetValue(Endpoint, out var endpointObj);
Check.NotNull(endpointObj, nameof(Endpoint));
return endpointObj.ToString()!;
}
public static TimeSpan GetMcpConnectionTimeout(this AIToolDefinition definition, double defaultConnectionTimeoutSeconds = 30)
{
definition.Properties.TryGetValue(ConnectionTimeout, out var connectionTimeoutObj);
if (connectionTimeoutObj != null &&
TimeSpan.TryParse(connectionTimeoutObj.ToString(), out var connectionTimeout))
{
return connectionTimeout;
}
return TimeSpan.FromSeconds(defaultConnectionTimeoutSeconds);
}
public static HttpTransportMode GetMcpTransportMode(this AIToolDefinition definition, HttpTransportMode defaultTransportMode = HttpTransportMode.AutoDetect)
{
definition.Properties.TryGetValue(TransportMode, out var defaultTransportModeObj);
if (defaultTransportModeObj != null &&
Enum.TryParse<HttpTransportMode>(defaultTransportModeObj.ToString(), out var transportMode))
{
return transportMode;
}
return defaultTransportMode;
}
public static int GetMcpMaxReconnectionAttempts(this AIToolDefinition definition, int defaultMaxReconnectionAttempts = 5)
{
definition.Properties.TryGetValue(MaxReconnectionAttempts, out var maxReconnectionAttemptsObj);
if (maxReconnectionAttemptsObj != null &&
int.TryParse(maxReconnectionAttemptsObj.ToString(), out var maxReconnectionAttempts))
{
return maxReconnectionAttempts;
}
return defaultMaxReconnectionAttempts;
}
public static IDictionary<string, string> GetMcpHeaders(this AIToolDefinition definition)
{
if (definition.Properties.TryGetValue(Headers, out var headersObj) && headersObj != null)
{
if (headersObj is IDictionary<string, string> h)
{
return h;
}
}
return new Dictionary<string, string>();
}
}

63
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/LINGYUN/Abp/AI/Tools/Mcp/McpAIToolProvider.cs

@ -0,0 +1,63 @@
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;
namespace LINGYUN.Abp.AI.Tools.Mcp;
public class McpAIToolProvider : IAIToolProvider, ITransientDependency
{
public const string ProviderName = "Mcp";
public string Name => ProviderName;
protected IServiceProvider ServiceProvider { get; }
protected IHttpClientFactory HttpClientFactory { get; }
public McpAIToolProvider(
IServiceProvider serviceProvider,
IHttpClientFactory httpClientFactory)
{
ServiceProvider = serviceProvider;
HttpClientFactory = httpClientFactory;
}
public async virtual Task<AITool[]> CreateToolsAsync(AIToolDefinition definition)
{
var httpClient = HttpClientFactory.CreateMcpAIToolClient();
var httpClientTransportOptions = new HttpClientTransportOptions
{
Endpoint = new Uri(definition.GetMcpEndpoint()),
AdditionalHeaders = new Dictionary<string, string>(),
TransportMode = definition.GetMcpTransportMode(),
ConnectionTimeout = definition.GetMcpConnectionTimeout(),
MaxReconnectionAttempts = definition.GetMcpMaxReconnectionAttempts(),
};
var headers = definition.GetMcpHeaders();
foreach (var header in headers)
{
httpClientTransportOptions.AdditionalHeaders.TryAdd(header.Key, header.Value);
}
if (definition.IsUseMcpCurrentAccessToken())
{
var accessTokenProvider = ServiceProvider.GetRequiredService<IAbpAccessTokenProvider>();
var token = await accessTokenProvider.GetTokenAsync();
if (!token.IsNullOrWhiteSpace())
{
// TODO: 使用OAuth配置?
httpClientTransportOptions.AdditionalHeaders.TryAdd("Authorization", $"Bearer {token}");
}
}
var mcpClient = await McpClient.CreateAsync(
new HttpClientTransport(httpClientTransportOptions, httpClient));
return (await mcpClient.ListToolsAsync()).ToArray();
}
}

18
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Mcp/Microsoft/Extensions/DependencyInjection/HttpClientMcpAIToolExtenssions.cs

@ -0,0 +1,18 @@
using System.Net.Http;
namespace Microsoft.Extensions.DependencyInjection;
internal static class HttpClientMcpAIToolExtenssions
{
private const string McpAIToolClient = "__AbpAIMcpToolClient";
public static IServiceCollection AddMcpAIToolClient(this IServiceCollection services)
{
services.AddHttpClient(McpAIToolClient);
return services;
}
public static HttpClient CreateMcpAIToolClient(this IHttpClientFactory httpClientFactory)
{
return httpClientFactory.CreateClient(McpAIToolClient);
}
}

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

@ -6,7 +6,7 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.SimpleStateChecking;
namespace LINGYUN.Abp.AI.Tools;
public class AIToolFactory : IAIToolFactory, ITransientDependency
public class AIToolFactory : IAIToolFactory, IScopedDependency
{
protected ISimpleStateCheckerManager<AIToolDefinition> StateCheckerManager { get; }
protected IAIToolDefinitionManager AIToolDefinitionManager { get; }
@ -22,7 +22,7 @@ public class AIToolFactory : IAIToolFactory, ITransientDependency
AIToolProviderManager = aIToolProviderManager;
}
public virtual AITool CreateTool(AIToolDefinition definition)
public virtual Task<AITool[]> CreateTool(AIToolDefinition definition)
{
foreach (var provider in AIToolProviderManager.Providers)
{
@ -31,7 +31,7 @@ public class AIToolFactory : IAIToolFactory, ITransientDependency
continue;
}
return provider.CreateTool(definition);
return provider.CreateToolsAsync(definition);
}
throw new AbpException($"The AITool provider implementation named {definition.Provider} was not found!");
@ -46,7 +46,7 @@ public class AIToolFactory : IAIToolFactory, ITransientDependency
{
if (await StateCheckerManager.IsEnabledAsync(toolDefine))
{
aiTools.Add(CreateTool(toolDefine));
aiTools.AddRange(await CreateTool(toolDefine));
}
}

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

@ -15,7 +15,7 @@ public static class FunctionAIToolDefinitionExtenssions
{
Check.NotNull(funcType, nameof(funcType));
definition.WithProperty(FunctionType, funcType);
definition.WithProperty(FunctionType, funcType.AssemblyQualifiedName);
return definition;
}

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

@ -2,6 +2,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
@ -17,7 +18,7 @@ public class FunctionAIToolProvider : IAIToolProvider, ITransientDependency
ServiceProvider = serviceProvider;
}
public virtual AITool CreateTool(AIToolDefinition definition)
public virtual Task<AITool[]> CreateToolsAsync(AIToolDefinition definition)
{
var aiToolType = definition.GetFunction();
// 框架约定, 自定义Tool只需要定义同步方法(Invoke)或异步方法(InvokeAsync)即可
@ -32,7 +33,7 @@ public class FunctionAIToolProvider : IAIToolProvider, ITransientDependency
description = definition.Description.Localize(localizerFactory)?.Value;
}
return AIFunctionFactory.Create(
var functionAITool = AIFunctionFactory.Create(
method: aiToolMethodInfo,
createInstanceFunc: (AIFunctionArguments args) =>
{
@ -44,5 +45,7 @@ public class FunctionAIToolProvider : IAIToolProvider, ITransientDependency
Description = description,
AdditionalProperties = definition.Properties,
});
return Task.FromResult<AITool[]>([functionAITool]);
}
}

2
aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/GlobalAIToolDefinitionProvider.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/GlobalFunctionAIToolDefinitionProvider.cs

@ -5,7 +5,7 @@ using LINGYUN.Abp.AI.Tools.Users;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.AI.Tools;
public class GlobalAIToolDefinitionProvider : AIToolDefinitionProvider
public class GlobalFunctionAIToolDefinitionProvider : AIToolDefinitionProvider
{
public override void Define(IAIToolDefinitionContext context)
{

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

@ -4,7 +4,7 @@ using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Tools;
public interface IAIToolFactory
{
AITool CreateTool(AIToolDefinition definition);
Task<AITool[]> CreateTool(AIToolDefinition definition);
Task<AITool[]> CreateAllTools();
}

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

@ -1,9 +1,10 @@
using Microsoft.Extensions.AI;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Tools;
public interface IAIToolProvider
{
string Name { get; }
AITool CreateTool(AIToolDefinition definition);
Task<AITool[]> CreateToolsAsync(AIToolDefinition definition);
}

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

@ -59,7 +59,7 @@ public class NowTimeAIToolDefinitionProvider : AIToolDefinitionProvider
```csharp
public class McpAIToolProvider : IAIToolProvider, ITransientDependency
{
public virtual AITool CreateTool(AIToolDefinition definition)
public virtual Task<AITool[]> CreateToolsAsync(AIToolDefinition definition)
{
// 你的具体实现
}

Loading…
Cancel
Save