30 changed files with 2179 additions and 0 deletions
@ -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<AIServiceDbMigratorModule>(options => |
|||
{ |
|||
options.Services.ReplaceConfiguration(_configuration); |
|||
options.UseAutofac(); |
|||
options.Services.AddLogging(c => c.AddSerilog()); |
|||
options.AddDataMigrationEnvironment(); |
|||
}); |
|||
|
|||
await application.InitializeAsync(); |
|||
|
|||
await application |
|||
.ServiceProvider |
|||
.GetRequiredService<AIServiceDbMigrationService>() |
|||
.CheckAndApplyDatabaseMigrationsAsync(); |
|||
|
|||
await application.ShutdownAsync(); |
|||
|
|||
_hostApplicationLifetime.StopApplication(); |
|||
} |
|||
|
|||
public Task StopAsync(CancellationToken cancellationToken) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
|
|||
@ -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 |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,40 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\common.secrets.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>net10.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<IsPackable>false</IsPackable> |
|||
<RootNamespace>LINGYUN.Abp.MicroService.AIService</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Serilog.Extensions.Logging" /> |
|||
<PackageReference Include="Serilog.Sinks.Async" /> |
|||
<PackageReference Include="Serilog.Sinks.File" /> |
|||
<PackageReference Include="Serilog.Sinks.Console" /> |
|||
<PackageReference Include="Microsoft.Extensions.Hosting" /> |
|||
<PackageReference Include="Volo.Abp.Autofac" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Remove="Logs\**" /> |
|||
<Content Remove="Logs\**" /> |
|||
<EmbeddedResource Remove="Logs\**" /> |
|||
<None Remove="Logs\**" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore\LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<None Update="appsettings.json"> |
|||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> |
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -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<AIServiceDbMigratorHostedService>(); |
|||
}); |
|||
await builder.RunConsoleAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Log.Fatal(ex, "Host terminated unexpectedly!"); |
|||
} |
|||
finally |
|||
{ |
|||
await Log.CloseAndFlushAsync(); |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" |
|||
} |
|||
} |
|||
@ -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<AIServiceDataSeeder> Logger { get; } |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public AIServiceDataSeeder( |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
CurrentTenant = currentTenant; |
|||
|
|||
Logger = NullLogger<AIServiceDataSeeder>.Instance; |
|||
} |
|||
|
|||
public virtual Task SeedAsync(DataSeedContext context) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
@ -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<AIServiceMigrationsDbContext> |
|||
{ |
|||
protected AIServiceDataSeeder DataSeeder { get; } |
|||
|
|||
public AIServiceDbMigrationEventHandler( |
|||
ICurrentTenant currentTenant, |
|||
IUnitOfWorkManager unitOfWorkManager, |
|||
ITenantStore tenantStore, |
|||
IAbpDistributedLock abpDistributedLock, |
|||
IDistributedEventBus distributedEventBus, |
|||
ILoggerFactory loggerFactory, |
|||
AIServiceDataSeeder dataSeeder) |
|||
: base( |
|||
ConnectionStringNameAttribute.GetConnStringName<AIServiceMigrationsDbContext>(), |
|||
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); |
|||
} |
|||
} |
|||
@ -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<AIServiceMigrationsDbContext>, ITransientDependency |
|||
{ |
|||
protected AIServiceDataSeeder DataSeeder { get; } |
|||
public AIServiceDbMigrationService( |
|||
ICurrentTenant currentTenant, |
|||
IUnitOfWorkManager unitOfWorkManager, |
|||
IServiceProvider serviceProvider, |
|||
IAbpDistributedLock abpDistributedLock, |
|||
IDistributedEventBus distributedEventBus, |
|||
ILoggerFactory loggerFactory, |
|||
AIServiceDataSeeder dataSeeder) |
|||
: base( |
|||
ConnectionStringNameAttribute.GetConnStringName<AIServiceMigrationsDbContext>(), |
|||
unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) |
|||
{ |
|||
DataSeeder = dataSeeder; |
|||
} |
|||
|
|||
protected async override Task SeedAsync() |
|||
{ |
|||
// DbMigrator迁移数据种子
|
|||
await DataSeeder.SeedAsync(new DataSeedContext()); |
|||
} |
|||
} |
|||
@ -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<AIServiceMigrationsDbContext>, |
|||
IAIManagementDbContext |
|||
{ |
|||
public DbSet<WorkspaceDefinitionRecord> WorkspaceDefinitions { get; set; } |
|||
public DbSet<TextChatMessageRecord> TextChatMessageRecords { get; set; } |
|||
public DbSet<ConversationRecord> ConversationRecords { get; set; } |
|||
public DbSet<TokenUsageRecord> TokenUsageRecords { get; set; } |
|||
|
|||
public AIServiceMigrationsDbContext( |
|||
DbContextOptions<AIServiceMigrationsDbContext> options) : base(options) |
|||
{ |
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
base.OnModelCreating(builder); |
|||
|
|||
builder.ConfigureAIManagement(); |
|||
} |
|||
} |
|||
@ -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<AIServiceMigrationsDbContext> |
|||
{ |
|||
public AIServiceMigrationsDbContext CreateDbContext(string[] args) |
|||
{ |
|||
var configuration = BuildConfiguration(); |
|||
var connectionString = configuration.GetConnectionString("Default"); |
|||
|
|||
var builder = new DbContextOptionsBuilder<AIServiceMigrationsDbContext>() |
|||
.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(); |
|||
} |
|||
} |
|||
@ -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<AIServiceMigrationsDbContext>(); |
|||
|
|||
Configure<AbpDbContextOptions>(options => |
|||
{ |
|||
options.UseNpgsql(); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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,35 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<IsPackable>false</IsPackable> |
|||
<TargetFramework>net10.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace>LINGYUN.Abp.MicroService.AIService</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools"> |
|||
<PrivateAssets>all</PrivateAssets> |
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> |
|||
</PackageReference> |
|||
<PackageReference Include="Volo.Abp.EntityFrameworkCore.PostgreSql" /> |
|||
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" /> |
|||
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" /> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AIManagement.EntityFrameworkCore\LINGYUN.Abp.AIManagement.EntityFrameworkCore.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\framework\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj" /> |
|||
<ProjectReference Include="..\..\modules\localization-management\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\modules\saas\LINGYUN.Abp.Saas.EntityFrameworkCore\LINGYUN.Abp.Saas.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\modules\text-templating\LINGYUN.Abp.TextTemplating.EntityFrameworkCore\LINGYUN.Abp.TextTemplating.EntityFrameworkCore.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,303 @@ |
|||
// <auto-generated />
|
|||
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 |
|||
{ |
|||
/// <inheritdoc />
|
|||
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<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<DateTime>("CreatedAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<DateTime>("ExpiredAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<string>("Name") |
|||
.IsRequired() |
|||
.HasMaxLength(50) |
|||
.HasColumnType("character varying(50)"); |
|||
|
|||
b.Property<Guid?>("TenantId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("TenantId"); |
|||
|
|||
b.Property<DateTime?>("UpdateAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.HasKey("Id"); |
|||
|
|||
b.ToTable("AbpAIConversations", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("LINGYUN.Abp.AIManagement.Chats.TextChatMessageRecord", b => |
|||
{ |
|||
b.Property<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<string>("ConcurrencyStamp") |
|||
.IsConcurrencyToken() |
|||
.IsRequired() |
|||
.HasMaxLength(40) |
|||
.HasColumnType("character varying(40)") |
|||
.HasColumnName("ConcurrencyStamp"); |
|||
|
|||
b.Property<string>("Content") |
|||
.IsRequired() |
|||
.HasMaxLength(1024) |
|||
.HasColumnType("character varying(1024)"); |
|||
|
|||
b.Property<Guid?>("ConversationId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<DateTime>("CreatedAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<string>("ExtraProperties") |
|||
.IsRequired() |
|||
.HasColumnType("text") |
|||
.HasColumnName("ExtraProperties"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<DateTime?>("ReplyAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("ReplyMessage") |
|||
.HasColumnType("text"); |
|||
|
|||
b.Property<string>("Role") |
|||
.IsRequired() |
|||
.HasMaxLength(20) |
|||
.HasColumnType("character varying(20)"); |
|||
|
|||
b.Property<Guid?>("TenantId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("TenantId"); |
|||
|
|||
b.Property<Guid?>("UserId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<string>("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<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<long?>("CachedInputTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<Guid?>("ConversationId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<long?>("InputTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<Guid?>("MessageId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<long?>("OutputTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<long?>("ReasoningTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<Guid?>("TenantId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("TenantId"); |
|||
|
|||
b.Property<long?>("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<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<string>("ApiBaseUrl") |
|||
.HasMaxLength(128) |
|||
.HasColumnType("character varying(128)"); |
|||
|
|||
b.Property<string>("ApiKey") |
|||
.HasMaxLength(64) |
|||
.HasColumnType("character varying(64)"); |
|||
|
|||
b.Property<string>("ConcurrencyStamp") |
|||
.IsConcurrencyToken() |
|||
.IsRequired() |
|||
.HasMaxLength(40) |
|||
.HasColumnType("character varying(40)") |
|||
.HasColumnName("ConcurrencyStamp"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<string>("Description") |
|||
.HasMaxLength(128) |
|||
.HasColumnType("character varying(128)"); |
|||
|
|||
b.Property<string>("DisplayName") |
|||
.IsRequired() |
|||
.HasMaxLength(128) |
|||
.HasColumnType("character varying(128)"); |
|||
|
|||
b.Property<string>("ExtraProperties") |
|||
.IsRequired() |
|||
.HasColumnType("text") |
|||
.HasColumnName("ExtraProperties"); |
|||
|
|||
b.Property<float?>("FrequencyPenalty") |
|||
.HasColumnType("real"); |
|||
|
|||
b.Property<string>("Instructions") |
|||
.HasMaxLength(512) |
|||
.HasColumnType("character varying(512)"); |
|||
|
|||
b.Property<bool>("IsEnabled") |
|||
.HasColumnType("boolean"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<int?>("MaxOutputTokens") |
|||
.HasColumnType("integer"); |
|||
|
|||
b.Property<string>("ModelName") |
|||
.IsRequired() |
|||
.HasMaxLength(64) |
|||
.HasColumnType("character varying(64)"); |
|||
|
|||
b.Property<string>("Name") |
|||
.IsRequired() |
|||
.HasMaxLength(64) |
|||
.HasColumnType("character varying(64)"); |
|||
|
|||
b.Property<float?>("PresencePenalty") |
|||
.HasColumnType("real"); |
|||
|
|||
b.Property<string>("Provider") |
|||
.IsRequired() |
|||
.HasMaxLength(20) |
|||
.HasColumnType("character varying(20)"); |
|||
|
|||
b.Property<string>("StateCheckers") |
|||
.HasMaxLength(256) |
|||
.HasColumnType("character varying(256)"); |
|||
|
|||
b.Property<string>("SystemPrompt") |
|||
.HasMaxLength(512) |
|||
.HasColumnType("character varying(512)"); |
|||
|
|||
b.Property<float?>("Temperature") |
|||
.HasColumnType("real"); |
|||
|
|||
b.HasKey("Id"); |
|||
|
|||
b.HasIndex("Name") |
|||
.IsUnique(); |
|||
|
|||
b.ToTable("AbpAIWorkspaceDefinitions", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace LINGYUN.Abp.MicroService.AIService.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class Initial_AI_Service : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: "AbpAIConversations", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uuid", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false), |
|||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
ExpiredAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
UpdateAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uuid", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpAIConversations", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "AbpAITextChatMessages", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uuid", nullable: false), |
|||
Content = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false), |
|||
ExtraProperties = table.Column<string>(type: "text", nullable: false), |
|||
ConcurrencyStamp = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false), |
|||
CreationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
TenantId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
Workspace = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), |
|||
Role = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false), |
|||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
UserId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
ConversationId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
ReplyMessage = table.Column<string>(type: "text", nullable: true), |
|||
ReplyAt = table.Column<DateTime>(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<Guid>(type: "uuid", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
MessageId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
ConversationId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
InputTokenCount = table.Column<long>(type: "bigint", nullable: true), |
|||
OutputTokenCount = table.Column<long>(type: "bigint", nullable: true), |
|||
TotalTokenCount = table.Column<long>(type: "bigint", nullable: true), |
|||
CachedInputTokenCount = table.Column<long>(type: "bigint", nullable: true), |
|||
ReasoningTokenCount = table.Column<long>(type: "bigint", nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uuid", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpAITokenUsages", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "AbpAIWorkspaceDefinitions", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uuid", nullable: false), |
|||
Name = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), |
|||
Provider = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false), |
|||
ModelName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), |
|||
DisplayName = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false), |
|||
Description = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true), |
|||
ApiKey = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true), |
|||
ApiBaseUrl = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true), |
|||
SystemPrompt = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true), |
|||
Instructions = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true), |
|||
Temperature = table.Column<float>(type: "real", nullable: true), |
|||
MaxOutputTokens = table.Column<int>(type: "integer", nullable: true), |
|||
FrequencyPenalty = table.Column<float>(type: "real", nullable: true), |
|||
PresencePenalty = table.Column<float>(type: "real", nullable: true), |
|||
IsEnabled = table.Column<bool>(type: "boolean", nullable: false), |
|||
StateCheckers = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "text", nullable: false), |
|||
ConcurrencyStamp = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false), |
|||
CreationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uuid", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: true), |
|||
LastModifierId = table.Column<Guid>(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); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "AbpAIConversations"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: "AbpAITextChatMessages"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: "AbpAITokenUsages"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: "AbpAIWorkspaceDefinitions"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,300 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using LINGYUN.Abp.MicroService.AIService; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
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))] |
|||
partial class AIServiceMigrationsDbContextModelSnapshot : ModelSnapshot |
|||
{ |
|||
protected override void BuildModel(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<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<DateTime>("CreatedAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<DateTime>("ExpiredAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<string>("Name") |
|||
.IsRequired() |
|||
.HasMaxLength(50) |
|||
.HasColumnType("character varying(50)"); |
|||
|
|||
b.Property<Guid?>("TenantId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("TenantId"); |
|||
|
|||
b.Property<DateTime?>("UpdateAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.HasKey("Id"); |
|||
|
|||
b.ToTable("AbpAIConversations", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("LINGYUN.Abp.AIManagement.Chats.TextChatMessageRecord", b => |
|||
{ |
|||
b.Property<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<string>("ConcurrencyStamp") |
|||
.IsConcurrencyToken() |
|||
.IsRequired() |
|||
.HasMaxLength(40) |
|||
.HasColumnType("character varying(40)") |
|||
.HasColumnName("ConcurrencyStamp"); |
|||
|
|||
b.Property<string>("Content") |
|||
.IsRequired() |
|||
.HasMaxLength(1024) |
|||
.HasColumnType("character varying(1024)"); |
|||
|
|||
b.Property<Guid?>("ConversationId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<DateTime>("CreatedAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<string>("ExtraProperties") |
|||
.IsRequired() |
|||
.HasColumnType("text") |
|||
.HasColumnName("ExtraProperties"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<DateTime?>("ReplyAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("ReplyMessage") |
|||
.HasColumnType("text"); |
|||
|
|||
b.Property<string>("Role") |
|||
.IsRequired() |
|||
.HasMaxLength(20) |
|||
.HasColumnType("character varying(20)"); |
|||
|
|||
b.Property<Guid?>("TenantId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("TenantId"); |
|||
|
|||
b.Property<Guid?>("UserId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<string>("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<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<long?>("CachedInputTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<Guid?>("ConversationId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<long?>("InputTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<Guid?>("MessageId") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<long?>("OutputTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<long?>("ReasoningTokenCount") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.Property<Guid?>("TenantId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("TenantId"); |
|||
|
|||
b.Property<long?>("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<Guid>("Id") |
|||
.HasColumnType("uuid"); |
|||
|
|||
b.Property<string>("ApiBaseUrl") |
|||
.HasMaxLength(128) |
|||
.HasColumnType("character varying(128)"); |
|||
|
|||
b.Property<string>("ApiKey") |
|||
.HasMaxLength(64) |
|||
.HasColumnType("character varying(64)"); |
|||
|
|||
b.Property<string>("ConcurrencyStamp") |
|||
.IsConcurrencyToken() |
|||
.IsRequired() |
|||
.HasMaxLength(40) |
|||
.HasColumnType("character varying(40)") |
|||
.HasColumnName("ConcurrencyStamp"); |
|||
|
|||
b.Property<DateTime>("CreationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("CreationTime"); |
|||
|
|||
b.Property<Guid?>("CreatorId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("CreatorId"); |
|||
|
|||
b.Property<string>("Description") |
|||
.HasMaxLength(128) |
|||
.HasColumnType("character varying(128)"); |
|||
|
|||
b.Property<string>("DisplayName") |
|||
.IsRequired() |
|||
.HasMaxLength(128) |
|||
.HasColumnType("character varying(128)"); |
|||
|
|||
b.Property<string>("ExtraProperties") |
|||
.IsRequired() |
|||
.HasColumnType("text") |
|||
.HasColumnName("ExtraProperties"); |
|||
|
|||
b.Property<float?>("FrequencyPenalty") |
|||
.HasColumnType("real"); |
|||
|
|||
b.Property<string>("Instructions") |
|||
.HasMaxLength(512) |
|||
.HasColumnType("character varying(512)"); |
|||
|
|||
b.Property<bool>("IsEnabled") |
|||
.HasColumnType("boolean"); |
|||
|
|||
b.Property<DateTime?>("LastModificationTime") |
|||
.HasColumnType("timestamp with time zone") |
|||
.HasColumnName("LastModificationTime"); |
|||
|
|||
b.Property<Guid?>("LastModifierId") |
|||
.HasColumnType("uuid") |
|||
.HasColumnName("LastModifierId"); |
|||
|
|||
b.Property<int?>("MaxOutputTokens") |
|||
.HasColumnType("integer"); |
|||
|
|||
b.Property<string>("ModelName") |
|||
.IsRequired() |
|||
.HasMaxLength(64) |
|||
.HasColumnType("character varying(64)"); |
|||
|
|||
b.Property<string>("Name") |
|||
.IsRequired() |
|||
.HasMaxLength(64) |
|||
.HasColumnType("character varying(64)"); |
|||
|
|||
b.Property<float?>("PresencePenalty") |
|||
.HasColumnType("real"); |
|||
|
|||
b.Property<string>("Provider") |
|||
.IsRequired() |
|||
.HasMaxLength(20) |
|||
.HasColumnType("character varying(20)"); |
|||
|
|||
b.Property<string>("StateCheckers") |
|||
.HasMaxLength(256) |
|||
.HasColumnType("character varying(256)"); |
|||
|
|||
b.Property<string>("SystemPrompt") |
|||
.HasMaxLength(512) |
|||
.HasColumnType("character varying(512)"); |
|||
|
|||
b.Property<float?>("Temperature") |
|||
.HasColumnType("real"); |
|||
|
|||
b.HasKey("Id"); |
|||
|
|||
b.HasIndex("Name") |
|||
.IsUnique(); |
|||
|
|||
b.ToTable("AbpAIWorkspaceDefinitions", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,423 @@ |
|||
using DotNetCore.CAP; |
|||
using LINGYUN.Abp.AIManagement; |
|||
using LINGYUN.Abp.AIManagement.Chats; |
|||
using LINGYUN.Abp.Localization.CultureMap; |
|||
using LINGYUN.Abp.LocalizationManagement; |
|||
using LINGYUN.Abp.Serilog.Enrichers.UniqueId; |
|||
using LINGYUN.Abp.TextTemplating; |
|||
using LINGYUN.Abp.Wrapper; |
|||
using Medallion.Threading; |
|||
using Medallion.Threading.Redis; |
|||
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|||
using Microsoft.AspNetCore.Cors; |
|||
using Microsoft.AspNetCore.DataProtection; |
|||
using Microsoft.Extensions.Caching.StackExchangeRedis; |
|||
using Microsoft.IdentityModel.Logging; |
|||
using Microsoft.IdentityModel.Tokens; |
|||
using Microsoft.OpenApi.Models; |
|||
using StackExchange.Redis; |
|||
using System.Text.Encodings.Web; |
|||
using System.Text.Unicode; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.AntiForgery; |
|||
using Volo.Abp.Auditing; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Domain.Entities.Events.Distributed; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Identity.Localization; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Security.Claims; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Timing; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.MicroService.AIService; |
|||
|
|||
public partial class AIServiceModule |
|||
{ |
|||
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); |
|||
|
|||
private void PreConfigureFeature() |
|||
{ |
|||
OneTimeRunner.Run(() => |
|||
{ |
|||
GlobalFeatureManager.Instance.Modules.Editions().EnableAll(); |
|||
}); |
|||
} |
|||
|
|||
private void PreConfigureApp(IConfiguration configuration) |
|||
{ |
|||
PreConfigure<AbpSerilogEnrichersUniqueIdOptions>(options => |
|||
{ |
|||
// 以开放端口区别,应在0-31之间
|
|||
options.SnowflakeIdOptions.WorkerId = 19; |
|||
options.SnowflakeIdOptions.WorkerIdBits = 5; |
|||
options.SnowflakeIdOptions.DatacenterId = 1; |
|||
}); |
|||
|
|||
if (configuration.GetValue<bool>("App:ShowPii")) |
|||
{ |
|||
IdentityModelEventSource.ShowPII = true; |
|||
} |
|||
} |
|||
|
|||
private void PreConfigureCAP(IConfiguration configuration) |
|||
{ |
|||
PreConfigure<CapOptions>(options => |
|||
{ |
|||
options |
|||
.UsePostgreSql(mySqlOptions => |
|||
{ |
|||
configuration.GetSection("CAP:PostgreSql").Bind(mySqlOptions); |
|||
}) |
|||
.UseRabbitMQ(rabbitMQOptions => |
|||
{ |
|||
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); |
|||
}) |
|||
.UseDashboard(); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureTextTemplating() |
|||
{ |
|||
Configure<AbpTextTemplatingCachingOptions>(options => |
|||
{ |
|||
options.IsDynamicTemplateDefinitionStoreEnabled = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureFeatureManagement() |
|||
{ |
|||
Configure<FeatureManagementOptions>(options => |
|||
{ |
|||
options.IsDynamicFeatureStoreEnabled = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureJsonSerializer(IConfiguration configuration) |
|||
{ |
|||
// 统一时间日期格式
|
|||
Configure<AbpJsonOptions>(options => |
|||
{ |
|||
var jsonConfiguration = configuration.GetSection("Json"); |
|||
if (jsonConfiguration.Exists()) |
|||
{ |
|||
jsonConfiguration.Bind(options); |
|||
} |
|||
}); |
|||
// 中文序列化的编码问题
|
|||
Configure<AbpSystemTextJsonSerializerOptions>(options => |
|||
{ |
|||
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAIManagement() |
|||
{ |
|||
Configure<AIManagementOptions>(options => |
|||
{ |
|||
options.IsDynamicWorkspaceStoreEnabled = true; |
|||
options.SaveStaticWorkspacesToDatabase = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigurePermissionManagement() |
|||
{ |
|||
Configure<PermissionManagementOptions>(options => |
|||
{ |
|||
options.IsDynamicPermissionStoreEnabled = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureSettingManagement() |
|||
{ |
|||
Configure<SettingManagementOptions>(options => |
|||
{ |
|||
options.IsDynamicSettingStoreEnabled = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureTiming(IConfiguration configuration) |
|||
{ |
|||
Configure<AbpClockOptions>(options => |
|||
{ |
|||
configuration.GetSection("Clock").Bind(options); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureCaching(IConfiguration configuration) |
|||
{ |
|||
Configure<AbpDistributedCacheOptions>(options => |
|||
{ |
|||
configuration.GetSection("DistributedCache").Bind(options); |
|||
}); |
|||
|
|||
Configure<AbpDistributedEntityEventOptions>(options => |
|||
{ |
|||
options.AutoEventSelectors.AddNamespace("Volo.Abp.TenantManagement"); |
|||
}); |
|||
|
|||
Configure<RedisCacheOptions>(options => |
|||
{ |
|||
var redisConfig = ConfigurationOptions.Parse(options.Configuration!); |
|||
options.ConfigurationOptions = redisConfig; |
|||
options.InstanceName = configuration["Redis:InstanceName"]; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureDistributedLocking(IServiceCollection services, IConfiguration configuration) |
|||
{ |
|||
var distributedLockEnabled = configuration["DistributedLock:IsEnabled"]; |
|||
if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled)) |
|||
{ |
|||
services.AddSingleton<IDistributedLockProvider>(sp => |
|||
{ |
|||
var connectionMultiplexer = sp.GetRequiredService<IConnectionMultiplexer>(); |
|||
return new RedisDistributedSynchronizationProvider(connectionMultiplexer.GetDatabase()); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private void ConfigureMvc(IServiceCollection services, IConfiguration configuration) |
|||
{ |
|||
Configure<AbpAspNetCoreMvcOptions>(options => |
|||
{ |
|||
options.ExposeIntegrationServices = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureVirtualFileSystem() |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AIServiceModule>("LINGYUN.Abp.MicroService.AIService"); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureMultiTenancy(IConfiguration configuration) |
|||
{ |
|||
// 多租户
|
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = true; |
|||
}); |
|||
|
|||
var tenantResolveCfg = configuration.GetSection("App:Domains"); |
|||
if (tenantResolveCfg.Exists()) |
|||
{ |
|||
Configure<AbpTenantResolveOptions>(options => |
|||
{ |
|||
var domains = tenantResolveCfg.Get<string[]>() ?? []; |
|||
foreach (var domain in domains) |
|||
{ |
|||
options.AddDomainTenantResolver(domain); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private void ConfigureIdentity(IConfiguration configuration) |
|||
{ |
|||
Configure<AbpClaimsPrincipalFactoryOptions>(options => |
|||
{ |
|||
options.IsDynamicClaimsEnabled = true; |
|||
options.RemoteRefreshUrl = configuration["App:RefreshClaimsUrl"] + options.RemoteRefreshUrl; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureAuditing(IConfiguration configuration) |
|||
{ |
|||
Configure<AbpAuditingOptions>(options => |
|||
{ |
|||
// 是否启用实体变更记录
|
|||
var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"]; |
|||
if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() || |
|||
(bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled)) |
|||
{ |
|||
options.EntityHistorySelectors.AddAllEntities(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureSwagger(IServiceCollection services, IConfiguration configuration) |
|||
{ |
|||
// Swagger
|
|||
services.AddAbpSwaggerGenWithOAuth( |
|||
configuration["AuthServer:Authority"]!, |
|||
new Dictionary<string, string> |
|||
{ |
|||
{ "AIService", "AI Service API"} |
|||
}, |
|||
options => |
|||
{ |
|||
options.SwaggerDoc("v1", new OpenApiInfo |
|||
{ |
|||
Title = "AI Service API", Version = "v1", |
|||
Contact = new OpenApiContact |
|||
{ |
|||
Name = "colin", |
|||
Email = "colin.in@foxmail.com", |
|||
Url = new Uri("https://github.com/colinin") |
|||
}, |
|||
License = new OpenApiLicense |
|||
{ |
|||
Name = "MIT", |
|||
Url = new Uri("https://github.com/colinin/abp-next-admin/blob/master/LICENSE") |
|||
} |
|||
}); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.CustomSchemaIds(type => type.FullName); |
|||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme |
|||
{ |
|||
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", |
|||
Name = "Authorization", |
|||
In = ParameterLocation.Header, |
|||
Scheme = "bearer", |
|||
Type = SecuritySchemeType.Http, |
|||
BearerFormat = "JWT" |
|||
}); |
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
{ |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
{ |
|||
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } |
|||
}, |
|||
new string[] { } |
|||
} |
|||
}); |
|||
options.OperationFilter<TenantHeaderParamter>(); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureLocalization() |
|||
{ |
|||
// 支持本地化语言类型
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Languages.Add(new LanguageInfo("en", "en", "English")); |
|||
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); |
|||
|
|||
options.Resources |
|||
.Get<IdentityResource>() |
|||
.AddVirtualJson("/Localization/Resources"); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationCultureMapOptions>(options => |
|||
{ |
|||
var zhHansCultureMapInfo = new CultureMapInfo |
|||
{ |
|||
TargetCulture = "zh-Hans", |
|||
SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" } |
|||
}; |
|||
|
|||
options.CulturesMaps.Add(zhHansCultureMapInfo); |
|||
options.UiCulturesMaps.Add(zhHansCultureMapInfo); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationManagementOptions>(options => |
|||
{ |
|||
options.SaveStaticLocalizationsToDatabase = true; |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureCors(IServiceCollection services, IConfiguration configuration) |
|||
{ |
|||
services.AddCors(options => |
|||
{ |
|||
options.AddDefaultPolicy(builder => |
|||
{ |
|||
var corsOrigins = configuration.GetSection("App:CorsOrigins").Get<List<string>>(); |
|||
if (corsOrigins == null || corsOrigins.Count == 0) |
|||
{ |
|||
corsOrigins = configuration["App:CorsOrigins"]? |
|||
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToList() ?? new List<string>(); |
|||
} |
|||
builder |
|||
.WithOrigins(corsOrigins |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToArray() |
|||
) |
|||
.WithAbpExposedHeaders() |
|||
.WithAbpWrapExposedHeaders() |
|||
.SetIsOriginAllowedToAllowWildcardSubdomains() |
|||
.AllowAnyHeader() |
|||
.AllowAnyMethod() |
|||
.AllowCredentials(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) |
|||
{ |
|||
Configure<AbpAntiForgeryOptions>(options => |
|||
{ |
|||
options.TokenCookie.HttpOnly = false; |
|||
options.TokenCookie.SameSite = SameSiteMode.Lax; |
|||
}); |
|||
|
|||
services.AddAlwaysAllowAuthorization(); |
|||
services.AddAlwaysAllowSession(); |
|||
|
|||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |
|||
.AddAbpJwtBearer(options => |
|||
{ |
|||
configuration.GetSection("AuthServer").Bind(options); |
|||
|
|||
var validIssuers = configuration.GetSection("AuthServer:ValidIssuers").Get<List<string>>(); |
|||
if (validIssuers?.Count > 0) |
|||
{ |
|||
options.TokenValidationParameters.ValidIssuers = validIssuers; |
|||
options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; |
|||
} |
|||
var validAudiences = configuration.GetSection("AuthServer:ValidAudiences").Get<List<string>>(); |
|||
if (validAudiences?.Count > 0) |
|||
{ |
|||
options.TokenValidationParameters.ValidAudiences = validAudiences; |
|||
} |
|||
}); |
|||
|
|||
services |
|||
.AddDataProtection() |
|||
.SetApplicationName("LINGYUN.Abp.Application") |
|||
.PersistKeysToStackExchangeRedis(() => |
|||
{ |
|||
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); |
|||
|
|||
return redis.GetDatabase(); |
|||
}, |
|||
"LINGYUN.Abp.Application:DataProtection:Protection-Keys"); |
|||
} |
|||
|
|||
private void ConfigureWrapper() |
|||
{ |
|||
Configure<AbpWrapperOptions>(options => |
|||
{ |
|||
options.IsEnabled = true; |
|||
|
|||
options.IgnoreControllers.Add<ChatController>(); |
|||
}); |
|||
} |
|||
|
|||
private void PreConfigureWrapper() |
|||
{ |
|||
// 服务间调用不包装
|
|||
PreConfigure<AbpHttpClientBuilderOptions>(options => |
|||
{ |
|||
options.ProxyClientActions.Add( |
|||
(_, _, client) => |
|||
{ |
|||
client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true"); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
using LINGYUN.Abp.AIManagement; |
|||
using LINGYUN.Abp.AspNetCore.HttpOverrides; |
|||
using LINGYUN.Abp.AspNetCore.Mvc.Localization; |
|||
using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; |
|||
using LINGYUN.Abp.AuditLogging.Elasticsearch; |
|||
using LINGYUN.Abp.Claims.Mapping; |
|||
using LINGYUN.Abp.Data.DbMigrator; |
|||
using LINGYUN.Abp.Emailing.Platform; |
|||
using LINGYUN.Abp.EventBus.CAP; |
|||
using LINGYUN.Abp.ExceptionHandling.Emailing; |
|||
using LINGYUN.Abp.Identity.Session.AspNetCore; |
|||
using LINGYUN.Abp.Localization.CultureMap; |
|||
using LINGYUN.Abp.Logging.Serilog.Elasticsearch; |
|||
using LINGYUN.Abp.Serilog.Enrichers.Application; |
|||
using LINGYUN.Abp.Serilog.Enrichers.UniqueId; |
|||
using LINGYUN.Abp.Sms.Platform; |
|||
using LINGYUN.Abp.TextTemplating.Scriban; |
|||
using Volo.Abp.AspNetCore.Authentication.JwtBearer; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; |
|||
using Volo.Abp.AspNetCore.Serilog; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.Caching.StackExchangeRedis; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.PermissionManagement.Identity; |
|||
using Volo.Abp.PermissionManagement.OpenIddict; |
|||
using Volo.Abp.Swashbuckle; |
|||
|
|||
namespace LINGYUN.Abp.MicroService.AIService; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpCAPEventBusModule), |
|||
typeof(AbpSerilogEnrichersApplicationModule), |
|||
typeof(AbpSerilogEnrichersUniqueIdModule), |
|||
typeof(AbpAspNetCoreSerilogModule), |
|||
typeof(AbpLoggingSerilogElasticsearchModule), |
|||
typeof(AbpAuditLoggingElasticsearchModule), |
|||
typeof(AbpAspNetCoreMvcUiMultiTenancyModule), |
|||
typeof(AbpAspNetCoreMvcLocalizationModule), |
|||
|
|||
typeof(AbpPermissionManagementDomainIdentityModule), |
|||
typeof(AbpPermissionManagementDomainOpenIddictModule), |
|||
|
|||
// 重写模板引擎支持外部本地化
|
|||
typeof(AbpTextTemplatingScribanModule), |
|||
|
|||
typeof(AbpIdentitySessionAspNetCoreModule), |
|||
|
|||
typeof(AbpAIManagementApplicationModule), |
|||
typeof(AbpAIManagementHttpApiModule), |
|||
typeof(AIServiceMigrationsEntityFrameworkCoreModule), |
|||
typeof(AbpDataDbMigratorModule), |
|||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), |
|||
typeof(AbpEmailingExceptionHandlingModule), |
|||
typeof(AbpHttpClientModule), |
|||
typeof(AbpSmsPlatformModule), |
|||
typeof(AbpEmailingPlatformModule), |
|||
typeof(AbpCachingStackExchangeRedisModule), |
|||
typeof(AbpLocalizationCultureMapModule), |
|||
typeof(AbpAspNetCoreMvcWrapperModule), |
|||
typeof(AbpAspNetCoreHttpOverridesModule), |
|||
typeof(AbpClaimsMappingModule), |
|||
typeof(AbpSwashbuckleModule), |
|||
typeof(AbpAutofacModule) |
|||
)] |
|||
public partial class AIServiceModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
PreConfigureWrapper(); |
|||
PreConfigureFeature(); |
|||
PreConfigureApp(configuration); |
|||
PreConfigureCAP(configuration); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
ConfigureWrapper(); |
|||
ConfigureLocalization(); |
|||
ConfigureVirtualFileSystem(); |
|||
ConfigureTextTemplating(); |
|||
ConfigureAIManagement(); |
|||
ConfigureSettingManagement(); |
|||
ConfigureFeatureManagement(); |
|||
ConfigurePermissionManagement(); |
|||
ConfigureIdentity(configuration); |
|||
ConfigureTiming(configuration); |
|||
ConfigureCaching(configuration); |
|||
ConfigureAuditing(configuration); |
|||
ConfigureMultiTenancy(configuration); |
|||
ConfigureJsonSerializer(configuration); |
|||
ConfigureMvc(context.Services, configuration); |
|||
ConfigureCors(context.Services, configuration); |
|||
ConfigureSwagger(context.Services, configuration); |
|||
ConfigureDistributedLocking(context.Services, configuration); |
|||
ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,71 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net10.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<RootNamespace>LINGYUN.Abp.MicroService.AIService</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="AgileConfig.Client" /> |
|||
<PackageReference Include="DotNetCore.CAP.Dashboard" /> |
|||
<PackageReference Include="DotNetCore.CAP.PostgreSql" /> |
|||
<PackageReference Include="DotNetCore.CAP.RabbitMQ" /> |
|||
<PackageReference Include="DistributedLock.Redis" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" /> |
|||
<PackageReference Include="Serilog.AspNetCore" /> |
|||
<PackageReference Include="Serilog.Enrichers.Environment" /> |
|||
<PackageReference Include="Serilog.Enrichers.Assembly" /> |
|||
<PackageReference Include="Serilog.Enrichers.Process" /> |
|||
<PackageReference Include="Serilog.Enrichers.Thread" /> |
|||
<PackageReference Include="Serilog.Settings.Configuration" /> |
|||
<PackageReference Include="Serilog.Sinks.Async" /> |
|||
<PackageReference Include="Serilog.Sinks.Elasticsearch" /> |
|||
<PackageReference Include="Serilog.Sinks.File" /> |
|||
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" /> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" /> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" /> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" /> |
|||
<PackageReference Include="Volo.Abp.Autofac" /> |
|||
<PackageReference Include="Volo.Abp.FeatureManagement.Application" /> |
|||
<PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" /> |
|||
<PackageReference Include="Volo.Abp.Http.Client" /> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.Application" /> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Identity" /> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" /> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" /> |
|||
<PackageReference Include="Volo.Abp.Swashbuckle" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\framework\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj" /> |
|||
<ProjectReference Include="..\..\framework\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" /> |
|||
<ProjectReference Include="..\..\framework\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj" /> |
|||
<ProjectReference Include="..\..\framework\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" /> |
|||
<ProjectReference Include="..\..\framework\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj" /> |
|||
<ProjectReference Include="..\..\framework\features\LINGYUN.Abp.FeatureManagement.Client\LINGYUN.Abp.FeatureManagement.Client.csproj" /> |
|||
<ProjectReference Include="..\..\framework\localization\LINGYUN.Abp.AspNetCore.Mvc.Localization\LINGYUN.Abp.AspNetCore.Mvc.Localization.csproj" /> |
|||
<ProjectReference Include="..\..\framework\localization\LINGYUN.Abp.Localization.CultureMap\LINGYUN.Abp.Localization.CultureMap.csproj" /> |
|||
<ProjectReference Include="..\..\framework\logging\LINGYUN.Abp.Logging.Serilog.Elasticsearch\LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj" /> |
|||
<ProjectReference Include="..\..\framework\logging\LINGYUN.Abp.Serilog.Enrichers.Application\LINGYUN.Abp.Serilog.Enrichers.Application.csproj" /> |
|||
<ProjectReference Include="..\..\framework\logging\LINGYUN.Abp.Serilog.Enrichers.UniqueId\LINGYUN.Abp.Serilog.Enrichers.UniqueId.csproj" /> |
|||
<ProjectReference Include="..\..\framework\mvc\LINGYUN.Abp.AspNetCore.Mvc.Wrapper\LINGYUN.Abp.AspNetCore.Mvc.Wrapper.csproj" /> |
|||
<ProjectReference Include="..\..\framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore\LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj" /> |
|||
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AIManagement.Application\LINGYUN.Abp.AIManagement.Application.csproj" /> |
|||
<ProjectReference Include="..\..\modules\ai\LINGYUN.Abp.AIManagement.HttpApi\LINGYUN.Abp.AIManagement.HttpApi.csproj" /> |
|||
<ProjectReference Include="..\..\modules\identity\LINGYUN.Abp.Identity.Session.AspNetCore\LINGYUN.Abp.Identity.Session.AspNetCore.csproj" /> |
|||
<ProjectReference Include="..\..\modules\platform\LINGYUN.Abp.Emailing.Platform\LINGYUN.Abp.Emailing.Platform.csproj" /> |
|||
<ProjectReference Include="..\..\modules\platform\LINGYUN.Abp.Sms.Platform\LINGYUN.Abp.Sms.Platform.csproj" /> |
|||
<ProjectReference Include="..\..\modules\text-templating\LINGYUN.Abp.TextTemplating.Scriban\LINGYUN.Abp.TextTemplating.Scriban.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.MicroService.ServiceDefaults\LINGYUN.Abp.MicroService.ServiceDefaults.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,99 @@ |
|||
using LINGYUN.Abp.Identity.Session.AspNetCore; |
|||
using LINGYUN.Abp.MicroService.AIService; |
|||
using LINGYUN.Abp.Serilog.Enrichers.Application; |
|||
using Serilog; |
|||
using Volo.Abp.IO; |
|||
using Volo.Abp.Modularity.PlugIns; |
|||
|
|||
Log.Information("Starting AIService Host..."); |
|||
|
|||
try |
|||
{ |
|||
var builder = WebApplication.CreateBuilder(args); |
|||
builder.Host.AddAppSettingsSecretsJson() |
|||
.UseAutofac() |
|||
.ConfigureAppConfiguration((context, config) => |
|||
{ |
|||
if (context.Configuration.GetValue("AgileConfig:IsEnabled", false)) |
|||
{ |
|||
config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); |
|||
} |
|||
}) |
|||
.UseSerilog((context, provider, config) => |
|||
{ |
|||
config.ReadFrom.Configuration(context.Configuration); |
|||
}); |
|||
|
|||
builder.AddServiceDefaults(); |
|||
|
|||
await builder.AddApplicationAsync<AIServiceModule>(options => |
|||
{ |
|||
var applicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME") ?? "AIService"; |
|||
options.ApplicationName = applicationName; |
|||
AbpSerilogEnrichersConsts.ApplicationName = applicationName; |
|||
|
|||
var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); |
|||
DirectoryHelper.CreateIfNotExists(pluginFolder); |
|||
options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); |
|||
}); |
|||
|
|||
var app = builder.Build(); |
|||
|
|||
await app.InitializeApplicationAsync(); |
|||
|
|||
app.MapDefaultEndpoints(); |
|||
|
|||
app.UseForwardedHeaders(); |
|||
// 本地化
|
|||
app.UseMapRequestLocalization(); |
|||
// http调用链
|
|||
app.UseCorrelationId(); |
|||
// 文件系统
|
|||
app.MapAbpStaticAssets(); |
|||
// 路由
|
|||
app.UseRouting(); |
|||
// 跨域
|
|||
app.UseCors(); |
|||
// 认证
|
|||
app.UseAuthentication(); |
|||
app.UseJwtTokenMiddleware(); |
|||
// 多租户
|
|||
app.UseMultiTenancy(); |
|||
// 会话
|
|||
app.UseAbpSession(); |
|||
// jwt
|
|||
app.UseDynamicClaims(); |
|||
// 授权
|
|||
app.UseAuthorization(); |
|||
// Swagger
|
|||
app.UseSwagger(); |
|||
// Swagger可视化界面
|
|||
app.UseAbpSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support AI Service API"); |
|||
|
|||
var configuration = app.Configuration; |
|||
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); |
|||
options.OAuthScopes(configuration["AuthServer:Audience"]); |
|||
}); |
|||
// 审计日志
|
|||
app.UseAuditing(); |
|||
app.UseAbpSerilogEnrichers(); |
|||
// 路由
|
|||
app.UseConfiguredEndpoints(); |
|||
|
|||
await app.RunAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
if (ex is HostAbortedException) |
|||
{ |
|||
throw; |
|||
} |
|||
|
|||
Log.Fatal(ex, "Host terminated unexpectedly!"); |
|||
} |
|||
finally |
|||
{ |
|||
await Log.CloseAndFlushAsync(); |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
{ |
|||
"profiles": { |
|||
"LINGYUN.Abp.MicroService.AIService": { |
|||
"commandName": "Project", |
|||
"launchBrowser": true, |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
}, |
|||
"applicationUrl": "https://localhost:49787;http://localhost:49788" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using Microsoft.Extensions.Options; |
|||
using Microsoft.OpenApi.Models; |
|||
using Swashbuckle.AspNetCore.SwaggerGen; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.MicroService.AIService; |
|||
|
|||
public class TenantHeaderParamter : IOperationFilter |
|||
{ |
|||
private readonly AbpMultiTenancyOptions _multiTenancyOptions; |
|||
private readonly AbpAspNetCoreMultiTenancyOptions _aspNetCoreMultiTenancyOptions; |
|||
public TenantHeaderParamter( |
|||
IOptions<AbpMultiTenancyOptions> multiTenancyOptions, |
|||
IOptions<AbpAspNetCoreMultiTenancyOptions> aspNetCoreMultiTenancyOptions) |
|||
{ |
|||
_multiTenancyOptions = multiTenancyOptions.Value; |
|||
_aspNetCoreMultiTenancyOptions = aspNetCoreMultiTenancyOptions.Value; |
|||
} |
|||
|
|||
public void Apply(OpenApiOperation operation, OperationFilterContext context) |
|||
{ |
|||
if (_multiTenancyOptions.IsEnabled) |
|||
{ |
|||
operation.Parameters = operation.Parameters ?? new List<OpenApiParameter>(); |
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Name = _aspNetCoreMultiTenancyOptions.TenantKey, |
|||
In = ParameterLocation.Header, |
|||
Description = "Tenant Id in http header", |
|||
Required = false |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
{ |
|||
"App": { |
|||
"ShowPii": true, |
|||
"CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ], |
|||
"RefreshClaimsUrl": "http://localhost:30015" |
|||
}, |
|||
"Auditing": { |
|||
"AllEntitiesSelector": true |
|||
}, |
|||
"DistributedCache": { |
|||
"HideErrors": true, |
|||
"KeyPrefix": "LINGYUN.Abp.Application", |
|||
"GlobalCacheEntryOptions": { |
|||
"SlidingExpiration": "30:00:00", |
|||
"AbsoluteExpirationRelativeToNow": "60:00:00" |
|||
} |
|||
}, |
|||
"ConnectionStrings": { |
|||
"Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" |
|||
}, |
|||
"CAP": { |
|||
"EventBus": { |
|||
"DefaultGroupName": "AIService", |
|||
"Version": "v1", |
|||
"FailedRetryInterval": 300, |
|||
"FailedRetryCount": 10, |
|||
"CollectorCleaningInterval": 3600000 |
|||
}, |
|||
"PostgreSql": { |
|||
"TableNamePrefix": "admin", |
|||
"ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" |
|||
}, |
|||
"RabbitMQ": { |
|||
"HostName": "localhost", |
|||
"Port": 5672, |
|||
"UserName": "admin", |
|||
"Password": "123456", |
|||
"ExchangeName": "LINGYUN.Abp.Application", |
|||
"VirtualHost": "/" |
|||
} |
|||
}, |
|||
"DistributedLock": { |
|||
"IsEnabled": true, |
|||
"Redis": { |
|||
"Configuration": "localhost,defaultDatabase=13" |
|||
} |
|||
}, |
|||
"Redis": { |
|||
"Configuration": "localhost,defaultDatabase=10", |
|||
"InstanceName": "LINGYUN.Abp.Application" |
|||
}, |
|||
"AuthServer": { |
|||
"Authority": "http://localhost:44385/", |
|||
"Audience": "admin-service", |
|||
"ValidAudiences": [ "lingyun-abp-application" ], |
|||
"MapInboundClaims": false, |
|||
"RequireHttpsMetadata": false, |
|||
"SwaggerClientId": "vue-oauth-client" |
|||
}, |
|||
"RemoteServices": { |
|||
"Platform": { |
|||
"BaseUrl": "http://localhost:30025", |
|||
"UseCurrentAccessToken": false |
|||
} |
|||
}, |
|||
"Logging": { |
|||
"Serilog": { |
|||
"Elasticsearch": { |
|||
"IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}" |
|||
} |
|||
} |
|||
}, |
|||
"AuditLogging": { |
|||
"Elasticsearch": { |
|||
"IndexPrefix": "abp.dev.auditing" |
|||
} |
|||
}, |
|||
"Elasticsearch": { |
|||
"NodeUris": "http://elasticsearch" |
|||
}, |
|||
"Serilog": { |
|||
"MinimumLevel": { |
|||
"Default": "Debug", |
|||
"Override": { |
|||
"System": "Warning", |
|||
"Microsoft": "Warning", |
|||
"DotNetCore": "Debug" |
|||
} |
|||
}, |
|||
"WriteTo": [ |
|||
{ |
|||
"Name": "Async", |
|||
"Args": { |
|||
"configure": [ |
|||
{ |
|||
"Name": "Console", |
|||
"Args": { |
|||
"restrictedToMinimumLevel": "Debug", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
}, |
|||
{ |
|||
"Name": "Elasticsearch", |
|||
"Args": { |
|||
"nodeUris": "http://elasticsearch", |
|||
"indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", |
|||
"autoRegisterTemplate": true, |
|||
"autoRegisterTemplateVersion": "ESv7" |
|||
} |
|||
} |
|||
] |
|||
} |
|||
} |
|||
] |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
{ |
|||
"Clock": { |
|||
"Kind": "Local" |
|||
}, |
|||
"Forwarded": { |
|||
"ForwardedHeaders": "XForwardedFor,XForwardedProto" |
|||
}, |
|||
"StringEncryption": { |
|||
"DefaultPassPhrase": "s46c5q55nxpeS8Ra", |
|||
"InitVectorBytes": "s83ng0abvd02js84", |
|||
"DefaultSalt": "sf&5)s3#" |
|||
}, |
|||
"Json": { |
|||
"InputDateTimeFormats": [ |
|||
"yyyy-MM-dd HH:mm:ss", |
|||
"yyyy-MM-ddTHH:mm:ss" |
|||
] |
|||
}, |
|||
"Serilog": { |
|||
"MinimumLevel": { |
|||
"Default": "Information", |
|||
"Override": { |
|||
"System": "Warning", |
|||
"Microsoft": "Warning", |
|||
"DotNetCore": "Information" |
|||
} |
|||
}, |
|||
"Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], |
|||
"WriteTo": [ |
|||
{ |
|||
"Name": "Async", |
|||
"Args": { |
|||
"configure": [ |
|||
{ |
|||
"Name": "Console", |
|||
"Args": { |
|||
"restrictedToMinimumLevel": "Debug", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
}, |
|||
{ |
|||
"Name": "File", |
|||
"Args": { |
|||
"path": "Logs/Debug-.log", |
|||
"restrictedToMinimumLevel": "Debug", |
|||
"rollingInterval": "Day", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
}, |
|||
{ |
|||
"Name": "File", |
|||
"Args": { |
|||
"path": "Logs/Info-.log", |
|||
"restrictedToMinimumLevel": "Information", |
|||
"rollingInterval": "Day", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
}, |
|||
{ |
|||
"Name": "File", |
|||
"Args": { |
|||
"path": "Logs/Warn-.log", |
|||
"restrictedToMinimumLevel": "Warning", |
|||
"rollingInterval": "Day", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
}, |
|||
{ |
|||
"Name": "File", |
|||
"Args": { |
|||
"path": "Logs/Error-.log", |
|||
"restrictedToMinimumLevel": "Error", |
|||
"rollingInterval": "Day", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
}, |
|||
{ |
|||
"Name": "File", |
|||
"Args": { |
|||
"path": "Logs/Fatal-.log", |
|||
"restrictedToMinimumLevel": "Fatal", |
|||
"rollingInterval": "Day", |
|||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
|||
} |
|||
} |
|||
] |
|||
} |
|||
} |
|||
] |
|||
} |
|||
} |
|||
Loading…
Reference in new issue