From 760e43c5da169ddf42e3cd274e2f80f354f66e18 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 13 Mar 2026 11:21:32 +0800 Subject: [PATCH] feat: Add the workspace field to the conversation. --- ...rkspace-To-Conversation-Record.Designer.cs | 308 ++++++++++++++++++ ...18_Add-Workspace-To-Conversation-Record.cs | 30 ++ ...ServiceMigrationsDbContextModelSnapshot.cs | 5 + .../LINGYUN/Abp/AI/Agent/AgentService.cs | 1 + .../Chats/Dtos/ConversationCreateDto.cs | 9 +- .../Chats/Dtos/ConversationDto.cs | 2 + .../Chats/ConversationAppService.cs | 4 + .../AIManagement/Chats/ConversationRecord.cs | 14 +- .../AIManagement/Chats/ConversationStore.cs | 3 +- ...nagementDbContextModelBuilderExtensions.cs | 3 + 10 files changed, 376 insertions(+), 3 deletions(-) create mode 100644 aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.Designer.cs create mode 100644 aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.cs diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.Designer.cs new file mode 100644 index 000000000..e6b5bb135 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.Designer.cs @@ -0,0 +1,308 @@ +// +using System; +using LINGYUN.Abp.MicroService.AIService; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AIService.Migrations +{ + [DbContext(typeof(AIServiceMigrationsDbContext))] + [Migration("20260313010418_Add-Workspace-To-Conversation-Record")] + partial class AddWorkspaceToConversationRecord + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LINGYUN.Abp.AIManagement.Chats.ConversationRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UpdateAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Workspace") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.ToTable("AbpAIConversations", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.AIManagement.Chats.TextChatMessageRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ConversationId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReplyAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyMessage") + .HasColumnType("text"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Workspace") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ConversationId"); + + b.ToTable("AbpAITextChatMessages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.AIManagement.Tokens.TokenUsageRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CachedInputTokenCount") + .HasColumnType("bigint"); + + b.Property("ConversationId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("InputTokenCount") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("OutputTokenCount") + .HasColumnType("bigint"); + + b.Property("ReasoningTokenCount") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalTokenCount") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ConversationId"); + + b.ToTable("AbpAITokenUsages", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.AIManagement.Workspaces.WorkspaceDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApiBaseUrl") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ApiKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FrequencyPenalty") + .HasColumnType("real"); + + b.Property("Instructions") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MaxOutputTokens") + .HasColumnType("integer"); + + b.Property("ModelName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("PresencePenalty") + .HasColumnType("real"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SystemPrompt") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Temperature") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpAIWorkspaceDefinitions", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.cs new file mode 100644 index 000000000..b080e32e7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313010418_Add-Workspace-To-Conversation-Record.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LINGYUN.Abp.MicroService.AIService.Migrations +{ + /// + public partial class AddWorkspaceToConversationRecord : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Workspace", + table: "AbpAIConversations", + type: "character varying(64)", + maxLength: 64, + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Workspace", + table: "AbpAIConversations"); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/AIServiceMigrationsDbContextModelSnapshot.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/AIServiceMigrationsDbContextModelSnapshot.cs index 095a0771d..9cc821579 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/AIServiceMigrationsDbContextModelSnapshot.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/AIServiceMigrationsDbContextModelSnapshot.cs @@ -63,6 +63,11 @@ namespace LINGYUN.Abp.MicroService.AIService.Migrations b.Property("UpdateAt") .HasColumnType("timestamp with time zone"); + b.Property("Workspace") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + b.HasKey("Id"); b.ToTable("AbpAIConversations", (string)null); diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentService.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentService.cs index 78c9f0508..046d714ce 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentService.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentService.cs @@ -127,6 +127,7 @@ public class AgentService : IAgentService, IScopedDependency var conversation = new Conversation( _guidGenerator.Create(), _localizerResource["NewConversation"], + message.Workspace, _clock.Now); await _conversationStore.SaveAsync(conversation); diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationCreateDto.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationCreateDto.cs index 8112305b2..e8ad0a33b 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationCreateDto.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationCreateDto.cs @@ -1,8 +1,15 @@ -using Volo.Abp.Validation; +using LINGYUN.Abp.AIManagement.Workspaces; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; namespace LINGYUN.Abp.AIManagement.Chats.Dtos; public class ConversationCreateDto { [DynamicStringLength(typeof(ConversationRecordConsts), nameof(ConversationRecordConsts.MaxNameLength))] public string? Name { get; set; } + + [Required] + [DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxNameLength))] + public string Workspace { get; set; } + } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationDto.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationDto.cs index 8f5945c95..5a64ac79e 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationDto.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationDto.cs @@ -6,6 +6,8 @@ public class ConversationDto : AuditedEntityDto { public string Name { get; set; } + public string Workspace { get; set; } + public DateTime CreatedAt { get; set; } public DateTime ExpiredAt { get; set; } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ConversationAppService.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ConversationAppService.cs index 203747602..dc1fc00af 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ConversationAppService.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ConversationAppService.cs @@ -46,6 +46,7 @@ public class ConversationAppService : return new ConversationRecord( GuidGenerator.Create(), conversationName, + createInput.Workspace, createdAt, expiredTime, CurrentTenant.Id); @@ -57,6 +58,8 @@ public class ConversationAppService : { entity.SetName(updateInput.Name); } + + entity.ChangeTime(Clock.Now); } protected override ConversationDto MapToGetOutputDto(ConversationRecord entity) @@ -72,6 +75,7 @@ public class ConversationAppService : LastModifierId = entity.LastModifierId, Name = entity.Name, UpdateAt = entity.UpdateAt, + Workspace = entity.Workspace, }; } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationRecord.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationRecord.cs index 10192ab8b..939d6f935 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationRecord.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationRecord.cs @@ -1,4 +1,5 @@ -using System; +using LINGYUN.Abp.AIManagement.Workspaces; +using System; using Volo.Abp; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; @@ -10,6 +11,8 @@ public class ConversationRecord : AuditedEntity, IMultiTenant public string Name { get; private set; } + public string Workspace { get; private set; } + public DateTime CreatedAt { get; private set; } public DateTime ExpiredAt { get; set; } @@ -18,13 +21,16 @@ public class ConversationRecord : AuditedEntity, IMultiTenant public ConversationRecord( Guid id, string name, + string workspace, DateTime createdAt, DateTime expiredAt, Guid? tenantId = null) : base(id) { Name = Check.NotNullOrWhiteSpace(name, nameof(name), ConversationRecordConsts.MaxNameLength); + Workspace = Check.NotNullOrWhiteSpace(workspace, nameof(workspace), WorkspaceDefinitionRecordConsts.MaxNameLength); CreatedAt = createdAt; + CreationTime = createdAt; ExpiredAt = expiredAt; UpdateAt = createdAt; @@ -36,4 +42,10 @@ public class ConversationRecord : AuditedEntity, IMultiTenant { Name = Check.NotNullOrWhiteSpace(name, nameof(name), ConversationRecordConsts.MaxNameLength); } + + public void ChangeTime(DateTime updateTime) + { + UpdateAt = updateTime; + LastModificationTime = updateTime; + } } diff --git a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationStore.cs b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationStore.cs index 3d7d2ed5e..7ee2c120a 100644 --- a/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationStore.cs +++ b/aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN/Abp/AIManagement/Chats/ConversationStore.cs @@ -3,7 +3,6 @@ using LINGYUN.Abp.AI.Models; using Microsoft.Extensions.Options; using System; using System.Threading.Tasks; -using Volo.Abp; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; using Volo.Abp.Specifications; @@ -58,6 +57,7 @@ public class ConversationStore : IConversationStore, ITransientDependency var conversation = new Conversation( conversationRecord.Id, conversationRecord.Name, + conversationRecord.Workspace, conversationRecord.CreatedAt) { UpdateAt = conversationRecord.UpdateAt, @@ -77,6 +77,7 @@ public class ConversationStore : IConversationStore, ITransientDependency conversationRecord = new ConversationRecord( conversation.Id, conversation.Name, + conversation.Workspace, conversation.CreatedAt, expiredTime, _currentTenant.Id); 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 f3f5e9f9a..e62b67b95 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 @@ -24,6 +24,9 @@ public static class AIManagementDbContextModelBuilderExtensions b.Property(x => x.Name) .HasMaxLength(ConversationRecordConsts.MaxNameLength) .IsRequired(); + b.Property(x => x.Workspace) + .HasMaxLength(WorkspaceDefinitionRecordConsts.MaxNameLength) + .IsRequired(); }); builder.Entity(b => {