diff --git a/aspnet-core/LINGYUN.MicroService.Aspire.slnx b/aspnet-core/LINGYUN.MicroService.Aspire.slnx
new file mode 100644
index 000000000..670b925f3
--- /dev/null
+++ b/aspnet-core/LINGYUN.MicroService.Aspire.slnx
@@ -0,0 +1,561 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorHostedService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorHostedService.cs
new file mode 100644
index 000000000..2590ba079
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorHostedService.cs
@@ -0,0 +1,53 @@
+using LINGYUN.Abp.MicroService.AIService.DbMigrator;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Serilog;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Data;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+public class AIServiceDbMigratorHostedService : IHostedService
+{
+ private readonly IHostApplicationLifetime _hostApplicationLifetime;
+ private readonly IConfiguration _configuration;
+
+ public AIServiceDbMigratorHostedService(
+ IHostApplicationLifetime hostApplicationLifetime,
+ IConfiguration configuration)
+ {
+ _hostApplicationLifetime = hostApplicationLifetime;
+ _configuration = configuration;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ using var application = await AbpApplicationFactory
+ .CreateAsync(options =>
+ {
+ options.Services.ReplaceConfiguration(_configuration);
+ options.UseAutofac();
+ options.Services.AddLogging(c => c.AddSerilog());
+ options.AddDataMigrationEnvironment();
+ });
+
+ await application.InitializeAsync();
+
+ await application
+ .ServiceProvider
+ .GetRequiredService()
+ .CheckAndApplyDatabaseMigrationsAsync();
+
+ await application.ShutdownAsync();
+
+ _hostApplicationLifetime.StopApplication();
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+}
+
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorModule.cs
new file mode 100644
index 000000000..ff9dd1c85
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorModule.cs
@@ -0,0 +1,13 @@
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.MicroService.AIService.DbMigrator;
+
+[DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(AIServiceMigrationsEntityFrameworkCoreModule)
+ )]
+public class AIServiceDbMigratorModule : AbpModule
+{
+
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj
new file mode 100644
index 000000000..662765cf3
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj
@@ -0,0 +1,40 @@
+
+
+
+
+
+ Exe
+ net10.0
+ enable
+ false
+ LINGYUN.Abp.MicroService.AIService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+ Always
+
+
+
+
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/Program.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/Program.cs
new file mode 100644
index 000000000..135bb215b
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/Program.cs
@@ -0,0 +1,43 @@
+using LINGYUN.Abp.MicroService.AIService;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Serilog;
+using Serilog.Events;
+using System;
+
+var defaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}";
+
+Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
+ .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning)
+#if DEBUG
+ .MinimumLevel.Override("LINGYUN.Abp.MicroService.AIService", LogEventLevel.Debug)
+#else
+ .MinimumLevel.Override("LINGYUN.Abp.MicroService.AIService", LogEventLevel.Information)
+#endif
+ .Enrich.FromLogContext()
+ .WriteTo.Async(x => x.Console(outputTemplate: defaultOutputTemplate))
+ .WriteTo.Async(x => x.File("Logs/migrations.txt", outputTemplate: defaultOutputTemplate))
+ .CreateLogger();
+
+try
+{
+ var builder = Host.CreateDefaultBuilder(args)
+ .AddAppSettingsSecretsJson()
+ .ConfigureLogging((context, logging) => logging.ClearProviders())
+ .ConfigureServices((hostContext, services) =>
+ {
+ services.AddHostedService();
+ });
+ await builder.RunConsoleAsync();
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "Host terminated unexpectedly!");
+}
+finally
+{
+ await Log.CloseAndFlushAsync();
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/appsettings.json
new file mode 100644
index 000000000..38212c579
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/appsettings.json
@@ -0,0 +1,5 @@
+{
+ "ConnectionStrings": {
+ "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456"
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDataSeeder.cs
new file mode 100644
index 000000000..8a088b76d
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDataSeeder.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using System.Threading.Tasks;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+public class AIServiceDataSeeder : ITransientDependency
+{
+ protected ILogger Logger { get; }
+ protected ICurrentTenant CurrentTenant { get; }
+
+ public AIServiceDataSeeder(
+ ICurrentTenant currentTenant)
+ {
+ CurrentTenant = currentTenant;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public virtual Task SeedAsync(DataSeedContext context)
+ {
+ return Task.CompletedTask;
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationEventHandler.cs
new file mode 100644
index 000000000..b05842e54
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationEventHandler.cs
@@ -0,0 +1,44 @@
+using Microsoft.Extensions.Logging;
+using System.Threading.Tasks;
+using Volo.Abp.Data;
+using Volo.Abp.DistributedLocking;
+using Volo.Abp.EntityFrameworkCore.Migrations;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Uow;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+public class AIServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase
+{
+ protected AIServiceDataSeeder DataSeeder { get; }
+
+ public AIServiceDbMigrationEventHandler(
+ ICurrentTenant currentTenant,
+ IUnitOfWorkManager unitOfWorkManager,
+ ITenantStore tenantStore,
+ IAbpDistributedLock abpDistributedLock,
+ IDistributedEventBus distributedEventBus,
+ ILoggerFactory loggerFactory,
+ AIServiceDataSeeder dataSeeder)
+ : base(
+ ConnectionStringNameAttribute.GetConnStringName(),
+ currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory)
+ {
+ DataSeeder = dataSeeder;
+ }
+
+ protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated)
+ {
+ // 新租户数据种子
+ var context = new DataSeedContext(eventData.Id);
+ if (eventData.Properties != null)
+ {
+ foreach (var property in eventData.Properties)
+ {
+ context.WithProperty(property.Key, property.Value);
+ }
+ }
+
+ await DataSeeder.SeedAsync(context);
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationService.cs
new file mode 100644
index 000000000..445f0fd92
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationService.cs
@@ -0,0 +1,36 @@
+using LINGYUN.Abp.Data.DbMigrator;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.DistributedLocking;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Uow;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+public class AIServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency
+{
+ protected AIServiceDataSeeder DataSeeder { get; }
+ public AIServiceDbMigrationService(
+ ICurrentTenant currentTenant,
+ IUnitOfWorkManager unitOfWorkManager,
+ IServiceProvider serviceProvider,
+ IAbpDistributedLock abpDistributedLock,
+ IDistributedEventBus distributedEventBus,
+ ILoggerFactory loggerFactory,
+ AIServiceDataSeeder dataSeeder)
+ : base(
+ ConnectionStringNameAttribute.GetConnStringName(),
+ unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory)
+ {
+ DataSeeder = dataSeeder;
+ }
+
+ protected async override Task SeedAsync()
+ {
+ // DbMigrator迁移数据种子
+ await DataSeeder.SeedAsync(new DataSeedContext());
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContext.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContext.cs
new file mode 100644
index 000000000..35d068464
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContext.cs
@@ -0,0 +1,32 @@
+using LINGYUN.Abp.AIManagement.Chats;
+using LINGYUN.Abp.AIManagement.EntityFrameworkCore;
+using LINGYUN.Abp.AIManagement.Tokens;
+using LINGYUN.Abp.AIManagement.Workspaces;
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.Data;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+
+[ConnectionStringName("Default")]
+public class AIServiceMigrationsDbContext :
+ AbpDbContext,
+ IAIManagementDbContext
+{
+ public DbSet WorkspaceDefinitions { get; set; }
+ public DbSet TextChatMessageRecords { get; set; }
+ public DbSet ConversationRecords { get; set; }
+ public DbSet TokenUsageRecords { get; set; }
+
+ public AIServiceMigrationsDbContext(
+ DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ base.OnModelCreating(builder);
+
+ builder.ConfigureAIManagement();
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContextFactory.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContextFactory.cs
new file mode 100644
index 000000000..afd229619
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContextFactory.cs
@@ -0,0 +1,28 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+using System.IO;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+public class AIServiceMigrationsDbContextFactory : IDesignTimeDbContextFactory
+{
+ public AIServiceMigrationsDbContext CreateDbContext(string[] args)
+ {
+ var configuration = BuildConfiguration();
+ var connectionString = configuration.GetConnectionString("Default");
+
+ var builder = new DbContextOptionsBuilder()
+ .UseNpgsql(connectionString);
+
+ return new AIServiceMigrationsDbContext(builder!.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../LINGYUN.Abp.MicroService.AIService.DbMigrator/"))
+ .AddJsonFile("appsettings.json", optional: false);
+
+ return builder.Build();
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsEntityFrameworkCoreModule.cs
new file mode 100644
index 000000000..1c84f02f9
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsEntityFrameworkCoreModule.cs
@@ -0,0 +1,45 @@
+using LINGYUN.Abp.AIManagement.EntityFrameworkCore;
+using LINGYUN.Abp.Data.DbMigrator;
+using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
+using LINGYUN.Abp.Saas.EntityFrameworkCore;
+using LINGYUN.Abp.TextTemplating.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.PostgreSql;
+using Volo.Abp.FeatureManagement.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+
+namespace LINGYUN.Abp.MicroService.AIService;
+
+[DependsOn(
+ typeof(AbpAIManagementEntityFrameworkCoreModule),
+ typeof(AbpSaasEntityFrameworkCoreModule),
+ typeof(AbpSettingManagementEntityFrameworkCoreModule),
+ typeof(AbpPermissionManagementEntityFrameworkCoreModule),
+ typeof(AbpFeatureManagementEntityFrameworkCoreModule),
+ typeof(AbpLocalizationManagementEntityFrameworkCoreModule),
+ typeof(AbpTextTemplatingEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCorePostgreSqlModule),
+ typeof(AbpDataDbMigratorModule)
+ )]
+public class AIServiceMigrationsEntityFrameworkCoreModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic
+ AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAbpDbContext();
+
+ Configure(options =>
+ {
+ options.UseNpgsql();
+ });
+ }
+}
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xsd
new file mode 100644
index 000000000..3f3946e28
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.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/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj
new file mode 100644
index 000000000..c85236273
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ false
+ net10.0
+ enable
+ LINGYUN.Abp.MicroService.AIService
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.Designer.cs
new file mode 100644
index 000000000..3b253c2ca
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.Designer.cs
@@ -0,0 +1,303 @@
+//
+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("20260127083027_Initial_AI_Service")]
+ partial class Initial_AI_Service
+ {
+ ///
+ 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.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/20260127083027_Initial_AI_Service.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.cs
new file mode 100644
index 000000000..ed6c57888
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.cs
@@ -0,0 +1,148 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LINGYUN.Abp.MicroService.AIService.Migrations
+{
+ ///
+ public partial class Initial_AI_Service : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "AbpAIConversations",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ TenantId = table.Column(type: "uuid", nullable: true),
+ Name = table.Column(type: "character varying(50)", maxLength: 50, nullable: false),
+ CreatedAt = table.Column(type: "timestamp with time zone", nullable: false),
+ ExpiredAt = table.Column(type: "timestamp with time zone", nullable: false),
+ UpdateAt = table.Column(type: "timestamp with time zone", nullable: true),
+ CreationTime = table.Column(type: "timestamp with time zone", nullable: false),
+ CreatorId = table.Column(type: "uuid", nullable: true),
+ LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true),
+ LastModifierId = table.Column(type: "uuid", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_AbpAIConversations", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "AbpAITextChatMessages",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ Content = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false),
+ ExtraProperties = table.Column(type: "text", nullable: false),
+ ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false),
+ CreationTime = table.Column(type: "timestamp with time zone", nullable: false),
+ CreatorId = table.Column(type: "uuid", nullable: true),
+ LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true),
+ LastModifierId = table.Column(type: "uuid", nullable: true),
+ TenantId = table.Column(type: "uuid", nullable: true),
+ Workspace = table.Column(type: "character varying(64)", maxLength: 64, nullable: false),
+ Role = table.Column(type: "character varying(20)", maxLength: 20, nullable: false),
+ CreatedAt = table.Column(type: "timestamp with time zone", nullable: false),
+ UserId = table.Column(type: "uuid", nullable: true),
+ ConversationId = table.Column(type: "uuid", nullable: true),
+ ReplyMessage = table.Column(type: "text", nullable: true),
+ ReplyAt = table.Column(type: "timestamp with time zone", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_AbpAITextChatMessages", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "AbpAITokenUsages",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ TenantId = table.Column(type: "uuid", nullable: true),
+ MessageId = table.Column(type: "uuid", nullable: true),
+ ConversationId = table.Column(type: "uuid", nullable: true),
+ InputTokenCount = table.Column(type: "bigint", nullable: true),
+ OutputTokenCount = table.Column(type: "bigint", nullable: true),
+ TotalTokenCount = table.Column(type: "bigint", nullable: true),
+ CachedInputTokenCount = table.Column(type: "bigint", nullable: true),
+ ReasoningTokenCount = table.Column(type: "bigint", nullable: true),
+ CreationTime = table.Column(type: "timestamp with time zone", nullable: false),
+ CreatorId = table.Column(type: "uuid", nullable: true),
+ LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true),
+ LastModifierId = table.Column(type: "uuid", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_AbpAITokenUsages", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "AbpAIWorkspaceDefinitions",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false),
+ Provider = table.Column(type: "character varying(20)", maxLength: 20, nullable: false),
+ ModelName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false),
+ DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false),
+ Description = table.Column(type: "character varying(128)", maxLength: 128, nullable: true),
+ ApiKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ ApiBaseUrl = table.Column(type: "character varying(128)", maxLength: 128, nullable: true),
+ SystemPrompt = table.Column(type: "character varying(512)", maxLength: 512, nullable: true),
+ Instructions = table.Column(type: "character varying(512)", maxLength: 512, nullable: true),
+ Temperature = table.Column(type: "real", nullable: true),
+ MaxOutputTokens = table.Column(type: "integer", nullable: true),
+ FrequencyPenalty = table.Column(type: "real", nullable: true),
+ PresencePenalty = table.Column(type: "real", nullable: true),
+ IsEnabled = table.Column(type: "boolean", nullable: false),
+ StateCheckers = table.Column(type: "character varying(256)", maxLength: 256, nullable: true),
+ ExtraProperties = table.Column(type: "text", nullable: false),
+ ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false),
+ CreationTime = table.Column(type: "timestamp with time zone", nullable: false),
+ CreatorId = table.Column(type: "uuid", nullable: true),
+ LastModificationTime = table.Column(type: "timestamp with time zone", nullable: true),
+ LastModifierId = table.Column(type: "uuid", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_AbpAIWorkspaceDefinitions", x => x.Id);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AbpAITextChatMessages_TenantId_ConversationId",
+ table: "AbpAITextChatMessages",
+ columns: new[] { "TenantId", "ConversationId" });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AbpAITokenUsages_TenantId_ConversationId",
+ table: "AbpAITokenUsages",
+ columns: new[] { "TenantId", "ConversationId" });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AbpAIWorkspaceDefinitions_Name",
+ table: "AbpAIWorkspaceDefinitions",
+ column: "Name",
+ unique: true);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "AbpAIConversations");
+
+ migrationBuilder.DropTable(
+ name: "AbpAITextChatMessages");
+
+ migrationBuilder.DropTable(
+ name: "AbpAITokenUsages");
+
+ migrationBuilder.DropTable(
+ name: "AbpAIWorkspaceDefinitions");
+ }
+ }
+}
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/20260313034606_Add-IsSystem-To-Workspace-Record.Designer.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313034606_Add-IsSystem-To-Workspace-Record.Designer.cs
new file mode 100644
index 000000000..3f1247abe
--- /dev/null
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260313034606_Add-IsSystem-To-Workspace-Record.Designer.cs
@@ -0,0 +1,311 @@
+//
+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("20260313034606_Add-IsSystem-To-Workspace-Record")]
+ partial class AddIsSystemToWorkspaceRecord
+ {
+ ///
+ 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