From 4896a7c4a9575a9f9402f143742860fe0649a304 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 27 Mar 2026 14:57:43 +0800 Subject: [PATCH] feat(ai): Add Use AI tool to the workspace --- .../Abp/AI/Workspaces/WorkspaceDefinition.cs | 10 ++++++++ .../LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs | 24 ++++++++++++++++--- ...kspaceDefinitionRecordCreateOrUpdateDto.cs | 2 ++ .../Dtos/WorkspaceDefinitionRecordDto.cs | 2 ++ .../AbpAIManagementApplicationMappers.cs | 9 +++++++ .../WorkspaceDefinitionAppService.cs | 7 ++++++ .../WorkspaceDefinitionRecordConsts.cs | 1 + ...icWorkspaceDefinitionStoreInMemoryCache.cs | 4 ++++ .../Workspaces/WorkspaceDefinitionRecord.cs | 14 +++++++++++ .../WorkspaceDefinitionSerializer.cs | 1 + ...nagementDbContextModelBuilderExtensions.cs | 2 ++ 11 files changed, 73 insertions(+), 3 deletions(-) diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs index 2f3288616..9b6d9c431 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs @@ -126,6 +126,9 @@ public class WorkspaceDefinition : IHasSimpleStateCheckers [NotNull] public Dictionary Properties { get; } + [NotNull] + public List Tools { get; } + public List> StateCheckers { get; } public WorkspaceDefinition( @@ -155,6 +158,7 @@ public class WorkspaceDefinition : IHasSimpleStateCheckers PresencePenalty = presencePenalty; IsEnabled = true; + Tools = new List(); Properties = new Dictionary(); StateCheckers = new List>(); } @@ -171,6 +175,12 @@ public class WorkspaceDefinition : IHasSimpleStateCheckers return this; } + public virtual WorkspaceDefinition WithTools(params string[] tools) + { + Tools.AddIfNotContains(tools); + return this; + } + public virtual WorkspaceDefinition WithProperty(string key, object value) { Properties[key] = value; diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs index 30029e5f5..353c9df60 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AI.Tools/LINGYUN/Abp/AI/Tools/AbpAIToolsModule.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; +using System.Linq; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; @@ -32,10 +33,27 @@ public class AbpAIToolsModule : AbpModule Configure(options => { - options.ChatClientBuildActions.Add(async (_, sp, builder) => + options.ChatClientBuildActions.Add(async (workspace, sp, builder) => { + var useAITools = new List(); var aiToolFactory = sp.GetRequiredService(); - var aiTools = await aiToolFactory.CreateAllTools(); + + if (workspace.Tools.Count > 0) + { + var aiToolDefinitionManager = sp.GetRequiredService(); + var aiToolDefinitions = await aiToolDefinitionManager.GetAllAsync(); + var useAIToolDefinitions = aiToolDefinitions.Where(aiTool => workspace.Tools.Contains(aiTool.Name)); + + foreach (var aiToolDefinition in aiToolDefinitions) + { + var aiTools = await aiToolFactory.CreateTool(aiToolDefinition); + useAITools.AddRange(aiTools); + } + } + else + { + useAITools.AddRange(await aiToolFactory.CreateAllTools()); + } builder.ConfigureOptions(ai => { @@ -44,7 +62,7 @@ public class AbpAIToolsModule : AbpModule ai.Tools ??= []; - foreach (var aiTool in aiTools) + foreach (var aiTool in useAITools) { ai.Tools.Add(aiTool); } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs index dcb866294..361ac7d50 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs @@ -42,6 +42,8 @@ public abstract class WorkspaceDefinitionRecordCreateOrUpdateDto : ExtensibleObj public bool IsEnabled { get; set; } + public string[]? Tools { get; set; } + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxStateCheckersLength))] public string? StateCheckers { get; set; } } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs index 07cc111c7..455ce4e2a 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs @@ -35,6 +35,8 @@ public class WorkspaceDefinitionRecordDto : ExtensibleAuditedEntityDto, IH public bool IsSystem { get; set; } + public string[]? Tools { get; set; } + public string? StateCheckers { get; set; } public string ConcurrencyStamp { get; set; } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs index 713877e48..bad789db5 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs @@ -14,8 +14,17 @@ namespace LINGYUN.Abp.AIManagement; [MapExtraProperties(DefinitionChecks = MappingPropertyDefinitionChecks.None)] public partial class WorkspaceDefinitionRecordToWorkspaceDefinitionRecordDtoMapper : MapperBase { + [MapPropertyFromSource(nameof(WorkspaceDefinitionRecordDto.Tools), Use = nameof(ConvertTools))] public override partial WorkspaceDefinitionRecordDto Map(WorkspaceDefinitionRecord source); + + [MapPropertyFromSource(nameof(WorkspaceDefinitionRecordDto.Tools), Use = nameof(ConvertTools))] public override partial void Map(WorkspaceDefinitionRecord source, WorkspaceDefinitionRecordDto destination); + + [UserMapping(Default = false)] + private static string[]? ConvertTools(WorkspaceDefinitionRecord record) + { + return record.Tools?.Split(","); + } } [Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs index 0f348fe50..d1b046c72 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs @@ -5,6 +5,7 @@ using LINGYUN.Abp.AIManagement.Workspaces.Dtos; 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; @@ -113,6 +114,7 @@ public class WorkspaceDefinitionAppService : createInput.MaxOutputTokens, createInput.FrequencyPenalty, createInput.PresencePenalty, + createInput.Tools?.JoinAsString(","), createInput.StateCheckers) { IsEnabled = createInput.IsEnabled, @@ -184,6 +186,11 @@ public class WorkspaceDefinitionAppService : entity.StateCheckers = updateInput.StateCheckers; } + if (updateInput.Tools != null) + { + entity.Tools = updateInput.Tools.JoinAsString(","); + } + if (!updateInput.ApiKey.IsNullOrWhiteSpace()) { var encryptApiKey = StringEncryptionService.Encrypt(updateInput.ApiKey); diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecordConsts.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecordConsts.cs index f8a2e6bd1..e1e5bac0f 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecordConsts.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecordConsts.cs @@ -10,5 +10,6 @@ public static class WorkspaceDefinitionRecordConsts public static int MaxApiBaseUrlLength { get; set; } = 128; public static int MaxSystemPromptLength { get; set; } = 512; public static int MaxInstructionsLength { get; set; } = 512; + public static int MaxToolsLength { get; set; } = 128; public static int MaxStateCheckersLength { get; set; } = 256; } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/DynamicWorkspaceDefinitionStoreInMemoryCache.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/DynamicWorkspaceDefinitionStoreInMemoryCache.cs index 3d7d0d142..7baf9dfd5 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/DynamicWorkspaceDefinitionStoreInMemoryCache.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/DynamicWorkspaceDefinitionStoreInMemoryCache.cs @@ -62,6 +62,10 @@ public class DynamicWorkspaceDefinitionStoreInMemoryCache : IDynamicWorkspaceDef { workspaceDef.WithApiBaseUrl(workspace.ApiBaseUrl); } + if (!workspace.Tools.IsNullOrWhiteSpace()) + { + workspaceDef.WithTools(workspace.Tools.Split(",")); + } workspaceDef.IsEnabled = workspace.IsEnabled; if (!workspace.StateCheckers.IsNullOrWhiteSpace()) diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecord.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecord.cs index 487256815..489adf94c 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecord.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionRecord.cs @@ -36,6 +36,8 @@ public class WorkspaceDefinitionRecord : AuditedAggregateRoot public bool IsSystem { get; set; } + public string? Tools { get; set; } + public string? StateCheckers { get; set; } protected WorkspaceDefinitionRecord() @@ -57,6 +59,7 @@ public class WorkspaceDefinitionRecord : AuditedAggregateRoot int? maxOutputTokens = null, float? frequencyPenalty = null, float? presencePenalty = null, + string? tools = null, string? stateCheckers = null) : base(id) { @@ -67,6 +70,7 @@ public class WorkspaceDefinitionRecord : AuditedAggregateRoot Description = Check.Length(description, nameof(description), WorkspaceDefinitionRecordConsts.MaxDescriptionLength); SystemPrompt = Check.Length(systemPrompt, nameof(systemPrompt), WorkspaceDefinitionRecordConsts.MaxSystemPromptLength); Instructions = Check.Length(instructions, nameof(instructions), WorkspaceDefinitionRecordConsts.MaxInstructionsLength); + Tools = Check.Length(tools, nameof(tools), WorkspaceDefinitionRecordConsts.MaxToolsLength); StateCheckers = Check.Length(stateCheckers, nameof(stateCheckers), WorkspaceDefinitionRecordConsts.MaxStateCheckersLength); Temperature = temperature; MaxOutputTokens = maxOutputTokens; @@ -147,6 +151,11 @@ public class WorkspaceDefinitionRecord : AuditedAggregateRoot return false; } + if (IsSystem != otherWorkspace.IsSystem) + { + return false; + } + if (Temperature != otherWorkspace.Temperature) { return false; @@ -232,6 +241,11 @@ public class WorkspaceDefinitionRecord : AuditedAggregateRoot IsEnabled = otherWorkspace.IsEnabled; } + if (IsSystem != otherWorkspace.IsSystem) + { + IsSystem = otherWorkspace.IsSystem; + } + if (Temperature != otherWorkspace.Temperature) { Temperature = otherWorkspace.Temperature; diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionSerializer.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionSerializer.cs index ec8ad7403..6202f058b 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionSerializer.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionSerializer.cs @@ -58,6 +58,7 @@ public class WorkspaceDefinitionSerializer : IWorkspaceDefinitionSerializer, ITr definition.MaxOutputTokens, definition.FrequencyPenalty, definition.PresencePenalty, + definition.Tools.JoinAsString(","), SerializeStateCheckers(definition.StateCheckers)); if (!definition.ApiKey.IsNullOrWhiteSpace()) diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/LINGYUN/Abp/AIManagement/EntityFrameworkCore/AIManagementDbContextModelBuilderExtensions.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/LINGYUN/Abp/AIManagement/EntityFrameworkCore/AIManagementDbContextModelBuilderExtensions.cs index ab0080782..ffe9e7f00 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/LINGYUN/Abp/AIManagement/EntityFrameworkCore/AIManagementDbContextModelBuilderExtensions.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/LINGYUN/Abp/AIManagement/EntityFrameworkCore/AIManagementDbContextModelBuilderExtensions.cs @@ -91,6 +91,8 @@ public static class AIManagementDbContextModelBuilderExtensions .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxInstructionsLength); b.Property(x => x.StateCheckers) .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxStateCheckersLength); + b.Property(x => x.Tools) + .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxToolsLength); b.HasIndex(x => new { x.Name }).IsUnique();