From e102e6c8f930d7739563a7fa1da246e972c687a7 Mon Sep 17 00:00:00 2001 From: colin Date: Wed, 28 Jan 2026 11:46:55 +0800 Subject: [PATCH] feat: Add Workspace management interface implementation --- ....AIManagement.Application.Contracts.csproj | 5 +- .../AIManagementRemoteServiceConsts.cs | 7 + ...pAIManagementApplicationContractsModule.cs | 14 ++ .../AbpAIManagementDomainSharedModule.cs | 8 - .../WorkspaceDefinitionRecordCreateDto.cs | 10 ++ ...kspaceDefinitionRecordCreateOrUpdateDto.cs | 47 ++++++ .../Dtos/WorkspaceDefinitionRecordDto.cs | 39 +++++ .../WorkspaceDefinitionRecordGetListInput.cs | 14 ++ .../WorkspaceDefinitionRecordUpdateDto.cs | 10 ++ .../IWorkspaceDefinitionAppService.cs | 14 ++ .../FodyWeavers.xsd | 30 ++++ .../AIManagementApplicationServiceBase.cs | 12 ++ .../AbpAIManagementApplicationMappers.cs | 15 ++ .../AbpAIManagementApplicationModule.cs | 17 ++ .../AbpAIManagementDomainSharedModule.cs | 8 - .../WorkspaceDefinitionAppService.cs | 152 ++++++++++++++++++ .../AIManagement/AIManagementErrorCodes.cs | 12 ++ .../WorkspaceAlreadyExistsException.cs | 16 ++ .../AbpAIManagementDbProperties.cs | 2 +- .../FodyWeavers.xsd | 30 ++++ ...nagementDbContextModelBuilderExtensions.cs | 2 +- .../AbpAIManagementDomainSharedModule.cs | 8 - .../WorkspaceDefinitionController.cs | 52 ++++++ 23 files changed, 496 insertions(+), 28 deletions(-) create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AIManagementRemoteServiceConsts.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationContractsModule.cs delete mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateDto.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordGetListInput.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordUpdateDto.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/IWorkspaceDefinitionAppService.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xsd create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AIManagementApplicationServiceBase.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationModule.cs delete mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/AIManagementErrorCodes.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceAlreadyExistsException.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/FodyWeavers.xsd delete mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs create mode 100644 aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionController.cs diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj index c756d035b..1d2169985 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj @@ -5,8 +5,8 @@ netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0 - LINGYUN.Abp.AIManagement.Domain - LINGYUN.Abp.AIManagement.Domain + LINGYUN.Abp.AIManagement.Application.Contracts + LINGYUN.Abp.AIManagement.Application.Contracts false false false @@ -16,6 +16,7 @@ + diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AIManagementRemoteServiceConsts.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AIManagementRemoteServiceConsts.cs new file mode 100644 index 000000000..b68f59f17 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AIManagementRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.AIManagement; +public static class AIManagementRemoteServiceConsts +{ + public const string RemoteServiceName = "AbpAIManagement"; + + public const string ModuleName = "ai-management"; +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationContractsModule.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationContractsModule.cs new file mode 100644 index 000000000..289fb8ed2 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationContractsModule.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Application; +using Volo.Abp.Authorization; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.AIManagement; + +[DependsOn( + typeof(AbpAIManagementDomainSharedModule), + typeof(AbpDddApplicationContractsModule), + typeof(AbpAuthorizationAbstractionsModule))] +public class AbpAIManagementApplicationContractsModule : AbpModule +{ + +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs deleted file mode 100644 index 751b9bfaa..000000000 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.AIManagement; - -public class AbpAIManagementDomainSharedModule : AbpModule -{ - -} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateDto.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateDto.cs new file mode 100644 index 000000000..9591c2773 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateDto.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos; +public class WorkspaceDefinitionRecordCreateDto : WorkspaceDefinitionRecordCreateOrUpdateDto +{ + [Required] + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxNameLength))] + public string Name { get; set; } +} 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 new file mode 100644 index 000000000..dcb866294 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs @@ -0,0 +1,47 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos; +public abstract class WorkspaceDefinitionRecordCreateOrUpdateDto : ExtensibleObject +{ + [Required] + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxProviderLength))] + public string Provider { get; set; } + + [Required] + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxModelNameLength))] + public string ModelName { get; set; } + + [Required] + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxDisplayNameLength))] + public string DisplayName { get; set; } + + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxDescriptionLength))] + public string? Description { get; set; } + + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxApiKeyLength))] + public string? ApiKey { get; set; } + + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxApiBaseUrlLength))] + public string? ApiBaseUrl { get; set; } + + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxSystemPromptLength))] + public string? SystemPrompt { get; set; } + + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxInstructionsLength))] + public string? Instructions { get; set; } + + public float? Temperature { get; set; } + + public int? MaxOutputTokens { get; set; } + + public float? FrequencyPenalty { get; set; } + + public float? PresencePenalty { get; set; } + + public bool IsEnabled { 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 new file mode 100644 index 000000000..f65dd0ee9 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs @@ -0,0 +1,39 @@ +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Entities; + +namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos; + +[Serializable] +public class WorkspaceDefinitionRecordDto : ExtensibleAuditedEntityDto, IHasConcurrencyStamp +{ + public string Name { get; set; } + + public string Provider { get; set; } + + public string ModelName { get; set; } + + public string DisplayName { get; set; } + + public string? Description { get; set; } + + public string? ApiBaseUrl { get; set; } + + public string? SystemPrompt { get; set; } + + public string? Instructions { get; set; } + + public float? Temperature { get; set; } + + public int? MaxOutputTokens { get; set; } + + public float? FrequencyPenalty { get; set; } + + public float? PresencePenalty { get; set; } + + public bool IsEnabled { get; set; } + + public string? StateCheckers { get; set; } + + public string ConcurrencyStamp { get; set; } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordGetListInput.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordGetListInput.cs new file mode 100644 index 000000000..a4f99fb6c --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordGetListInput.cs @@ -0,0 +1,14 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos; + +[Serializable] +public class WorkspaceDefinitionRecordGetListInput : PagedAndSortedResultRequestDto +{ + public string? Filter { get; set; } + + public string? Provider { get; set; } + + public string? ModelName { get; set; } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordUpdateDto.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordUpdateDto.cs new file mode 100644 index 000000000..848ef7394 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordUpdateDto.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Domain.Entities; + +namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos; +public class WorkspaceDefinitionRecordUpdateDto : WorkspaceDefinitionRecordCreateOrUpdateDto, IHasConcurrencyStamp +{ + [Required] + [StringLength(40)] + public string ConcurrencyStamp { get; set; } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/IWorkspaceDefinitionAppService.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/IWorkspaceDefinitionAppService.cs new file mode 100644 index 000000000..6ebb52c95 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/IWorkspaceDefinitionAppService.cs @@ -0,0 +1,14 @@ +using LINGYUN.Abp.AIManagement.Workspaces.Dtos; +using System; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.AIManagement.Workspaces; +public interface IWorkspaceDefinitionAppService : + ICrudAppService< + WorkspaceDefinitionRecordDto, + Guid, + WorkspaceDefinitionRecordGetListInput, + WorkspaceDefinitionRecordCreateDto, + WorkspaceDefinitionRecordUpdateDto> +{ +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xsd b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AIManagementApplicationServiceBase.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AIManagementApplicationServiceBase.cs new file mode 100644 index 000000000..291b27256 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AIManagementApplicationServiceBase.cs @@ -0,0 +1,12 @@ +using LINGYUN.Abp.AIManagement.Localization; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.AIManagement; +public abstract class AIManagementApplicationServiceBase : ApplicationService +{ + protected AIManagementApplicationServiceBase() + { + LocalizationResource = typeof(AIManagementResource); + ObjectMapperContext = typeof(AbpAIManagementApplicationModule); + } +} 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 new file mode 100644 index 000000000..adc71e599 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs @@ -0,0 +1,15 @@ +using LINGYUN.Abp.AIManagement.Workspaces; +using LINGYUN.Abp.AIManagement.Workspaces.Dtos; +using Riok.Mapperly.Abstractions; +using Volo.Abp.Mapperly; +using Volo.Abp.ObjectExtending; + +namespace LINGYUN.Abp.AIManagement; + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +[MapExtraProperties(DefinitionChecks = MappingPropertyDefinitionChecks.None)] +public partial class WorkspaceDefinitionRecordToWorkspaceDefinitionRecordDtoMapper : MapperBase +{ + public override partial WorkspaceDefinitionRecordDto Map(WorkspaceDefinitionRecord source); + public override partial void Map(WorkspaceDefinitionRecord source, WorkspaceDefinitionRecordDto destination); +} \ No newline at end of file diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationModule.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationModule.cs new file mode 100644 index 000000000..4b5413042 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationModule.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Application; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.AIManagement; + +[DependsOn( + typeof(AbpAIManagementApplicationContractsModule), + typeof(AbpAIManagementDomainModule), + typeof(AbpDddApplicationModule))] +public class AbpAIManagementApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMapperlyObjectMapper(); + } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs deleted file mode 100644 index 751b9bfaa..000000000 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.AIManagement; - -public class AbpAIManagementDomainSharedModule : AbpModule -{ - -} 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 new file mode 100644 index 000000000..e249d025b --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs @@ -0,0 +1,152 @@ +using LINGYUN.Abp.AIManagement.Localization; +using LINGYUN.Abp.AIManagement.Workspaces.Dtos; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; +using Volo.Abp.Data; +using Volo.Abp.Security.Encryption; + +namespace LINGYUN.Abp.AIManagement.Workspaces; +public class WorkspaceDefinitionAppService : + CrudAppService< + WorkspaceDefinitionRecord, + WorkspaceDefinitionRecordDto, + Guid, + WorkspaceDefinitionRecordGetListInput, + WorkspaceDefinitionRecordCreateDto, + WorkspaceDefinitionRecordUpdateDto>, + IWorkspaceDefinitionAppService +{ + protected IStringEncryptionService StringEncryptionService { get; } + protected IWorkspaceDefinitionRecordRepository WorkspaceDefinitionRecordRepository { get; } + public WorkspaceDefinitionAppService( + IStringEncryptionService stringEncryptionService, + IWorkspaceDefinitionRecordRepository repository) : base(repository) + { + StringEncryptionService = stringEncryptionService; + WorkspaceDefinitionRecordRepository = repository; + + LocalizationResource = typeof(AIManagementResource); + ObjectMapperContext = typeof(AbpAIManagementApplicationModule); + } + + protected async override Task> CreateFilteredQueryAsync(WorkspaceDefinitionRecordGetListInput input) + { + var queryable = await base.CreateFilteredQueryAsync(input); + + return queryable + .WhereIf(!input.Provider.IsNullOrWhiteSpace(), x => x.Provider == input.Provider) + .WhereIf(!input.ModelName.IsNullOrWhiteSpace(), x => x.ModelName == input.ModelName) + .WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Provider.Contains(input.Filter!) || + x.ModelName.Contains(input.Filter!) || x.DisplayName.Contains(input.Filter!) || + (!x.Description.IsNullOrWhiteSpace() && x.Description.Contains(input.Filter!)) || + (!x.SystemPrompt.IsNullOrWhiteSpace() && x.SystemPrompt.Contains(input.Filter!)) || + (!x.Instructions.IsNullOrWhiteSpace() && x.Instructions.Contains(input.Filter!))); + } + + protected async override Task MapToEntityAsync(WorkspaceDefinitionRecordCreateDto createInput) + { + if (await WorkspaceDefinitionRecordRepository.FindByNameAsync(createInput.Name) != null) + { + throw new WorkspaceAlreadyExistsException(createInput.Name); + } + + var record = new WorkspaceDefinitionRecord( + GuidGenerator.Create(), + createInput.Name, + createInput.Provider, + createInput.ModelName, + createInput.DisplayName, + createInput.Description, + createInput.SystemPrompt, + createInput.Instructions, + createInput.Temperature, + createInput.MaxOutputTokens, + createInput.FrequencyPenalty, + createInput.PresencePenalty, + createInput.StateCheckers); + + if (!createInput.ApiKey.IsNullOrWhiteSpace()) + { + var encryptApiKey = StringEncryptionService.Encrypt(createInput.ApiKey); + record.SetApiKey(encryptApiKey, createInput.ApiBaseUrl); + } + + return record; + } + + protected override void MapToEntity(WorkspaceDefinitionRecordUpdateDto updateInput, WorkspaceDefinitionRecord entity) + { + if (entity.DisplayName != updateInput.DisplayName) + { + entity.SetDisplayName(updateInput.DisplayName); + } + + if (entity.Description != updateInput.Description) + { + entity.Description = updateInput.Description; + } + + if (entity.Provider != updateInput.Provider || entity.ModelName != updateInput.ModelName) + { + entity.SetModel(updateInput.Provider, updateInput.ModelName); + } + + if (entity.SystemPrompt != updateInput.SystemPrompt) + { + entity.SystemPrompt = updateInput.SystemPrompt; + } + + if (entity.Instructions != updateInput.Instructions) + { + entity.Instructions = updateInput.Instructions; + } + + if (entity.IsEnabled != updateInput.IsEnabled) + { + entity.IsEnabled = updateInput.IsEnabled; + } + + if (entity.Temperature != updateInput.Temperature) + { + entity.Temperature = updateInput.Temperature; + } + + if (entity.MaxOutputTokens != updateInput.MaxOutputTokens) + { + entity.MaxOutputTokens = updateInput.MaxOutputTokens; + } + + if (entity.FrequencyPenalty != updateInput.FrequencyPenalty) + { + entity.FrequencyPenalty = updateInput.FrequencyPenalty; + } + + if (entity.PresencePenalty != updateInput.PresencePenalty) + { + entity.PresencePenalty = updateInput.PresencePenalty; + } + + if (entity.StateCheckers != updateInput.StateCheckers) + { + entity.StateCheckers = updateInput.StateCheckers; + } + + if (!updateInput.ApiKey.IsNullOrWhiteSpace()) + { + var encryptApiKey = StringEncryptionService.Encrypt(updateInput.ApiKey); + entity.SetApiKey(encryptApiKey, updateInput.ApiBaseUrl); + } + + if (!entity.HasSameExtraProperties(updateInput)) + { + entity.ExtraProperties.Clear(); + + foreach (var property in updateInput.ExtraProperties) + { + entity.ExtraProperties.Add(property.Key, property.Value); + } + } + } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/AIManagementErrorCodes.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/AIManagementErrorCodes.cs new file mode 100644 index 000000000..ae295d8db --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/AIManagementErrorCodes.cs @@ -0,0 +1,12 @@ +namespace LINGYUN.Abp.AIManagement; +public static class AIManagementErrorCodes +{ + public const string Namespace = "AIManagement"; + + public static class Workspace + { + public const string Prefix = Namespace + ":100"; + + public const string NameAlreadyExists = Prefix + "001"; + } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceAlreadyExistsException.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceAlreadyExistsException.cs new file mode 100644 index 000000000..5e23fd8b3 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceAlreadyExistsException.cs @@ -0,0 +1,16 @@ +using Volo.Abp; + +namespace LINGYUN.Abp.AIManagement.Workspaces; +public class WorkspaceAlreadyExistsException : BusinessException +{ + public string Workspace { get; } + public WorkspaceAlreadyExistsException(string workspace) + : base( + AIManagementErrorCodes.Workspace.NameAlreadyExists, + $"A Workspace named {workspace} already exists!") + { + Workspace = workspace; + + WithData(nameof(Workspace), workspace); + } +} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/AbpAIManagementDbProperties.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/AbpAIManagementDbProperties.cs index 852fbd74a..947baaa18 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/AbpAIManagementDbProperties.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/AbpAIManagementDbProperties.cs @@ -3,7 +3,7 @@ namespace LINGYUN.Abp.AIManagement; public static class AbpAIManagementDbProperties { - public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix; + public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix + "AI"; public static string? DbSchema { get; set; } = AbpCommonDbProperties.DbSchema; diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file 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 b6e8d2110..f3f5e9f9a 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 @@ -80,7 +80,7 @@ public static class AIManagementDbContextModelBuilderExtensions b.Property(x => x.ApiKey) .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxApiKeyLength); b.Property(x => x.ApiBaseUrl) - .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxApiKeyLength); + .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxApiBaseUrlLength); b.Property(x => x.SystemPrompt) .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxSystemPromptLength); b.Property(x => x.Instructions) diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs deleted file mode 100644 index 751b9bfaa..000000000 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/AbpAIManagementDomainSharedModule.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.AIManagement; - -public class AbpAIManagementDomainSharedModule : AbpModule -{ - -} diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionController.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionController.cs new file mode 100644 index 000000000..58444f420 --- /dev/null +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionController.cs @@ -0,0 +1,52 @@ +using LINGYUN.Abp.AIManagement.Workspaces.Dtos; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.AIManagement.Workspaces; + +[Controller] +[RemoteService(Name = AIManagementRemoteServiceConsts.RemoteServiceName)] +[Area(AIManagementRemoteServiceConsts.ModuleName)] +[Route($"api/{AIManagementRemoteServiceConsts.ModuleName}/workspaces")] +public class WorkspaceDefinitionController : AbpControllerBase, IWorkspaceDefinitionAppService +{ + private readonly IWorkspaceDefinitionAppService _service; + public WorkspaceDefinitionController(IWorkspaceDefinitionAppService service) + { + _service = service; + } + + [HttpPost] + public virtual Task CreateAsync(WorkspaceDefinitionRecordCreateDto input) + { + return _service.CreateAsync(input); + } + + [HttpDelete("{id}")] + public virtual Task DeleteAsync(Guid id) + { + return _service.DeleteAsync(id); + } + + [HttpGet("{id}")] + public virtual Task GetAsync(Guid id) + { + return _service.GetAsync(id); + } + + [HttpGet] + public virtual Task> GetListAsync(WorkspaceDefinitionRecordGetListInput input) + { + return _service.GetListAsync(input); + } + + [HttpPut("{id}")] + public virtual Task UpdateAsync(Guid id, WorkspaceDefinitionRecordUpdateDto input) + { + return _service.UpdateAsync(id, input); + } +}