23 changed files with 496 additions and 28 deletions
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.AIManagement; |
|||
public static class AIManagementRemoteServiceConsts |
|||
{ |
|||
public const string RemoteServiceName = "AbpAIManagement"; |
|||
|
|||
public const string ModuleName = "ai-management"; |
|||
} |
|||
@ -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 |
|||
{ |
|||
|
|||
} |
|||
@ -1,8 +0,0 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.AIManagement; |
|||
|
|||
public class AbpAIManagementDomainSharedModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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<Guid>, 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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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> |
|||
{ |
|||
} |
|||
@ -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> |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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<WorkspaceDefinitionRecord, WorkspaceDefinitionRecordDto> |
|||
{ |
|||
public override partial WorkspaceDefinitionRecordDto Map(WorkspaceDefinitionRecord source); |
|||
public override partial void Map(WorkspaceDefinitionRecord source, WorkspaceDefinitionRecordDto destination); |
|||
} |
|||
@ -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<AbpAIManagementApplicationModule>(); |
|||
} |
|||
} |
|||
@ -1,8 +0,0 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.AIManagement; |
|||
|
|||
public class AbpAIManagementDomainSharedModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -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<IQueryable<WorkspaceDefinitionRecord>> 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<WorkspaceDefinitionRecord> 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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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"; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -1,8 +0,0 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.AIManagement; |
|||
|
|||
public class AbpAIManagementDomainSharedModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -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<WorkspaceDefinitionRecordDto> CreateAsync(WorkspaceDefinitionRecordCreateDto input) |
|||
{ |
|||
return _service.CreateAsync(input); |
|||
} |
|||
|
|||
[HttpDelete("{id}")] |
|||
public virtual Task DeleteAsync(Guid id) |
|||
{ |
|||
return _service.DeleteAsync(id); |
|||
} |
|||
|
|||
[HttpGet("{id}")] |
|||
public virtual Task<WorkspaceDefinitionRecordDto> GetAsync(Guid id) |
|||
{ |
|||
return _service.GetAsync(id); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual Task<PagedResultDto<WorkspaceDefinitionRecordDto>> GetListAsync(WorkspaceDefinitionRecordGetListInput input) |
|||
{ |
|||
return _service.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut("{id}")] |
|||
public virtual Task<WorkspaceDefinitionRecordDto> UpdateAsync(Guid id, WorkspaceDefinitionRecordUpdateDto input) |
|||
{ |
|||
return _service.UpdateAsync(id, input); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue