Browse Source

feat(ai): Add the HttpAITool module

pull/1456/head
colin 2 days ago
parent
commit
45e52110ce
  1. 2
      aspnet-core/LINGYUN.MicroService.Aspire.slnx
  2. 5
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs
  3. 2
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/LINGYUN.Abp.MicroService.AIService.csproj
  4. 8
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json
  5. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/FodyWeavers.xml
  6. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/FodyWeavers.xsd
  7. 31
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN.Abp.AI.Tools.Http.csproj
  8. 42
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/AbpAIToolsHttpModule.cs
  9. 31
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/AbpAIToolsHttpOptiions.cs
  10. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/ApplicationConfigurations/AbpAIToolsApplicationConfigurationOptions.cs
  11. 36
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/GlobalHttpAIToolDefinitionProvider.cs
  12. 136
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAITool.cs
  13. 150
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolDefinitionExtenssions.cs
  14. 15
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolInvokeContext.cs
  15. 47
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/HttpAIToolProvider.cs
  16. 6
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/Localization/Resources/en.json
  17. 6
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/LINGYUN/Abp/AI/Tools/Http/Localization/Resources/zh-Hans.json
  18. 48
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools.Http/Microsoft/Extensions/DependencyInjection/HttpClientHttpAIToolExtenssions.cs

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

@ -285,6 +285,8 @@
<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/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" />

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

@ -1,5 +1,6 @@
using LINGYUN.Abp.AI.Ollama;
using LINGYUN.Abp.AI.Tools;
using LINGYUN.Abp.AI.Tools.Http;
using LINGYUN.Abp.AIManagement;
using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.AspNetCore.Mvc.Localization;
@ -23,6 +24,7 @@ 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,14 @@ namespace LINGYUN.Abp.MicroService.AIService;
typeof(AbpAIOllamaModule),
typeof(AbpAIToolsModule),
typeof(AbpAIToolsHttpModule),
typeof(AbpAIManagementApplicationModule),
typeof(AbpAIManagementHttpApiModule),
typeof(AIServiceMigrationsEntityFrameworkCoreModule),
typeof(AbpDataDbMigratorModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpHttpClientModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpSmsPlatformModule),
typeof(AbpEmailingPlatformModule),
typeof(AbpCachingStackExchangeRedisModule),

2
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,7 @@
<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.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.GetHttpAIToolClient();
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 GetHttpAIToolClient(this IHttpClientFactory httpClientFactory)
{
return httpClientFactory.CreateClient(HttpAIToolClient);
}
}
Loading…
Cancel
Save