Browse Source

Merge 4ffa047d72 into 5c395d32a6

pull/1421/merge
yx lin 3 days ago
committed by GitHub
parent
commit
476011b51f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 561
      aspnet-core/LINGYUN.MicroService.Aspire.slnx
  2. 53
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorHostedService.cs
  3. 13
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/AIServiceDbMigratorModule.cs
  4. 3
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/FodyWeavers.xml
  5. 40
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj
  6. 43
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/Program.cs
  7. 5
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/appsettings.json
  8. 26
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDataSeeder.cs
  9. 44
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationEventHandler.cs
  10. 36
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceDbMigrationService.cs
  11. 32
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContext.cs
  12. 28
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsDbContextFactory.cs
  13. 45
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/AIServiceMigrationsEntityFrameworkCoreModule.cs
  14. 3
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xml
  15. 30
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xsd
  16. 35
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj
  17. 303
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.Designer.cs
  18. 148
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.cs
  19. 300
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/AIServiceMigrationsDbContextModelSnapshot.cs
  20. 423
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.Configure.cs
  21. 103
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs
  22. 3
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/FodyWeavers.xml
  23. 71
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/LINGYUN.Abp.MicroService.AIService.csproj
  24. 99
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/Program.cs
  25. 12
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/Properties/launchSettings.json
  26. 35
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/TenantHeaderParamter.cs
  27. 116
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json
  28. 91
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.json
  29. 25
      aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json
  30. 25
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs
  31. 2
      aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/LINGYUN.Abp.MicroService.AppHost.csproj
  32. 1
      aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/LINGYUN.Abp.MicroService.TaskService.csproj
  33. 2
      aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.cs
  34. 110
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentFactory.cs
  35. 157
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentService.cs
  36. 80
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/ChatClientAgentFactory.cs
  37. 6
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IAgentFactory.cs
  38. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IAgentService.cs
  39. 59
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/WorkspaceAIAgent.cs
  40. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN.Abp.AI.Core.csproj
  41. 27
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAICoreModule.cs
  42. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAIErrorCodes.cs
  43. 19
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientProvider.cs
  44. 12
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/IChatMessageStore.cs
  45. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/IConversationStore.cs
  46. 52
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/InMemoryChatMessageStore.cs
  47. 48
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/InMemoryConversationStore.cs
  48. 49
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/ChatClientFactory.cs
  49. 2
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/ChatClientProviderManager.cs
  50. 15
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/DeepSeekChatClientProvider.cs
  51. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/DeepSeekKernelProvider.cs
  52. 47
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/KernelFactory.cs
  53. 2
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/KernelProviderManager.cs
  54. 25
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/OpenAIChatClientProvider.cs
  55. 39
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/OpenAIKernelProvider.cs
  56. 19
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelProvider.cs
  57. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Localization/Resources/en.json
  58. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Localization/Resources/zh-Hans.json
  59. 53
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/ChatMessage.cs
  60. 28
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/Conversation.cs
  61. 13
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/MediaMessage.cs
  62. 25
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/TextChatMessage.cs
  63. 42
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/TokenUsageInfo.cs
  64. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Tokens/ITokenUsageStore.cs
  65. 28
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Tokens/InMemoryTokenUsageStore.cs
  66. 11
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Tools/GlobalFunctions.cs
  67. 86
      aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs
  68. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/FodyWeavers.xml
  69. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/FodyWeavers.xsd
  70. 26
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj
  71. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AIManagementRemoteServiceConsts.cs
  72. 14
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationContractsModule.cs
  73. 14
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ChatMessageDto.cs
  74. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationCreateDto.cs
  75. 14
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationDto.cs
  76. 7
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationGetListInput.cs
  77. 10
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationUpdateDto.cs
  78. 19
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/SendTextChatMessageDto.cs
  79. 8
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/TextChatMessageDto.cs
  80. 9
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/IChatAppService.cs
  81. 14
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/IConversationAppService.cs
  82. 10
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateDto.cs
  83. 47
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs
  84. 39
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs
  85. 14
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordGetListInput.cs
  86. 10
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordUpdateDto.cs
  87. 14
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/IWorkspaceDefinitionAppService.cs
  88. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xml
  89. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xsd
  90. 26
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN.Abp.AIManagement.Application.csproj
  91. 12
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AIManagementApplicationServiceBase.cs
  92. 15
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs
  93. 17
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationModule.cs
  94. 28
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ChatAppService.cs
  95. 82
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ConversationAppService.cs
  96. 152
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs
  97. 3
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/FodyWeavers.xml
  98. 30
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/FodyWeavers.xsd
  99. 26
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN.Abp.AIManagement.Domain.Shared.csproj
  100. 12
      aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/AIManagementErrorCodes.cs

561
aspnet-core/LINGYUN.MicroService.Aspire.slnx

@ -0,0 +1,561 @@
<Solution>
<Folder Name="/.github/" />
<Folder Name="/.github/workflows/">
<File Path="../.github/workflows/build.yml" />
<File Path="../.github/workflows/publish.yml" />
<File Path="../.github/workflows/release.yml" />
</Folder>
<Folder Name="/.Solution Items/">
<File Path="../common.props" />
<File Path="../common.secrets.props" />
<File Path="../configureawait.props" />
<File Path="../Directory.Build.props" />
<File Path="../Directory.Packages.props" />
<File Path="../NuGet.Config" />
<File Path="aspire/.gitignore" />
<File Path="aspire/README.md" />
</Folder>
<Folder Name="/aspire/">
<Project Path="aspire/LINGYUN.Abp.MicroService.AppHost/LINGYUN.Abp.MicroService.AppHost.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.ServiceDefaults/LINGYUN.Abp.MicroService.ServiceDefaults.csproj" />
</Folder>
<Folder Name="/aspire/admin-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.AdminService.DbMigrator/LINGYUN.Abp.MicroService.AdminService.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.AdminService/LINGYUN.Abp.MicroService.AdminService.csproj" />
</Folder>
<Folder Name="/aspire/ai-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj" Id="90b68785-b0e0-457d-ab88-99e80b24bfcc" />
<Project Path="aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj" Id="791ec2ee-7374-4c7d-bfb4-16d2237ec718" />
<Project Path="aspire/LINGYUN.Abp.MicroService.AIService/LINGYUN.Abp.MicroService.AIService.csproj" Id="0f6d76dc-ff49-4bb6-88aa-3f0fc036bc19" />
</Folder>
<Folder Name="/aspire/api-gateway/">
<Project Path="aspire/LINGYUN.Abp.MicroService.ApiGateway/LINGYUN.Abp.MicroService.ApiGateway.csproj" />
</Folder>
<Folder Name="/aspire/auth-server/">
<Project Path="aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/LINGYUN.Abp.MicroService.AuthServer.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj" />
</Folder>
<Folder Name="/aspire/identity-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.IdentityService/LINGYUN.Abp.MicroService.IdentityService.csproj" />
</Folder>
<Folder Name="/aspire/localization-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator/LINGYUN.Abp.MicroService.LocalizationService.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore/LINGYUN.Abp.MicroService.LocalizationService.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.LocalizationService/LINGYUN.Abp.MicroService.LocalizationService.csproj" />
</Folder>
<Folder Name="/aspire/message-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.MessageService.DbMigrator/LINGYUN.Abp.MicroService.MessageService.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj" />
</Folder>
<Folder Name="/aspire/platform-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.PlatformService.DbMigrator/LINGYUN.Abp.MicroService.PlatformService.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj" />
</Folder>
<Folder Name="/aspire/task-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.TaskService.DbMigrator/LINGYUN.Abp.MicroService.TaskService.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.TaskService/LINGYUN.Abp.MicroService.TaskService.csproj" />
</Folder>
<Folder Name="/aspire/webhook-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.WebhookService.DbMigrator/LINGYUN.Abp.MicroService.WebhookService.DbMigrator.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore.csproj" />
<Project Path="aspire/LINGYUN.Abp.MicroService.WebhookService/LINGYUN.Abp.MicroService.WebhookService.csproj" />
</Folder>
<Folder Name="/aspire/wechat-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.WeChatService/LINGYUN.Abp.MicroService.WeChatService.csproj" />
</Folder>
<Folder Name="/aspire/workflow-service/">
<Project Path="aspire/LINGYUN.Abp.MicroService.WorkflowService/LINGYUN.Abp.MicroService.WorkflowService.csproj" />
</Folder>
<Folder Name="/framework/" />
<Folder Name="/framework/auditing/">
<File Path="framework/auditing/README.md" />
<Project Path="framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN.Abp.AspNetCore.Auditing.csproj" />
<Project Path="framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj" />
<Project Path="framework/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj" />
<Project Path="framework/auditing/LINGYUN.Abp.AuditLogging.IP.Location/LINGYUN.Abp.AuditLogging.IP.Location.csproj" />
<Project Path="framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj" />
</Folder>
<Folder Name="/framework/authentication/">
<Project Path="framework/authentication/LINGYUN.Abp.Authentication.QQ/LINGYUN.Abp.Authentication.QQ.csproj" />
<Project Path="framework/authentication/LINGYUN.Abp.Authentication.WeChat/LINGYUN.Abp.Authentication.WeChat.csproj" />
</Folder>
<Folder Name="/framework/authorization/">
<Project Path="framework/authorization/LINGYUN.Abp.Authorization.OrganizationUnits/LINGYUN.Abp.Authorization.OrganizationUnits.csproj" />
</Folder>
<Folder Name="/framework/cli/">
<Project Path="framework/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj" />
</Folder>
<Folder Name="/framework/cloud-aliyun/">
<Project Path="framework/cloud-aliyun/LINGYUN.Abp.Aliyun.SettingManagement/LINGYUN.Abp.Aliyun.SettingManagement.csproj" />
<Project Path="framework/cloud-aliyun/LINGYUN.Abp.Aliyun/LINGYUN.Abp.Aliyun.csproj" />
<Project Path="framework/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj" />
</Folder>
<Folder Name="/framework/cloud-tencent/">
<Project Path="framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN.Abp.BlobStoring.Tencent.csproj" />
<Project Path="framework/cloud-tencent/LINGYUN.Abp.Sms.Tencent/LINGYUN.Abp.Sms.Tencent.csproj" />
<Project Path="framework/cloud-tencent/LINGYUN.Abp.Tencent.QQ/LINGYUN.Abp.Tencent.QQ.csproj" />
<Project Path="framework/cloud-tencent/LINGYUN.Abp.Tencent.SettingManagement/LINGYUN.Abp.Tencent.SettingManagement.csproj" />
<Project Path="framework/cloud-tencent/LINGYUN.Abp.Tencent/LINGYUN.Abp.Tencent.csproj" />
</Folder>
<Folder Name="/framework/common/">
<Project Path="framework/common/LINGYUN.Abp.AspNetCore.HttpOverrides/LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" />
<Project Path="framework/common/LINGYUN.Abp.AspNetCore.Mvc.Client/LINGYUN.Abp.AspNetCore.Mvc.Client.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Data.DbMigrator/LINGYUN.Abp.Data.DbMigrator.csproj" />
<Project Path="framework/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj" />
<Project Path="framework/common/LINGYUN.Abp.IdGenerator/LINGYUN.Abp.IdGenerator.csproj" />
<Project Path="framework/common/LINGYUN.Abp.IP.Location/LINGYUN.Abp.IP.Location.csproj" />
<Project Path="framework/common/LINGYUN.Abp.IP2Region/LINGYUN.Abp.IP2Region.csproj" />
</Folder>
<Folder Name="/framework/dapr/">
<Project Path="framework/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore.Wrapper/LINGYUN.Abp.Dapr.Actors.AspNetCore.Wrapper.csproj" />
<Project Path="framework/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj" />
<Project Path="framework/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN.Abp.Dapr.Actors.csproj" />
<Project Path="framework/dapr/LINGYUN.Abp.Dapr.Client.Wrapper/LINGYUN.Abp.Dapr.Client.Wrapper.csproj" />
<Project Path="framework/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj" />
<Project Path="framework/dapr/LINGYUN.Abp.Dapr/LINGYUN.Abp.Dapr.csproj" />
<Project Path="framework/dapr/LINGYUN.Abp.DistributedLocking.Dapr/LINGYUN.Abp.DistributedLocking.Dapr.csproj" />
</Folder>
<Folder Name="/framework/data-protection/">
<Project Path="framework/data-protection/LINGYUN.Abp.DataProtection.Abstractions/LINGYUN.Abp.DataProtection.Abstractions.csproj" />
<Project Path="framework/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj" />
<Project Path="framework/data-protection/LINGYUN.Abp.DataProtection/LINGYUN.Abp.DataProtection.csproj" />
</Folder>
<Folder Name="/framework/dynamic-queryable/">
<Project Path="framework/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application.Contracts/LINGYUN.Abp.Dynamic.Queryable.Application.Contracts.csproj" />
<Project Path="framework/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application/LINGYUN.Abp.Dynamic.Queryable.Application.csproj" />
<Project Path="framework/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.HttpApi/LINGYUN.Abp.Dynamic.Queryable.HttpApi.csproj" />
<Project Path="framework/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN.Linq.Dynamic.Queryable.csproj" />
</Folder>
<Folder Name="/framework/elasticsearch/">
<Project Path="framework/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN.Abp.Elasticsearch.csproj" />
</Folder>
<Folder Name="/framework/entity-change/">
<Project Path="framework/entity-change/LINGYUN.Abp.EntityChange.Application.Contracts/LINGYUN.Abp.EntityChange.Application.Contracts.csproj" />
<Project Path="framework/entity-change/LINGYUN.Abp.EntityChange.Application/LINGYUN.Abp.EntityChange.Application.csproj" />
<Project Path="framework/entity-change/LINGYUN.Abp.EntityChange.HttpApi/LINGYUN.Abp.EntityChange.HttpApi.csproj" />
</Folder>
<Folder Name="/framework/exception-handling/">
<Project Path="framework/common/LINGYUN.Abp.ExceptionHandling.Emailing/LINGYUN.Abp.ExceptionHandling.Emailing.csproj" />
<Project Path="framework/common/LINGYUN.Abp.ExceptionHandling/LINGYUN.Abp.ExceptionHandling.csproj" />
</Folder>
<Folder Name="/framework/exporter/">
<Project Path="framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj" />
<Project Path="framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN.Abp.Exporter.MagicodesIE.Excel.csproj" />
<Project Path="framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN.Abp.Exporter.MiniExcel.csproj" />
<Project Path="framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN.Abp.Exporter.Pdf.LibreOffice.csproj" />
<Project Path="framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN.Abp.Exporter.Pdf.SpireLib.csproj" />
<Project Path="framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN.Abp.Exporter.Pdf.csproj" />
</Folder>
<Folder Name="/framework/features/">
<Project Path="framework/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN.Abp.Features.LimitValidation.Redis.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Features.LimitValidation/LINGYUN.Abp.Features.LimitValidation.csproj" />
<Project Path="framework/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj" />
<Project Path="framework/features/LINGYUN.Abp.Features.Client/LINGYUN.Abp.Features.Client.csproj" />
</Folder>
<Folder Name="/framework/hangfire/">
<Project Path="framework/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj" />
<Project Path="framework/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN.Abp.Hangfire.Dashboard.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Hangfire.MySqlStorage/LINGYUN.Abp.Hangfire.Storage.MySql.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Hangfire.Storage.SqlServer/LINGYUN.Abp.Hangfire.Storage.SqlServer.csproj" />
</Folder>
<Folder Name="/framework/localization/">
<Project Path="framework/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN.Abp.AspNetCore.Mvc.Localization.csproj" />
<Project Path="framework/localization/LINGYUN.Abp.Localization.CultureMap/LINGYUN.Abp.Localization.CultureMap.csproj" />
<Project Path="framework/localization/LINGYUN.Abp.Localization.Xml/LINGYUN.Abp.Localization.Xml.csproj" />
</Folder>
<Folder Name="/framework/location/">
<Project Path="framework/common/LINGYUN.Abp.Location.Baidu/LINGYUN.Abp.Location.Baidu.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Location.Tencent/LINGYUN.Abp.Location.Tencent.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Location/LINGYUN.Abp.Location.csproj" />
</Folder>
<Folder Name="/framework/logging/">
<Project Path="framework/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj" />
<Project Path="framework/logging/LINGYUN.Abp.Logging/LINGYUN.Abp.Logging.csproj" />
<Project Path="framework/logging/LINGYUN.Abp.Serilog.Enrichers.Application/LINGYUN.Abp.Serilog.Enrichers.Application.csproj" />
<Project Path="framework/logging/LINGYUN.Abp.Serilog.Enrichers.UniqueId/LINGYUN.Abp.Serilog.Enrichers.UniqueId.csproj" />
</Folder>
<Folder Name="/framework/navigation/">
<Project Path="framework/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN.Abp.UI.Navigation.csproj" />
</Folder>
<Folder Name="/framework/nexus/">
<Project Path="framework/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN.Abp.BlobStoring.Nexus.csproj" />
<Project Path="framework/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN.Abp.Sonatype.Nexus.csproj" />
</Folder>
<Folder Name="/framework/open-api/">
<Project Path="framework/open-api/LINGYUN.Abp.OpenApi.Authorization/LINGYUN.Abp.OpenApi.Authorization.csproj" />
<Project Path="framework/open-api/LINGYUN.Abp.OpenApi.IdentityServer/LINGYUN.Abp.OpenApi.IdentityServer.csproj" />
<Project Path="framework/open-api/LINGYUN.Abp.OpenApi.OpenIddict/LINGYUN.Abp.OpenApi.OpenIddict.csproj" />
<Project Path="framework/open-api/LINGYUN.Abp.OpenApi/LINGYUN.Abp.OpenApi.csproj" />
</Folder>
<Folder Name="/framework/pushplus/">
<Project Path="framework/pushplus/LINGYUN.Abp.PushPlus.SettingManagement/LINGYUN.Abp.PushPlus.SettingManagement.csproj" />
<Project Path="framework/pushplus/LINGYUN.Abp.PushPlus/LINGYUN.Abp.PushPlus.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.PushPlus/LINGYUN.Abp.Notifications.PushPlus.csproj" />
</Folder>
<Folder Name="/framework/realtime/">
<Project Path="framework/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj" />
</Folder>
<Folder Name="/framework/rules/">
<Project Path="framework/rules/LINGYUN.Abp.Rules.NRules/LINGYUN.Abp.Rules.NRules.csproj" />
<Project Path="framework/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj" />
<Project Path="framework/rules/LINGYUN.Abp.Rules/LINGYUN.Abp.Rules.csproj" />
</Folder>
<Folder Name="/framework/security/">
<Project Path="framework/security/LINGYUN.Abp.Claims.Mapping/LINGYUN.Abp.Claims.Mapping.csproj" />
<Project Path="framework/security/LINGYUN.Abp.Encryption.SM4/LINGYUN.Abp.Encryption.SM4.csproj" />
<Project Path="framework/security/LINGYUN.Abp.Security/LINGYUN.Abp.Security.csproj" />
</Folder>
<Folder Name="/framework/settings/">
<Project Path="framework/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj" />
<Project Path="framework/settings/LINGYUN.Abp.Settings/LINGYUN.Abp.Settings.csproj" />
</Folder>
<Folder Name="/framework/tenants/">
<Project Path="framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN.Abp.AspNetCore.MultiTenancy.csproj" />
<Project Path="framework/tenants/LINGYUN.Abp.MultiTenancy.Editions/LINGYUN.Abp.MultiTenancy.Editions.csproj" />
</Folder>
<Folder Name="/framework/themes/">
<Project Path="framework/themes/LINGYUN.Abp.AspNetCore.Mvc.UI.Theme.Lepton/LINGYUN.Abp.AspNetCore.Mvc.UI.Theme.Lepton.csproj" />
<Project Path="framework/themes/LINGYUN.Abp.Themes.Lepton/LINGYUN.Abp.Themes.Lepton.csproj" />
</Folder>
<Folder Name="/framework/tracking/">
<Project Path="framework/telemetry/LINGYUN.Abp.Telemetry.APM/LINGYUN.Abp.Telemetry.APM.csproj" />
<Project Path="framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN.Abp.Telemetry.OpenTelemetry.csproj" />
<Project Path="framework/telemetry/LINGYUN.Abp.Telemetry.SkyWalking/LINGYUN.Abp.Telemetry.SkyWalking.csproj" />
</Folder>
<Folder Name="/framework/wechat/">
<Project Path="framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN.Abp.Identity.WeChat.Work.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN.Abp.Identity.WeChat.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN.Abp.WeChat.Common.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN.Abp.WeChat.MiniProgram.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Official.Application.Contracts/LINGYUN.Abp.WeChat.Official.Application.Contracts.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Official.Application/LINGYUN.Abp.WeChat.Official.Application.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Official.Handlers/LINGYUN.Abp.WeChat.Official.Handlers.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Official.HttpApi/LINGYUN.Abp.WeChat.Official.HttpApi.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Official.Senparc/LINGYUN.Abp.WeChat.Official.Senparc.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN.Abp.WeChat.Official.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.SettingManagement/LINGYUN.Abp.WeChat.SettingManagement.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.Application.Contracts/LINGYUN.Abp.WeChat.Work.Application.Contracts.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN.Abp.WeChat.Work.Application.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/LINGYUN.Abp.WeChat.Work.AspNetCore.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.Contacts/LINGYUN.Abp.WeChat.Work.Contacts.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN.Abp.WeChat.Work.ExternalContact.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.Handlers/LINGYUN.Abp.WeChat.Work.Handlers.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.HttpApi/LINGYUN.Abp.WeChat.Work.HttpApi.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work.OA/LINGYUN.Abp.WeChat.Work.OA.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj" />
<Project Path="framework/wechat/LINGYUN.Abp.WeChat/LINGYUN.Abp.WeChat.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.MiniProgram/LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN.Abp.Notifications.WeChat.Work.csproj" />
</Folder>
<Folder Name="/framework/wrapper/">
<Project Path="framework/common/LINGYUN.Abp.AspNetCore.Wrapper/LINGYUN.Abp.AspNetCore.Wrapper.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Http.Client.Wrapper/LINGYUN.Abp.Http.Client.Wrapper.csproj" />
<Project Path="framework/common/LINGYUN.Abp.Wrapper/LINGYUN.Abp.Wrapper.csproj" />
<Project Path="framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN.Abp.AspNetCore.Mvc.Wrapper.csproj" />
</Folder>
<Folder Name="/framework/wx-pusher/">
<Project Path="framework/wx-pusher/LINGYUN.Abp.Identity.WxPusher/LINGYUN.Abp.Identity.WxPusher.csproj" />
<Project Path="framework/wx-pusher/LINGYUN.Abp.WxPusher.SettingManagement/LINGYUN.Abp.WxPusher.SettingManagement.csproj" />
<Project Path="framework/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN.Abp.WxPusher.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.WxPusher/LINGYUN.Abp.Notifications.WxPusher.csproj" />
</Folder>
<Folder Name="/modules/" />
<Folder Name="/modules/account/">
<Project Path="modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.HttpApi.Client/LINGYUN.Abp.Account.HttpApi.Client.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN.Abp.Account.OAuth.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.Security/LINGYUN.Abp.Account.Security.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.Web.IdentityServer/LINGYUN.Abp.Account.Web.IdentityServer.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.Web.OAuth/LINGYUN.Abp.Account.Web.OAuth.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.Web.OpenIddict/LINGYUN.Abp.Account.Web.OpenIddict.csproj" />
<Project Path="modules/account/LINGYUN.Abp.Account.Web/LINGYUN.Abp.Account.Web.csproj" />
</Folder>
<Folder Name="/modules/ai/">
<Project Path="modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN.Abp.AI.Agent.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AI.Core/LINGYUN.Abp.AI.Core.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AI.DeepSeek.Console/LINGYUN.Abp.AI.DeepSeek.Console.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AI.DeepSeek/LINGYUN.Abp.AI.DeepSeek.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN.Abp.AIManagement.Application.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN.Abp.AIManagement.Domain.Shared.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.Domain/LINGYUN.Abp.AIManagement.Domain.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.EntityFrameworkCore/LINGYUN.Abp.AIManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.HttpApi.Client/LINGYUN.Abp.AIManagement.HttpApi.Client.csproj" />
<Project Path="modules/ai/LINGYUN.Abp.AIManagement.HttpApi/LINGYUN.Abp.AIManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/auditing/">
<Project Path="modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN.Abp.Auditing.Application.Contracts.csproj" />
<Project Path="modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN.Abp.Auditing.Application.csproj" />
<Project Path="modules/auditing/LINGYUN.Abp.Auditing.HttpApi.Client/LINGYUN.Abp.Auditing.HttpApi.Client.csproj" />
<Project Path="modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN.Abp.Auditing.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/caching-management/">
<Project Path="modules/caching-management/LINGYUN.Abp.CachingManagement.Application.Contracts/LINGYUN.Abp.CachingManagement.Application.Contracts.csproj" />
<Project Path="modules/caching-management/LINGYUN.Abp.CachingManagement.Application/LINGYUN.Abp.CachingManagement.Application.csproj" />
<Project Path="modules/caching-management/LINGYUN.Abp.CachingManagement.Domain/LINGYUN.Abp.CachingManagement.Domain.csproj" />
<Project Path="modules/caching-management/LINGYUN.Abp.CachingManagement.HttpApi/LINGYUN.Abp.CachingManagement.HttpApi.csproj" />
<Project Path="modules/caching-management/LINGYUN.Abp.CachingManagement.StackExchangeRedis/LINGYUN.Abp.CachingManagement.StackExchangeRedis.csproj" />
</Folder>
<Folder Name="/modules/data-protection/">
<Project Path="modules/data-protection/LINGYUN.Abp.DataProtectionManagement.Application.Contracts/LINGYUN.Abp.DataProtectionManagement.Application.Contracts.csproj" />
<Project Path="modules/data-protection/LINGYUN.Abp.DataProtectionManagement.Application/LINGYUN.Abp.DataProtectionManagement.Application.csproj" />
<Project Path="modules/data-protection/LINGYUN.Abp.DataProtectionManagement.Domain.Shared/LINGYUN.Abp.DataProtectionManagement.Domain.Shared.csproj" />
<Project Path="modules/data-protection/LINGYUN.Abp.DataProtectionManagement.Domain/LINGYUN.Abp.DataProtectionManagement.Domain.csproj" />
<Project Path="modules/data-protection/LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore/LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/data-protection/LINGYUN.Abp.DataProtectionManagement.HttpApi/LINGYUN.Abp.DataProtectionManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/elsa/">
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities.BlobStoring/LINGYUN.Abp.Elsa.Activities.BlobStoring.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities.Emailing/LINGYUN.Abp.Elsa.Activities.Emailing.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities.IM/LINGYUN.Abp.Elsa.Activities.IM.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities.Notifications/LINGYUN.Abp.Elsa.Activities.Notifications.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities.Sms/LINGYUN.Abp.Elsa.Activities.Sms.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities.Webhooks/LINGYUN.Abp.Elsa.Activities.Webhooks.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Activities/LINGYUN.Abp.Elsa.Activities.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql/LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN.Abp.Elsa.EntityFrameworkCore.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Notifications/LINGYUN.Abp.Elsa.Notifications.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa.Server/LINGYUN.Abp.Elsa.Server.csproj" />
<Project Path="modules/elsa/LINGYUN.Abp.Elsa/LINGYUN.Abp.Elsa.csproj" />
</Folder>
<Folder Name="/modules/feature-management/">
<Project Path="modules/feature-management/LINGYUN.Abp.FeatureManagement.Application.Contracts/LINGYUN.Abp.FeatureManagement.Application.Contracts.csproj" />
<Project Path="modules/feature-management/LINGYUN.Abp.FeatureManagement.Application/LINGYUN.Abp.FeatureManagement.Application.csproj" />
<Project Path="modules/feature-management/LINGYUN.Abp.FeatureManagement.HttpApi/LINGYUN.Abp.FeatureManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/gdpr/">
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.Application.Contracts/LINGYUN.Abp.Gdpr.Application.Contracts.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.Application/LINGYUN.Abp.Gdpr.Application.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.Domain.Identity/LINGYUN.Abp.Gdpr.Domain.Identity.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.Domain.Shared/LINGYUN.Abp.Gdpr.Domain.Shared.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.Domain/LINGYUN.Abp.Gdpr.Domain.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.EntityFrameworkCore/LINGYUN.Abp.Gdpr.EntityFrameworkCore.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.HttpApi.Client/LINGYUN.Abp.Gdpr.HttpApi.Client.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.HttpApi/LINGYUN.Abp.Gdpr.HttpApi.csproj" />
<Project Path="modules/gdpr/LINGYUN.Abp.Gdpr.Web/LINGYUN.Abp.Gdpr.Web.csproj" />
</Folder>
<Folder Name="/modules/identity/">
<Project Path="modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN.Abp.Identity.Application.Contracts.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN.Abp.Identity.Application.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.AspNetCore.QrCode/LINGYUN.Abp.Identity.AspNetCore.QrCode.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.AspNetCore.Session/LINGYUN.Abp.Identity.AspNetCore.Session.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN.Abp.Identity.Domain.Shared.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN.Abp.Identity.Domain.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.EntityFrameworkCore/LINGYUN.Abp.Identity.EntityFrameworkCore.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.HttpApi.Client/LINGYUN.Abp.Identity.HttpApi.Client.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN.Abp.Identity.HttpApi.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN.Abp.Identity.Notifications.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.OrganizaztionUnits/LINGYUN.Abp.Identity.OrganizaztionUnits.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.QrCode/LINGYUN.Abp.Identity.QrCode.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.Session.AspNetCore/LINGYUN.Abp.Identity.Session.AspNetCore.csproj" />
<Project Path="modules/identity/LINGYUN.Abp.Identity.Session/LINGYUN.Abp.Identity.Session.csproj" />
</Folder>
<Folder Name="/modules/identityServer/">
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.Domain/LINGYUN.Abp.IdentityServer.Domain.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.EntityFrameworkCore/LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.LinkUser/LINGYUN.Abp.IdentityServer.LinkUser.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.Portal/LINGYUN.Abp.IdentityServer.Portal.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.Session/LINGYUN.Abp.IdentityServer.Session.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj" />
<Project Path="modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat.Work/LINGYUN.Abp.IdentityServer.WeChat.Work.csproj" />
</Folder>
<Folder Name="/modules/localization-management/">
<File Path="modules/localization-management/README.md" />
<Project Path="modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application.Contracts/LINGYUN.Abp.LocalizationManagement.Application.Contracts.csproj" />
<Project Path="modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN.Abp.LocalizationManagement.Application.csproj" />
<Project Path="modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj" />
<Project Path="modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN.Abp.LocalizationManagement.Domain.csproj" />
<Project Path="modules/localization-management/LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore/LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/localization-management/LINGYUN.Abp.LocalizationManagement.HttpApi/LINGYUN.Abp.LocalizationManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/openiddict/">
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN.Abp.OpenIddict.Application.Contracts.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN.Abp.OpenIddict.Application.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.AspNetCore.Session/LINGYUN.Abp.OpenIddict.AspNetCore.Session.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.Dapr.Client/LINGYUN.Abp.OpenIddict.Dapr.Client.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.HttpApi.Client/LINGYUN.Abp.OpenIddict.HttpApi.Client.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.HttpApi/LINGYUN.Abp.OpenIddict.HttpApi.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.LinkUser/LINGYUN.Abp.OpenIddict.LinkUser.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.Portal/LINGYUN.Abp.OpenIddict.Portal.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.Sms/LINGYUN.Abp.OpenIddict.Sms.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.WeChat.Work/LINGYUN.Abp.OpenIddict.WeChat.Work.csproj" />
<Project Path="modules/openIddict/LINGYUN.Abp.OpenIddict.WeChat/LINGYUN.Abp.OpenIddict.WeChat.csproj" />
</Folder>
<Folder Name="/modules/oss-management/">
<File Path="modules/oss-management/README.md" />
<Project Path="modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN.Abp.BlobStoring.OssManagement.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN.Abp.OssManagement.Aliyun.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN.Abp.OssManagement.Application.Contracts.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN.Abp.OssManagement.Domain.Shared.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN.Abp.OssManagement.Domain.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN.Abp.OssManagement.FileSystem.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN.Abp.OssManagement.HttpApi.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.ImageSharp/LINGYUN.Abp.OssManagement.ImageSharp.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Imaging/LINGYUN.Abp.OssManagement.Imaging.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN.Abp.OssManagement.Minio.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN.Abp.OssManagement.Nexus.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.SettingManagement/LINGYUN.Abp.OssManagement.SettingManagement.csproj" />
<Project Path="modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN.Abp.OssManagement.Tencent.csproj" />
</Folder>
<Folder Name="/modules/permission-management/">
<Project Path="modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj" />
<Project Path="modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj" />
<Project Path="modules/permissions-management/LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits/LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits.csproj" />
<Project Path="modules/permissions-management/LINGYUN.Abp.PermissionManagement.HttpApi/LINGYUN.Abp.PermissionManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/platform/">
<Project Path="modules/platform/LINGYUN.Abp.Emailing.Platform/LINGYUN.Abp.Emailing.Platform.csproj" />
<Project Path="modules/platform/LINGYUN.Abp.Sms.Platform/LINGYUN.Abp.Sms.Platform.csproj" />
<Project Path="modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj" />
<Project Path="modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN.Platform.Application.Contracts.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.Application/LINGYUN.Platform.Application.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN.Platform.Domain.Shared.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.Domain/LINGYUN.Platform.Domain.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN.Platform.EntityFrameworkCore.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.HttpApi.Client/LINGYUN.Platform.HttpApi.Client.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.HttpApi/LINGYUN.Platform.HttpApi.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.Settings.VueVbenAdmin/LINGYUN.Platform.Settings.VueVbenAdmin.csproj" />
<Project Path="modules/platform/LINGYUN.Platform.Theme.VueVbenAdmin/LINGYUN.Platform.Theme.VueVbenAdmin.csproj" />
</Folder>
<Folder Name="/modules/project/">
<Project Path="modules/project/LINGYUN.Abp.ProjectManagement.Application.Contracts/LINGYUN.Abp.ProjectManagement.Application.Contracts.csproj" />
<Project Path="modules/project/LINGYUN.Abp.ProjectManagement.Application/LINGYUN.Abp.ProjectManagement.Application.csproj" />
<Project Path="modules/project/LINGYUN.Abp.ProjectManagement.Domain.Shared/LINGYUN.Abp.ProjectManagement.Domain.Shared.csproj" />
<Project Path="modules/project/LINGYUN.Abp.ProjectManagement.Domain/LINGYUN.Abp.ProjectManagement.Domain.csproj" />
<Project Path="modules/project/LINGYUN.Abp.ProjectManagement.EntityFrameworkCore/LINGYUN.Abp.ProjectManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/project/LINGYUN.Abp.ProjectManagement.HttpApi/LINGYUN.Abp.ProjectManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/realtime-message/">
<Project Path="modules/realtime-message/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.Application.Contracts/LINGYUN.Abp.MessageService.Application.Contracts.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.Application/LINGYUN.Abp.MessageService.Application.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.HttpApi.Client/LINGYUN.Abp.MessageService.HttpApi.Client.csproj" />
<Project Path="modules/realtime-message/LINGYUN.Abp.MessageService.HttpApi/LINGYUN.Abp.MessageService.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/realtime-notifications/">
<Project Path="modules/realtime-notifications/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN.Abp.ExceptionHandling.Notifications.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN.Abp.Notifications.Application.Contracts.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Application/LINGYUN.Abp.Notifications.Application.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Common/LINGYUN.Abp.Notifications.Common.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Core/LINGYUN.Abp.Notifications.Core.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain.Shared/LINGYUN.Abp.Notifications.Domain.Shared.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN.Abp.Notifications.Domain.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Emailing/LINGYUN.Abp.Notifications.Emailing.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.EntityFrameworkCore/LINGYUN.Abp.Notifications.EntityFrameworkCore.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.HttpApi.Client/LINGYUN.Abp.Notifications.HttpApi.Client.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.HttpApi/LINGYUN.Abp.Notifications.HttpApi.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications.Sms/LINGYUN.Abp.Notifications.Sms.csproj" />
<Project Path="modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.Notifications.Jobs/LINGYUN.Abp.Notifications.Jobs.csproj" />
</Folder>
<Folder Name="/modules/rules-management/" />
<Folder Name="/modules/rules-management/rules-engine/">
<Project Path="modules/rules-management/rules-engine/LINGYUN.Abp.RulesEngineManagement.Application.Contracts/LINGYUN.Abp.RulesEngineManagement.Application.Contracts.csproj" />
<Project Path="modules/rules-management/rules-engine/LINGYUN.Abp.RulesEngineManagement.Application/LINGYUN.Abp.RulesEngineManagement.Application.csproj" />
<Project Path="modules/rules-management/rules-engine/LINGYUN.Abp.RulesEngineManagement.Domain.Shared/LINGYUN.Abp.RulesEngineManagement.Domain.Shared.csproj" />
<Project Path="modules/rules-management/rules-engine/LINGYUN.Abp.RulesEngineManagement.Domain/LINGYUN.Abp.RulesEngineManagement.Domain.csproj" />
<Project Path="modules/rules-management/rules-engine/LINGYUN.Abp.RulesEngineManagement.EntityFrameworkCore/LINGYUN.Abp.RulesEngineManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/rules-management/rules-engine/LINGYUN.Abp.RulesEngineManagement.HttpApi/LINGYUN.Abp.RulesEngineManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/saas/">
<Project Path="modules/saas/LINGYUN.Abp.MultiTenancy.Saas/LINGYUN.Abp.MultiTenancy.Saas.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN.Abp.Saas.Application.Contracts.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN.Abp.Saas.Application.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN.Abp.Saas.DbChecker.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN.Abp.Saas.Domain.Shared.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN.Abp.Saas.Domain.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.EntityFrameworkCore/LINGYUN.Abp.Saas.EntityFrameworkCore.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.HttpApi.Client/LINGYUN.Abp.Saas.HttpApi.Client.csproj" />
<Project Path="modules/saas/LINGYUN.Abp.Saas.HttpApi/LINGYUN.Abp.Saas.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/settings/">
<Project Path="modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj" />
<Project Path="modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/task-management/">
<Project Path="modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN.Abp.BackgroundTasks.Abstractions.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN.Abp.BackgroundTasks.Jobs.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.BackgroundTasks.Notifications/LINGYUN.Abp.BackgroundTasks.Notifications.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN.Abp.BackgroundTasks.Quartz.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN.Abp.BackgroundTasks.TaskManagement.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.Elasticsearch.Jobs/LINGYUN.Abp.Elasticsearch.Jobs.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN.Abp.Quartz.MySqlInstaller.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.Quartz.PostgresSqlInstaller/LINGYUN.Abp.Quartz.PostgresSqlInstaller.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.Quartz.SqlInstaller/LINGYUN.Abp.Quartz.SqlInstaller.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN.Abp.TaskManagement.Application.Contracts.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN.Abp.TaskManagement.Application.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN.Abp.TaskManagement.Domain.Shared.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN.Abp.TaskManagement.Domain.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN.Abp.TaskManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi.Client/LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj" />
<Project Path="modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN.Abp.TaskManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/modules/text-templating/">
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN.Abp.TextTemplating.Application.Contracts.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN.Abp.TextTemplating.Application.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN.Abp.TextTemplating.Domain.Shared.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN.Abp.TextTemplating.Domain.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN.Abp.TextTemplating.EntityFrameworkCore.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi.Client/LINGYUN.Abp.TextTemplating.HttpApi.Client.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN.Abp.TextTemplating.HttpApi.csproj" />
<Project Path="modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN.Abp.TextTemplating.Scriban.csproj" />
</Folder>
<Folder Name="/modules/webhooks/">
<Project Path="modules/webhooks/LINGYUN.Abp.Webhooks.Core/LINGYUN.Abp.Webhooks.Core.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.Webhooks.EventBus/LINGYUN.Abp.Webhooks.EventBus.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN.Abp.Webhooks.Identity.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN.Abp.Webhooks.Saas.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN.Abp.WebHooks.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN.Abp.WebhooksManagement.Application.Contracts.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN.Abp.WebhooksManagement.Application.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain.Shared/LINGYUN.Abp.WebhooksManagement.Domain.Shared.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN.Abp.WebhooksManagement.Domain.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore/LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore.csproj" />
<Project Path="modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN.Abp.WebhooksManagement.HttpApi.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/LINGYUN.Abp.Aliyun.Tests/LINGYUN.Abp.Aliyun.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Emailing.Platform.Tests/LINGYUN.Abp.Emailing.Platform.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Features.LimitValidation.Tests/LINGYUN.Abp.Features.LimitValidation.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.IdGenerator.Tests/LINGYUN.Abp.IdGenerator.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Location.Baidu.Tests/LINGYUN.Abp.Location.Baidu.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Location.Tencent.Tests/LINGYUN.Abp.Location.Tencent.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.OssManagement.Domain.Tests/LINGYUN.Abp.OssManagement.Domain.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.OssManagement.Minio.Tests/LINGYUN.Abp.OssManagement.Minio.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN.Abp.OssManagement.Nexus.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN.Abp.Rules.RulesEngine.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.Sms.Platform.Tests/LINGYUN.Abp.Sms.Platform.Tests.csproj" />
<Project Path="tests/LINGYUN.Abp.TestBase/LINGYUN.Abp.TestsBase.csproj" />
<Project Path="tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN.Abp.WeChat.Work.Tests.csproj" />
</Folder>
</Solution>

53
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<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;
}
}

13
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
{
}

3
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

40
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.DbMigrator/LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj

@ -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>

43
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<AIServiceDbMigratorHostedService>();
});
await builder.RunConsoleAsync();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly!");
}
finally
{
await Log.CloseAndFlushAsync();
}

5
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"
}
}

26
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<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;
}
}

44
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<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);
}
}

36
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<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());
}
}

32
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<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();
}
}

28
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<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();
}
}

45
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<AIServiceMigrationsDbContext>();
Configure<AbpDbContextOptions>(options =>
{
options.UseNpgsql();
});
}
}

3
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/FodyWeavers.xsd

@ -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>

35
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore.csproj

@ -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>

303
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/20260127083027_Initial_AI_Service.Designer.cs

@ -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
}
}
}

148
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
{
/// <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");
}
}
}

300
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService.EntityFrameworkCore/Migrations/AIServiceMigrationsDbContextModelSnapshot.cs

@ -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
}
}
}

423
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.Configure.cs

@ -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");
});
});
}
}

103
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs

@ -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());
}
}

3
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

71
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/LINGYUN.Abp.MicroService.AIService.csproj

@ -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>

99
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/Program.cs

@ -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();
}

12
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/Properties/launchSettings.json

@ -0,0 +1,12 @@
{
"profiles": {
"LINGYUN.Abp.MicroService.AIService": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:49787;http://localhost:49788"
}
}
}

35
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/TenantHeaderParamter.cs

@ -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
});
}
}
}

116
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json

@ -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"
}
}
]
}
}
]
}
}

91
aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.json

@ -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}"
}
}
]
}
}
]
}
}

25
aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json

@ -1,6 +1,21 @@
{
"ReverseProxy": {
"Routes": {
"ai-management-route": {
"ClusterId": "ai-management-cluster",
"Match": {
"Path": "/api/ai-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"abp-route": {
"ClusterId": "admin-service-cluster",
"Match": {
@ -451,6 +466,16 @@
}
},
"Clusters": {
"ai-management-cluster": {
"Destinations": {
"destination1": {
"Address": "http://localhost:30070",
"Metadata": {
"SwaggerEndpoint": "http://localhost:30070"
}
}
}
},
"auth-server-cluster": {
"Destinations": {
"destination1": {

25
aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs

@ -10,8 +10,17 @@ var redis = builder.AddRedis("redis")
// Elasticsearch
var elasticsearch = builder.AddElasticsearch("elasticsearch")
.WithContainerName("elasticsearch")
.WithImageTag("8.17.3")
.WithDataVolume("elasticsearch-dev")
.WithEnvironment("ES_JAVA_OPTS", "-Xms2g -Xmx2g");
.WithEnvironment("ES_JAVA_OPTS", "-Xms2g -Xmx2g")
// see: https://www.funkysi1701.com/posts/2025/adding-elasticsearch-with-aspire/
.WithEnvironment("xpack.security.enabled", "false");
// Kibana
builder.AddContainer("kibana", "kibana", "8.17.3")
.WithReference(elasticsearch)
.WithEndpoint(5601, 5601)
.WaitFor(elasticsearch);
// Postgres
var postgres = builder.AddPostgres("postgres")
@ -215,9 +224,21 @@ builder.AddProject<Projects.LINGYUN_Abp_MicroService_WorkflowService>("WorkflowS
.WaitFor(rabbitmq)
.WaitFor(taskService);
// AIService
AddDotNetProject<
Projects.LINGYUN_Abp_MicroService_AIService_DbMigrator,
Projects.LINGYUN_Abp_MicroService_AIService>(
builder: builder,
servicePrefix: "AI",
serviceSuffix: "Service",
migratorSuffix: "Migrator",
port: 30070,
portName: "ai",
waitProject: localizationService);
// ApiGateway
var apigateway = builder.AddProject<Projects.LINGYUN_Abp_MicroService_ApiGateway>("ApiGateway")
.WithHttpEndpoint(port: 30000, name: "gateway")
// .WithHttpEndpoint(port: 30000, name: "gateway")
.WithExternalHttpEndpoints()
.WithReference(redis, "Redis")
.WithReference(elasticsearch, "Elasticsearch")

2
aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/LINGYUN.Abp.MicroService.AppHost.csproj

@ -17,6 +17,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AIService.DbMigrator\LINGYUN.Abp.MicroService.AIService.DbMigrator.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AIService\LINGYUN.Abp.MicroService.AIService.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AdminService.DbMigrator\LINGYUN.Abp.MicroService.AdminService.DbMigrator.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AdminService\LINGYUN.Abp.MicroService.AdminService.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.MicroService.AuthServer.DbMigrator\LINGYUN.Abp.MicroService.AuthServer.DbMigrator.csproj" />

1
aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/LINGYUN.Abp.MicroService.TaskService.csproj

@ -55,6 +55,7 @@
<ProjectReference Include="..\..\framework\telemetry\LINGYUN.Abp.Telemetry.SkyWalking\LINGYUN.Abp.Telemetry.SkyWalking.csproj" />
<ProjectReference Include="..\..\framework\tenants\LINGYUN.Abp.MultiTenancy.Editions\LINGYUN.Abp.MultiTenancy.Editions.csproj" />
<ProjectReference Include="..\..\framework\mvc\LINGYUN.Abp.AspNetCore.Mvc.Wrapper\LINGYUN.Abp.AspNetCore.Mvc.Wrapper.csproj" />
<ProjectReference Include="..\..\modules\task-management\LINGYUN.Abp.Elasticsearch.Jobs\LINGYUN.Abp.Elasticsearch.Jobs.csproj" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/TaskServiceModule.cs

@ -10,6 +10,7 @@ using LINGYUN.Abp.BackgroundTasks.Notifications;
using LINGYUN.Abp.BackgroundTasks.Quartz;
using LINGYUN.Abp.Claims.Mapping;
using LINGYUN.Abp.Data.DbMigrator;
using LINGYUN.Abp.Elasticsearch.Jobs;
using LINGYUN.Abp.Emailing.Platform;
using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling.Emailing;
@ -54,6 +55,7 @@ namespace LINGYUN.Abp.MicroService.TaskService;
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpAspNetCoreMvcLocalizationModule),
typeof(AbpElasticsearchJobsModule),
typeof(AbpBackgroundTasksJobsModule),
typeof(AbpBackgroundTasksQuartzModule),
typeof(AbpBackgroundTasksDistributedLockingModule),

110
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentFactory.cs

@ -0,0 +1,110 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Localization;
using System;
using System.Threading.Tasks;
using Volo.Abp.AI;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.SimpleStateChecking;
namespace LINGYUN.Abp.AI.Agent;
public class AgentFactory : IAgentFactory, IScopedDependency
{
protected IServiceProvider ServiceProvider { get; }
protected IChatClientFactory ChatClientFactory { get; }
protected IStringLocalizerFactory StringLocalizerFactory { get; }
protected IWorkspaceDefinitionManager WorkspaceDefinitionManager { get; }
protected ISimpleStateCheckerManager<WorkspaceDefinition> StateCheckerManager { get; }
public AgentFactory(
IServiceProvider serviceProvider,
IChatClientFactory chatClientFactory,
IStringLocalizerFactory stringLocalizerFactory,
IWorkspaceDefinitionManager workspaceDefinitionManager,
ISimpleStateCheckerManager<WorkspaceDefinition> stateCheckerManager)
{
ServiceProvider = serviceProvider;
ChatClientFactory = chatClientFactory;
StringLocalizerFactory = stringLocalizerFactory;
WorkspaceDefinitionManager = workspaceDefinitionManager;
StateCheckerManager = stateCheckerManager;
}
public async virtual Task<AIAgent> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
var chatClient = await ChatClientFactory.CreateAsync<TWorkspace>();
var workspaceDefine = await WorkspaceDefinitionManager.GetOrNullAsync(workspace);
if (workspaceDefine != null)
{
await CheckWorkspaceStateAsync(workspaceDefine);
}
return await CreateAgentAsync(chatClient, workspaceDefine);
}
public async virtual Task<AIAgent> CreateAsync(string workspace)
{
var workspaceDefine = await WorkspaceDefinitionManager.GetAsync(workspace);
await CheckWorkspaceStateAsync(workspaceDefine);
var chatClient = await ChatClientFactory.CreateAsync(workspace);
return await CreateAgentAsync(chatClient, workspaceDefine);
}
protected async virtual Task<AIAgent> CreateAgentAsync(IChatClient chatClient, WorkspaceDefinition? workspace)
{
string? description = null;
if (workspace?.Description != null)
{
description = workspace.Description.Localize(StringLocalizerFactory);
}
var tools = await GetAgentToolsAsync(workspace);
var clientAgentOptions = new ChatClientAgentOptions
{
ChatOptions = new ChatOptions
{
Instructions = workspace?.Instructions,
Temperature = workspace?.Temperature,
MaxOutputTokens = workspace?.MaxOutputTokens,
PresencePenalty = workspace?.PresencePenalty,
FrequencyPenalty = workspace?.FrequencyPenalty,
Tools = tools,
},
Name = workspace?.Name,
Description = description,
};
var aiAgent = chatClient.CreateAIAgent(clientAgentOptions)
.AsBuilder()
.UseLogging()
.UseOpenTelemetry()
.Build(ServiceProvider);
return new WorkspaceAIAgent(aiAgent, workspace);
}
protected virtual Task<AITool[]> GetAgentToolsAsync(WorkspaceDefinition? workspace)
{
return Task.FromResult<AITool[]>([]);
}
protected async virtual Task CheckWorkspaceStateAsync(WorkspaceDefinition workspace)
{
if (!await StateCheckerManager.IsEnabledAsync(workspace))
{
throw new AbpAuthorizationException(
$"Workspace is not enabled: {workspace.Name}!",
AbpAIErrorCodes.WorkspaceIsNotEnabled)
.WithData("Workspace", workspace.Name);
}
}
}

157
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/AgentService.cs

@ -0,0 +1,157 @@
using LINGYUN.Abp.AI.Chats;
using LINGYUN.Abp.AI.Localization;
using LINGYUN.Abp.AI.Models;
using LINGYUN.Abp.AI.Tokens;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Timing;
using AIChatMessage = Microsoft.Extensions.AI.ChatMessage;
namespace LINGYUN.Abp.AI.Agent;
public class AgentService : IAgentService, IScopedDependency
{
private readonly IClock _clock;
private readonly IGuidGenerator _guidGenerator;
private readonly IAgentFactory _agentFactory;
private readonly ITokenUsageStore _tokenUsageStore;
private readonly IChatMessageStore _chatMessageStore;
private readonly IConversationStore _conversationStore;
private readonly IStringLocalizer<AbpAIResource> _localizerResource;
public AgentService(
IClock clock,
IGuidGenerator guidGenerator,
IAgentFactory agentFactory,
ITokenUsageStore tokenUsageStore,
IChatMessageStore chatMessageStore,
IConversationStore conversationStore,
IStringLocalizer<AbpAIResource> localizerResource)
{
_clock = clock;
_guidGenerator = guidGenerator;
_agentFactory = agentFactory;
_tokenUsageStore = tokenUsageStore;
_chatMessageStore = chatMessageStore;
_conversationStore = conversationStore;
_localizerResource = localizerResource;
}
public async virtual IAsyncEnumerable<string> SendMessageAsync(Models.ChatMessage message)
{
var conversationId = await StoreConversation(message);
message.WithConversationId(conversationId);
var messages = await BuildChatMessages(message);
var agent = await _agentFactory.CreateAsync(message.Workspace);
var agentRunRes = agent.RunStreamingAsync(messages);
var tokenUsageInfo = new TokenUsageInfo(message.Workspace, conversationId);
var agentMessageBuilder = new StringBuilder();
await foreach (var response in agentRunRes)
{
UpdateTokenUsageInfo(tokenUsageInfo, response);
agentMessageBuilder.Append(response.Text);
yield return response.Text;
}
var messageId = await StoreChatMessage(message, agentMessageBuilder.ToString());
tokenUsageInfo.WithMessageId(messageId);
#if DEBUG
Console.WriteLine();
Console.WriteLine(tokenUsageInfo);
#endif
await StoreTokenUsageInfo(tokenUsageInfo);
}
protected virtual async Task<IEnumerable<AIChatMessage>> BuildChatMessages(Models.ChatMessage message)
{
var messages = new List<AIChatMessage>();
if (message.ConversationId.HasValue)
{
var historyMessages = await _chatMessageStore.GetHistoryMessagesAsync(message.ConversationId.Value);
// TODO: 应用摘要提示压缩
foreach (var chatMessage in historyMessages)
{
messages.Add(new AIChatMessage(chatMessage.Role, chatMessage.GetMessagePrompt()));
}
}
messages.Add(new AIChatMessage(ChatRole.User, message.GetMessagePrompt()));
return messages;
}
protected async virtual Task<Guid> StoreChatMessage(Models.ChatMessage message, string agentMessage)
{
message.WithReply(agentMessage, _clock.Now);
return await _chatMessageStore.SaveMessageAsync(message);
}
protected async virtual Task<Guid> StoreConversation(Models.ChatMessage message)
{
if (message.ConversationId.HasValue)
{
var conversation = await _conversationStore.FindAsync(message.ConversationId.Value);
if (conversation == null || conversation.ExpiredAt <= _clock.Now)
{
throw new BusinessException(
AbpAIErrorCodes.ConversationHasExpired,
"The conversation has expired. Please create a new one!");
}
conversation.UpdateAt = _clock.Now;
await _conversationStore.SaveAsync(conversation);
return conversation.Id;
}
else
{
var conversation = new Conversation(
_guidGenerator.Create(),
_localizerResource["NewConversation"],
_clock.Now);
await _conversationStore.SaveAsync(conversation);
return conversation.Id;
}
}
protected async virtual Task StoreTokenUsageInfo(TokenUsageInfo tokenUsageInfo)
{
await _tokenUsageStore.SaveTokenUsageAsync(tokenUsageInfo);
}
private static void UpdateTokenUsageInfo(TokenUsageInfo tokenUsageInfo, AgentRunResponseUpdate response)
{
if (response.RawRepresentation != null &&
response.RawRepresentation is ChatResponseUpdate update)
{
var usageContents = update.Contents.OfType<UsageContent>();
tokenUsageInfo.InputTokenCount = usageContents.Max(x => x.Details.InputTokenCount);
tokenUsageInfo.OutputTokenCount = usageContents.Max(x => x.Details.OutputTokenCount);
tokenUsageInfo.TotalTokenCount = usageContents.Max(x => x.Details.TotalTokenCount);
tokenUsageInfo.ReasoningTokenCount = usageContents.Max(x => x.Details.ReasoningTokenCount);
tokenUsageInfo.CachedInputTokenCount = usageContents.Max(x => x.Details.CachedInputTokenCount);
}
}
}

80
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/ChatClientAgentFactory.cs

@ -1,80 +0,0 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Localization;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Volo.Abp.AI;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Agent;
public class ChatClientAgentFactory : IChatClientAgentFactory, ISingletonDependency
{
private readonly static ConcurrentDictionary<string, ChatClientAgent> _chatClientAgentCache = new();
private readonly IChatClientFactory _chatClientFactory;
private readonly IStringLocalizerFactory _stringLocalizerFactory;
private readonly IWorkspaceDefinitionManager _workspaceDefinitionManager;
public ChatClientAgentFactory(
IChatClientFactory chatClientFactory,
IStringLocalizerFactory stringLocalizerFactory,
IWorkspaceDefinitionManager workspaceDefinitionManager)
{
_chatClientFactory = chatClientFactory;
_stringLocalizerFactory = stringLocalizerFactory;
_workspaceDefinitionManager = workspaceDefinitionManager;
}
public async virtual Task<ChatClientAgent> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
if (_chatClientAgentCache.TryGetValue(workspace, out var chatClientAgent))
{
return chatClientAgent;
}
var chatClient = await _chatClientFactory.CreateAsync<TWorkspace>();
var workspaceDefine = await _workspaceDefinitionManager.GetOrNullAsync(workspace);
string? description = null;
if (workspaceDefine?.Description != null)
{
description = workspaceDefine.Description.Localize(_stringLocalizerFactory);
}
chatClientAgent = chatClient.CreateAIAgent(
instructions: workspaceDefine?.SystemPrompt,
name: workspaceDefine?.Name,
description: description);
_chatClientAgentCache.TryAdd(workspace, chatClientAgent);
return chatClientAgent;
}
public async virtual Task<ChatClientAgent> CreateAsync(string workspace)
{
if (_chatClientAgentCache.TryGetValue(workspace, out var chatClientAgent))
{
return chatClientAgent;
}
var workspaceDefine = await _workspaceDefinitionManager.GetAsync(workspace);
var chatClient = await _chatClientFactory.CreateAsync(workspace);
string? description = null;
if (workspaceDefine.Description != null)
{
description = workspaceDefine.Description.Localize(_stringLocalizerFactory);
}
chatClientAgent = chatClient.CreateAIAgent(
instructions: workspaceDefine.SystemPrompt,
name: workspaceDefine.Name,
description: description);
_chatClientAgentCache.TryAdd(workspace, chatClientAgent);
return chatClientAgent;
}
}

6
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IChatClientAgentFactory.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IAgentFactory.cs

@ -3,11 +3,11 @@ using Microsoft.Agents.AI;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Agent;
public interface IChatClientAgentFactory
public interface IAgentFactory
{
[NotNull]
Task<ChatClientAgent> CreateAsync<TWorkspace>();
Task<AIAgent> CreateAsync<TWorkspace>();
[NotNull]
Task<ChatClientAgent> CreateAsync(string workspace);
Task<AIAgent> CreateAsync(string workspace);
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/IAgentService.cs

@ -0,0 +1,8 @@
using LINGYUN.Abp.AI.Models;
using System.Collections.Generic;
namespace LINGYUN.Abp.AI.Agent;
public interface IAgentService
{
IAsyncEnumerable<string> SendMessageAsync(ChatMessage message);
}

59
aspnet-core/modules/ai/LINGYUN.Abp.AI.Agent/LINGYUN/Abp/AI/Agent/WorkspaceAIAgent.cs

@ -0,0 +1,59 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Agent;
public class WorkspaceAIAgent : AIAgent
{
protected AIAgent InnerAgent { get; }
protected WorkspaceDefinition? Workspace { get; }
public WorkspaceAIAgent(AIAgent innerAgent, WorkspaceDefinition? workspace)
{
InnerAgent = innerAgent;
Workspace = workspace;
}
public override AgentThread DeserializeThread(JsonElement serializedThread, JsonSerializerOptions? jsonSerializerOptions = null)
{
return InnerAgent.DeserializeThread(serializedThread, jsonSerializerOptions);
}
public override AgentThread GetNewThread()
{
return InnerAgent.GetNewThread();
}
protected override Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
{
return InnerAgent.RunAsync(GetChatMessages(messages), thread, options, cancellationToken);
}
protected override IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
{
return InnerAgent.RunStreamingAsync(GetChatMessages(messages), thread, options, cancellationToken);
}
protected virtual IEnumerable<ChatMessage> GetChatMessages(IEnumerable<ChatMessage> messages)
{
var unionMessages = new List<ChatMessage>();
if (Workspace != null)
{
if (!Workspace.SystemPrompt.IsNullOrWhiteSpace())
{
unionMessages.Add(new ChatMessage(ChatRole.System, Workspace.SystemPrompt));
}
if (!Workspace.Instructions.IsNullOrWhiteSpace())
{
unionMessages.Add(new ChatMessage(ChatRole.System, Workspace.Instructions));
}
}
return unionMessages.Union(messages);
}
}

7
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN.Abp.AI.Core.csproj

@ -14,9 +14,16 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\AI\Localization\Resources\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\AI\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AI" />
<PackageReference Include="Volo.Abp.Localization" />
<PackageReference Include="Volo.Abp.Guids" />
<PackageReference Include="Volo.Abp.Timing" />
</ItemGroup>
</Project>

27
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAICoreModule.cs

@ -1,16 +1,23 @@
using LINGYUN.Abp.AI.Localization;
using LINGYUN.Abp.AI.Internal;
using LINGYUN.Abp.AI.Localization;
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using Volo.Abp.AI;
using Volo.Abp.Guids;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
using Volo.Abp.Timing;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.AI;
[DependsOn(
typeof(AbpAIModule),
typeof(AbpGuidsModule),
typeof(AbpTimingModule),
typeof(AbpLocalizationModule))]
public class AbpAICoreModule : AbpModule
{
@ -21,14 +28,30 @@ public class AbpAICoreModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAICoreModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources.Add<AbpAIResource>();
options.Resources
.Add<AbpAIResource>()
.AddVirtualJson("/LINGYUN/Abp/AI/Localization/Resources");
});
Configure<AbpAICoreOptions>(options =>
{
options.ChatClientProviders.Add<OpenAIChatClientProvider>();
options.ChatClientProviders.Add<DeepSeekChatClientProvider>();
options.KernelProviders.Add<OpenAIKernelProvider>();
options.KernelProviders.Add<DeepSeekKernelProvider>();
});
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace(AbpAIErrorCodes.Namespace, typeof(AbpAIResource));
});
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/AbpAIErrorCodes.cs

@ -0,0 +1,13 @@
namespace LINGYUN.Abp.AI;
public static class AbpAIErrorCodes
{
public const string Namespace = "Abp.AI";
/// <summary>
/// 工作区不可用: {Workspace}!
/// </summary>
public const string WorkspaceIsNotEnabled = Namespace + ":110001";
/// <summary>
/// 对话已过期, 请重新创建会话!
/// </summary>
public const string ConversationHasExpired = Namespace + ":110101";
}

19
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientProvider.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.AI;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public abstract class ChatClientProvider : IChatClientProvider, ITransientDependency
{
public abstract string Name { get; }
protected IServiceProvider ServiceProvider { get; }
protected ChatClientProvider(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public abstract Task<IChatClient> CreateAsync(WorkspaceDefinition workspace);
}

12
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/IChatMessageStore.cs

@ -0,0 +1,12 @@
using LINGYUN.Abp.AI.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Chats;
public interface IChatMessageStore
{
Task<Guid> SaveMessageAsync(ChatMessage message);
Task<IEnumerable<ChatMessage>> GetHistoryMessagesAsync(Guid conversationId);
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/IConversationStore.cs

@ -0,0 +1,13 @@
using LINGYUN.Abp.AI.Models;
using System;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Chats;
public interface IConversationStore
{
Task SaveAsync(Conversation conversation);
Task<Conversation?> FindAsync(Guid conversationId);
Task CleanupAsync();
}

52
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/InMemoryChatMessageStore.cs

@ -0,0 +1,52 @@
using LINGYUN.Abp.AI.Models;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Chats;
[Dependency(ServiceLifetime.Singleton, TryRegister = true)]
public class InMemoryChatMessageStore : IChatMessageStore
{
private static readonly ConcurrentDictionary<Guid, List<ChatMessage>> _userMessageCache = new ConcurrentDictionary<Guid, List<ChatMessage>>();
public Task<IEnumerable<ChatMessage>> GetHistoryMessagesAsync(Guid conversationId)
{
var messages = new List<ChatMessage>();
foreach (var userMessages in _userMessageCache.Values)
{
messages.AddRange(userMessages.Where(x => x.ConversationId == conversationId));
}
return Task.FromResult<IEnumerable<ChatMessage>>(
messages
.OrderByDescending(x => x.CreatedAt)
.Take(5)
.OrderBy(x => x.CreatedAt));
}
public Task<Guid> SaveMessageAsync(ChatMessage message)
{
var messageId = message.Id;
if (!messageId.HasValue)
{
messageId = Guid.NewGuid();
message.WithMessageId(messageId.Value);
}
if (_userMessageCache.ContainsKey(messageId.Value))
{
_userMessageCache[messageId.Value].Add(message);
}
else
{
_userMessageCache[messageId.Value] = new List<ChatMessage>() { message };
}
return Task.FromResult(messageId.Value);
}
}

48
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Chats/InMemoryConversationStore.cs

@ -0,0 +1,48 @@
using LINGYUN.Abp.AI.Models;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Chats;
[Dependency(ServiceLifetime.Singleton, TryRegister = true)]
public class InMemoryConversationStore : IConversationStore
{
private static readonly ConcurrentDictionary<Guid, Conversation> _conversationCache = new ConcurrentDictionary<Guid, Conversation>();
public Task SaveAsync(Conversation conversation)
{
if (_conversationCache.ContainsKey(conversation.Id))
{
conversation.ExpiredAt = DateTime.Now.AddHours(2);
_conversationCache[conversation.Id] = conversation;
}
else
{
_conversationCache.TryAdd(conversation.Id, conversation);
}
return Task.CompletedTask;
}
public Task<Conversation?> FindAsync(Guid conversationId)
{
_conversationCache.TryGetValue(conversationId, out var conversation);
return Task.FromResult<Conversation?>(conversation);
}
public Task CleanupAsync()
{
// Configure it...
var expiredTime = DateTime.Now.AddHours(-2);
var expiredConversationIds = _conversationCache.Values
.Where(x => x.UpdateAt <= expiredTime)
.Select(x => x.Id);
_conversationCache.RemoveAll(x => expiredConversationIds.Contains(x.Key));
return Task.CompletedTask;
}
}

49
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientFactory.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/ChatClientFactory.cs

@ -1,25 +1,28 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.Extensions.AI;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AI;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.SimpleStateChecking;
namespace LINGYUN.Abp.AI;
public class ChatClientFactory : IChatClientFactory, ISingletonDependency
namespace LINGYUN.Abp.AI.Internal;
public class ChatClientFactory : IChatClientFactory, IScopedDependency
{
private readonly static ConcurrentDictionary<string, IChatClient> _chatClientCache = new();
protected ISimpleStateCheckerManager<WorkspaceDefinition> StateCheckerManager { get; }
protected IWorkspaceDefinitionManager WorkspaceDefinitionManager { get; }
protected IChatClientProviderManager ChatClientProviderManager { get; }
protected IServiceProvider ServiceProvider { get; }
public ChatClientFactory(
ISimpleStateCheckerManager<WorkspaceDefinition> stateCheckerManager,
IWorkspaceDefinitionManager workspaceDefinitionManager,
IChatClientProviderManager chatClientProviderManager,
IServiceProvider serviceProvider)
{
StateCheckerManager = stateCheckerManager;
WorkspaceDefinitionManager = workspaceDefinitionManager;
ChatClientProviderManager = chatClientProviderManager;
ServiceProvider = serviceProvider;
@ -28,10 +31,6 @@ public class ChatClientFactory : IChatClientFactory, ISingletonDependency
public async virtual Task<IChatClient> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
if (_chatClientCache.TryGetValue(workspace, out var chatClient))
{
return chatClient;
}
var chatClientAccessorType = typeof(IChatClientAccessor<>).MakeGenericType(typeof(TWorkspace));
var chatClientAccessor = ServiceProvider.GetService(chatClientAccessorType);
@ -39,30 +38,19 @@ public class ChatClientFactory : IChatClientFactory, ISingletonDependency
chatClientAccessor is IChatClientAccessor accessor &&
accessor.ChatClient != null)
{
chatClient = accessor.ChatClient;
_chatClientCache.TryAdd(workspace, chatClient);
}
else
{
chatClient = await CreateAsync(workspace);
return accessor.ChatClient;
}
return chatClient;
return await CreateAsync(workspace);
}
public async virtual Task<IChatClient> CreateAsync(string workspace)
{
if (_chatClientCache.TryGetValue(workspace, out var chatClient))
{
return chatClient;
}
var workspaceDefine = await WorkspaceDefinitionManager.GetAsync(workspace);
chatClient = await CreateChatClientAsync(workspaceDefine);
_chatClientCache.TryAdd(workspace, chatClient);
await CheckWorkspaceStateAsync(workspaceDefine);
return chatClient;
return await CreateChatClientAsync(workspaceDefine);
}
protected async virtual Task<IChatClient> CreateChatClientAsync(WorkspaceDefinition workspace)
@ -77,6 +65,17 @@ public class ChatClientFactory : IChatClientFactory, ISingletonDependency
return await provider.CreateAsync(workspace);
}
throw new AbpException($"The ChatClient provider implementation named {workspace.Provider} was not found");
throw new AbpException($"The ChatClient provider implementation named {workspace.Provider} was not found!");
}
protected async virtual Task CheckWorkspaceStateAsync(WorkspaceDefinition workspace)
{
if (!await StateCheckerManager.IsEnabledAsync(workspace))
{
throw new AbpAuthorizationException(
$"Workspace is not enabled: {workspace.Name}!",
AbpAIErrorCodes.WorkspaceIsNotEnabled)
.WithData("Workspace", workspace.Name);
}
}
}

2
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/ChatClientProviderManager.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/ChatClientProviderManager.cs

@ -7,7 +7,7 @@ using System.Linq;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
namespace LINGYUN.Abp.AI.Internal;
public class ChatClientProviderManager : IChatClientProviderManager, ISingletonDependency
{
public List<IChatClientProvider> Providers => _lazyProviders.Value;

15
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/DeepSeekChatClientProvider.cs

@ -0,0 +1,15 @@
using System;
namespace LINGYUN.Abp.AI.Internal;
public class DeepSeekChatClientProvider : OpenAIChatClientProvider
{
protected override string DefaultEndpoint => "https://api.deepseek.com/v1";
public new const string ProviderName = "DeepSeek";
public override string Name => ProviderName;
public DeepSeekChatClientProvider(
IServiceProvider serviceProvider)
: base(serviceProvider)
{
}
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/DeepSeekKernelProvider.cs

@ -0,0 +1,13 @@
using System;
namespace LINGYUN.Abp.AI.Internal;
public class DeepSeekKernelProvider : OpenAIKernelProvider
{
protected override string DefaultEndpoint => "https://api.deepseek.com/v1";
public new const string ProviderName = "DeepSeek";
public override string Name => ProviderName;
public DeepSeekKernelProvider(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
}

47
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelFactory.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/KernelFactory.cs

@ -1,25 +1,28 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.SemanticKernel;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AI;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.SimpleStateChecking;
namespace LINGYUN.Abp.AI;
public class KernelFactory : IKernelFactory, ISingletonDependency
namespace LINGYUN.Abp.AI.Internal;
public class KernelFactory : IKernelFactory, IScopedDependency
{
private readonly static ConcurrentDictionary<string, Kernel> _kernelCache = new();
protected ISimpleStateCheckerManager<WorkspaceDefinition> StateCheckerManager { get; }
protected IWorkspaceDefinitionManager WorkspaceDefinitionManager { get; }
protected IKernelProviderManager KernelProviderManager { get; }
protected IServiceProvider ServiceProvider { get; }
public KernelFactory(
ISimpleStateCheckerManager<WorkspaceDefinition> stateCheckerManager,
IWorkspaceDefinitionManager workspaceDefinitionManager,
IKernelProviderManager kernelProviderManager,
IServiceProvider serviceProvider)
{
StateCheckerManager = stateCheckerManager;
WorkspaceDefinitionManager = workspaceDefinitionManager;
KernelProviderManager = kernelProviderManager;
ServiceProvider = serviceProvider;
@ -28,10 +31,6 @@ public class KernelFactory : IKernelFactory, ISingletonDependency
public async virtual Task<Kernel> CreateAsync<TWorkspace>()
{
var workspace = WorkspaceNameAttribute.GetWorkspaceName<TWorkspace>();
if (_kernelCache.TryGetValue(workspace, out var kernel))
{
return kernel;
}
var kernelAccessorType = typeof(IKernelAccessor<>).MakeGenericType(typeof(TWorkspace));
var kernelAccessor = ServiceProvider.GetService(kernelAccessorType);
@ -39,30 +38,18 @@ public class KernelFactory : IKernelFactory, ISingletonDependency
kernelAccessor is IKernelAccessor accessor
&& accessor.Kernel != null)
{
kernel = accessor.Kernel;
_kernelCache.TryAdd(workspace, kernel);
}
else
{
kernel = await CreateAsync(workspace);
return accessor.Kernel;
}
return kernel;
return await CreateAsync(workspace);
}
public async virtual Task<Kernel> CreateAsync(string workspace)
{
if (_kernelCache.TryGetValue(workspace, out var kernel))
{
return kernel;
}
var workspaceDefine = await WorkspaceDefinitionManager.GetAsync(workspace);
kernel = await CreateKernelAsync(workspaceDefine);
_kernelCache.TryAdd(workspace, kernel);
await CheckWorkspaceStateAsync(workspaceDefine);
return kernel;
return await CreateKernelAsync(workspaceDefine);
}
protected async virtual Task<Kernel> CreateKernelAsync(WorkspaceDefinition workspace)
@ -77,6 +64,16 @@ public class KernelFactory : IKernelFactory, ISingletonDependency
return await provider.CreateAsync(workspace);
}
throw new AbpException($"The Kernel provider implementation named {workspace.Provider} was not found");
throw new AbpException($"The Kernel provider implementation named {workspace.Provider} was not found!");
}
protected async virtual Task CheckWorkspaceStateAsync(WorkspaceDefinition workspace)
{
if (!await StateCheckerManager.IsEnabledAsync(workspace))
{
throw new AbpAuthorizationException(
$"Workspace is not enabled: {workspace.Name}!",
AbpAIErrorCodes.WorkspaceIsNotEnabled)
.WithData("Workspace", workspace.Name);
}
}
}

2
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelProviderManager.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/KernelProviderManager.cs

@ -6,7 +6,7 @@ using System.Linq;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
namespace LINGYUN.Abp.AI.Internal;
public class KernelProviderManager : IKernelProviderManager, ISingletonDependency
{
public List<IKernelProvider> Providers => _lazyProviders.Value;

25
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/OpenAIChatClientProvider.cs → aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/OpenAIChatClientProvider.cs

@ -5,17 +5,20 @@ using System;
using System.ClientModel;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public class OpenAIChatClientProvider : IChatClientProvider, ITransientDependency
namespace LINGYUN.Abp.AI.Internal;
public class OpenAIChatClientProvider : ChatClientProvider
{
private const string DefaultEndpoint = "https://api.openai.com/v1";
public const string ProviderName = "OpenAI";
protected virtual string DefaultEndpoint => "https://api.openai.com/v1";
public virtual string Name => ProviderName;
public const string ProviderName = "OpenAI";
public override string Name => ProviderName;
public OpenAIChatClientProvider(IServiceProvider serviceProvider)
: base(serviceProvider)
{
}
public virtual Task<IChatClient> CreateAsync(WorkspaceDefinition workspace)
public override Task<IChatClient> CreateAsync(WorkspaceDefinition workspace)
{
Check.NotNull(workspace, nameof(workspace));
Check.NotNullOrWhiteSpace(workspace.ApiKey, nameof(WorkspaceDefinition.ApiKey));
@ -29,7 +32,13 @@ public class OpenAIChatClientProvider : IChatClientProvider, ITransientDependenc
var chatClient = openAIClient
.GetChatClient(workspace.ModelName)
.AsIChatClient();
.AsIChatClient()
.AsBuilder()
.UseLogging()
.UseOpenTelemetry()
.UseFunctionInvocation()
.UseDistributedCache()
.Build(ServiceProvider);
return Task.FromResult(chatClient);
}

39
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Internal/OpenAIKernelProvider.cs

@ -0,0 +1,39 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.SemanticKernel;
using OpenAI;
using System;
using System.ClientModel;
using System.Threading.Tasks;
using Volo.Abp;
namespace LINGYUN.Abp.AI.Internal;
public class OpenAIKernelProvider : KernelProvider
{
protected virtual string DefaultEndpoint { get; set; } = "https://api.openai.com/v1";
public const string ProviderName = "OpenAI";
public override string Name => ProviderName;
public OpenAIKernelProvider(IServiceProvider serviceProvider)
: base(serviceProvider)
{
}
public override Task<Kernel> CreateAsync(WorkspaceDefinition workspace)
{
Check.NotNull(workspace, nameof(workspace));
Check.NotNullOrWhiteSpace(workspace.ApiKey, nameof(WorkspaceDefinition.ApiKey));
var openAIClient = new OpenAIClient(
new ApiKeyCredential(workspace.ApiKey),
new OpenAIClientOptions
{
Endpoint = new Uri(workspace.ApiBaseUrl ?? DefaultEndpoint),
});
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatClient(workspace.ModelName, openAIClient)
.Build();
return Task.FromResult(kernel);
}
}

19
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/KernelProvider.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.AI.Workspaces;
using Microsoft.SemanticKernel;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI;
public abstract class KernelProvider : IKernelProvider, ITransientDependency
{
public abstract string Name { get; }
protected IServiceProvider ServiceProvider { get; }
protected KernelProvider(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public abstract Task<Kernel> CreateAsync(WorkspaceDefinition workspace);
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Localization/Resources/en.json

@ -0,0 +1,8 @@
{
"culture": "en",
"texts": {
"Abp.AI:110001": "Workspace is not enabled: {Workspace}!",
"Abp.AI:110101": "The conversation has expired. Please create a new one!",
"NewConversation": "New Conversation"
}
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Localization/Resources/zh-Hans.json

@ -0,0 +1,8 @@
{
"culture": "zh-Hans",
"texts": {
"Abp.AI:110001": "工作区不可用: {Workspace}!",
"Abp.AI:110101": "对话已过期, 请重新创建会话!",
"NewConversation": "新对话"
}
}

53
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/ChatMessage.cs

@ -0,0 +1,53 @@
using Microsoft.Extensions.AI;
using System;
namespace LINGYUN.Abp.AI.Models;
public abstract class ChatMessage
{
public string Workspace { get; }
public Guid? Id { get; private set; }
public Guid? ConversationId { get; private set; }
public string? ReplyMessage { get; private set; }
public DateTime? ReplyAt { get; private set; }
public ChatRole Role { get; private set; }
public DateTime CreatedAt { get; private set; }
protected ChatMessage(
string workspace,
ChatRole? role = null,
DateTime? createdAt = null)
{
Workspace = workspace;
Role = role ?? ChatRole.User;
CreatedAt = createdAt ?? DateTime.Now;
}
public virtual ChatMessage WithMessageId(Guid id)
{
Id = id;
return this;
}
public virtual ChatMessage WithConversationId(Guid conversationId)
{
ConversationId = conversationId;
return this;
}
public virtual ChatMessage WithReply(string replyMessage, DateTime replyAt)
{
ReplyMessage = replyMessage;
ReplyAt = replyAt;
return this;
}
public virtual string GetMessagePrompt()
{
return string.Empty;
}
}

28
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/Conversation.cs

@ -0,0 +1,28 @@
using System;
namespace LINGYUN.Abp.AI.Models;
public class Conversation
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public DateTime CreatedAt { get; private set; }
public DateTime? ExpiredAt { get; set; }
public DateTime? UpdateAt { get; set; }
public Conversation(
Guid id,
string name,
DateTime createdAt)
{
Id = id;
Name = name;
CreatedAt = createdAt;
UpdateAt = createdAt;
}
public Conversation WithName(string name)
{
Name = name;
return this;
}
}

13
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/MediaMessage.cs

@ -0,0 +1,13 @@
using Volo.Abp.Content;
namespace LINGYUN.Abp.AI.Models;
public class MediaMessage
{
public string Id { get; }
public IRemoteStreamContent Content { get; }
public MediaMessage(string id, IRemoteStreamContent content)
{
Id = id;
Content = content;
}
}

25
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/TextChatMessage.cs

@ -0,0 +1,25 @@
using Microsoft.Extensions.AI;
using System;
namespace LINGYUN.Abp.AI.Models;
public class TextChatMessage : ChatMessage
{
/// <summary>
/// 消息内容
/// </summary>
public string Content { get; }
public TextChatMessage(
string workspace,
string content,
ChatRole? role = null,
DateTime? createdAt = null)
: base(workspace, role, createdAt)
{
Content = content;
}
public override string GetMessagePrompt()
{
return Content;
}
}

42
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Models/TokenUsageInfo.cs

@ -0,0 +1,42 @@
using System;
using System.Text;
namespace LINGYUN.Abp.AI.Models;
public class TokenUsageInfo
{
public string Workspace { get; }
public Guid? MessageId { get; private set; }
public Guid ConversationId { get; private set; }
public long? InputTokenCount { get; set; }
public long? OutputTokenCount { get; set; }
public long? TotalTokenCount { get; set; }
public long? CachedInputTokenCount { get; set; }
public long? ReasoningTokenCount { get; set; }
public TokenUsageInfo(string workspace, Guid conversationId)
{
Workspace = workspace;
ConversationId = conversationId;
}
public virtual TokenUsageInfo WithMessageId(Guid id)
{
MessageId = id;
return this;
}
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("---------------------- TokenUsage Begin ----------------------");
sb.AppendLine($"====== Workspace - {Workspace}");
sb.AppendLine($"====== MessageId - {MessageId}");
sb.AppendLine($"====== ConversationId - {ConversationId}");
sb.AppendLine($"====== InputTokenCount - {InputTokenCount}");
sb.AppendLine($"====== OutputTokenCount - {OutputTokenCount}");
sb.AppendLine($"====== TotalTokenCount - {TotalTokenCount}");
sb.AppendLine($"====== ReasoningTokenCount - {ReasoningTokenCount}");
sb.AppendLine("---------------------- TokenUsage End ----------------------");
return sb.ToString();
}
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Tokens/ITokenUsageStore.cs

@ -0,0 +1,8 @@
using LINGYUN.Abp.AI.Models;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AI.Tokens;
public interface ITokenUsageStore
{
Task SaveTokenUsageAsync(TokenUsageInfo tokenUsageInfo);
}

28
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Tokens/InMemoryTokenUsageStore.cs

@ -0,0 +1,28 @@
using LINGYUN.Abp.AI.Models;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AI.Tokens;
[Dependency(ServiceLifetime.Singleton, TryRegister = true)]
public class InMemoryTokenUsageStore : ITokenUsageStore
{
private static readonly ConcurrentDictionary<string, List<TokenUsageInfo>> _tokenUsageCache = new ConcurrentDictionary<string, List<TokenUsageInfo>>();
public Task SaveTokenUsageAsync(TokenUsageInfo tokenUsageInfo)
{
if (_tokenUsageCache.TryGetValue(tokenUsageInfo.Workspace, out var tokenUsageInfos))
{
tokenUsageInfos.Add(tokenUsageInfo);
}
else
{
_tokenUsageCache.TryAdd(tokenUsageInfo.Workspace, [tokenUsageInfo]);
}
return Task.CompletedTask;
}
}

11
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Tools/GlobalFunctions.cs

@ -0,0 +1,11 @@
using Microsoft.Extensions.AI;
using System;
namespace LINGYUN.Abp.AI.Tools;
public static class GlobalFunctions
{
public static AITool Now => AIFunctionFactory.Create(
() => DateTime.Now,
nameof(Now),
"Get now time");
}

86
aspnet-core/modules/ai/LINGYUN.Abp.AI.Core/LINGYUN/Abp/AI/Workspaces/WorkspaceDefinition.cs

@ -41,16 +41,84 @@ public class WorkspaceDefinition : IHasSimpleStateCheckers<WorkspaceDefinition>
/// <summary>
/// API 身份验证密钥
/// </summary>
public string? ApiKey { get; set; }
public string? ApiKey { get; private set; }
/// <summary>
/// 自定义端点 URL
/// </summary>
public string? ApiBaseUrl { get; set; }
public string? ApiBaseUrl { get; private set; }
/// <summary>
/// 系统提示词
/// </summary>
public string? SystemPrompt { get; set; }
/// <summary>
/// 附加系统提示词
/// </summary>
public string? Instructions { get; set; }
/// <summary>
/// 聊天回复时所依据的温度值, 为空时由模型提供者决定默认值
/// </summary>
/// <remarks>
/// 范围在 0 到 2 之间, 数值越高(比如 0.8)会使输出更加随机,而数值越低(比如 0.2)则会使输出更加集中且更具确定性
/// </remarks>
public float? Temperature {
get => _temperature;
set {
if (value.HasValue)
{
_temperature = Check.Range(value.Value, nameof(value), 0, 2);
}
else
{
_temperature = value;
}
}
}
private float? _temperature;
/// <summary>
/// 限制一次请求中模型生成 completion 的最大 token 数
/// </summary>
public int? MaxOutputTokens { get; set; }
/// <summary>
/// 介于 -2.0 和 2.0 之间的数字
/// </summary>
/// <remarks>
/// 如果该值为正,那么新 token 会根据其在已有文本中的出现频率受到相应的惩罚,降低模型重复相同内容的可能性
/// </remarks>
public float? FrequencyPenalty {
get => _frequencyPenalty;
set {
if (value.HasValue)
{
_frequencyPenalty = Check.Range(value.Value, nameof(value), -2, 2);
}
else
{
_frequencyPenalty = value;
}
}
}
private float? _frequencyPenalty;
/// <summary>
/// 介于 -2.0 和 2.0 之间的数字
/// </summary>
/// <remarks>
/// 如果该值为正,那么新 token 会根据其是否已在已有文本中出现受到相应的惩罚,从而增加模型谈论新主题的可能性
/// </remarks>
public float? PresencePenalty {
get => _presencePenalty;
set {
if (value.HasValue)
{
_presencePenalty = Check.Range(value.Value, nameof(value), -2, 2);
}
else
{
_presencePenalty = value;
}
}
}
private float? _presencePenalty;
/// <summary>
/// 启用/禁用工作区
/// </summary>
public bool IsEnabled { get; set; }
@ -65,7 +133,13 @@ public class WorkspaceDefinition : IHasSimpleStateCheckers<WorkspaceDefinition>
string provider,
string modelName,
ILocalizableString displayName,
ILocalizableString? description = null)
ILocalizableString? description = null,
string? systemPrompt = null,
string? instructions = null,
float? temperature = null,
int? maxOutputTokens = null,
float? frequencyPenalty = null,
float? presencePenalty = null)
{
Name = name;
Provider = provider;
@ -73,6 +147,12 @@ public class WorkspaceDefinition : IHasSimpleStateCheckers<WorkspaceDefinition>
_displayName = displayName;
_displayName = displayName;
Description = description;
SystemPrompt = systemPrompt;
Instructions = instructions;
Temperature = temperature;
MaxOutputTokens = maxOutputTokens;
FrequencyPenalty = frequencyPenalty;
PresencePenalty = presencePenalty;
IsEnabled = true;
Properties = new Dictionary<string, object>();

3
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/FodyWeavers.xsd

@ -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>

26
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN.Abp.AIManagement.Application.Contracts.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AIManagement.Application.Contracts</AssemblyName>
<PackageId>LINGYUN.Abp.AIManagement.Application.Contracts</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" />
<PackageReference Include="Volo.Abp.Authorization.Abstractions" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.AIManagement.Domain.Shared\LINGYUN.Abp.AIManagement.Domain.Shared.csproj" />
</ItemGroup>
</Project>

7
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AIManagementRemoteServiceConsts.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Abp.AIManagement;
public static class AIManagementRemoteServiceConsts
{
public const string RemoteServiceName = "AbpAIManagement";
public const string ModuleName = "ai-management";
}

14
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationContractsModule.cs

@ -0,0 +1,14 @@
using Volo.Abp.Application;
using Volo.Abp.Authorization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AIManagement;
[DependsOn(
typeof(AbpAIManagementDomainSharedModule),
typeof(AbpDddApplicationContractsModule),
typeof(AbpAuthorizationAbstractionsModule))]
public class AbpAIManagementApplicationContractsModule : AbpModule
{
}

14
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ChatMessageDto.cs

@ -0,0 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public abstract class ChatMessageDto : ExtensibleAuditedEntityDto<Guid>
{
public string Workspace { get; set; }
public DateTime CreatedAt { get; set; }
public Guid? UserId { get; set; }
public Guid? ConversationId { get; set; }
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationCreateDto.cs

@ -0,0 +1,8 @@
using Volo.Abp.Validation;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public class ConversationCreateDto
{
[DynamicStringLength(typeof(ConversationRecordConsts), nameof(ConversationRecordConsts.MaxNameLength))]
public string? Name { get; set; }
}

14
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationDto.cs

@ -0,0 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public class ConversationDto : AuditedEntityDto<Guid>
{
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime ExpiredAt { get; set; }
public DateTime? UpdateAt { get; set; }
}

7
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationGetListInput.cs

@ -0,0 +1,7 @@
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public class ConversationGetListInput : PagedAndSortedResultRequestDto
{
public string? Filter { get; set; }
}

10
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/ConversationUpdateDto.cs

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public class ConversationUpdateDto
{
[Required]
[DynamicStringLength(typeof(ConversationRecordConsts), nameof(ConversationRecordConsts.MaxNameLength))]
public string Name { get; set; }
}

19
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/SendTextChatMessageDto.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.AIManagement.Workspaces;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public class SendTextChatMessageDto
{
[Required]
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxNameLength))]
public string Workspace { get; set; }
[Required]
public Guid ConversationId { get; set; }
[Required]
[DynamicStringLength(typeof(TextChatMessageRecordConsts), nameof(TextChatMessageRecordConsts.MaxContentLength))]
public string Content { get; set; }
}

8
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/Dtos/TextChatMessageDto.cs

@ -0,0 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace LINGYUN.Abp.AIManagement.Chats.Dtos;
public class TextChatMessageDto
{
}

9
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/IChatAppService.cs

@ -0,0 +1,9 @@
using LINGYUN.Abp.AIManagement.Chats.Dtos;
using System.Collections.Generic;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.AIManagement.Chats;
public interface IChatAppService : IApplicationService
{
IAsyncEnumerable<string> SendMessageAsync(SendTextChatMessageDto input);
}

14
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Chats/IConversationAppService.cs

@ -0,0 +1,14 @@
using LINGYUN.Abp.AIManagement.Chats.Dtos;
using System;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.AIManagement.Chats;
public interface IConversationAppService :
ICrudAppService<
ConversationDto,
Guid,
ConversationGetListInput,
ConversationCreateDto,
ConversationUpdateDto>
{
}

10
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateDto.cs

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos;
public class WorkspaceDefinitionRecordCreateDto : WorkspaceDefinitionRecordCreateOrUpdateDto
{
[Required]
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxNameLength))]
public string Name { get; set; }
}

47
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordCreateOrUpdateDto.cs

@ -0,0 +1,47 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.ObjectExtending;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos;
public abstract class WorkspaceDefinitionRecordCreateOrUpdateDto : ExtensibleObject
{
[Required]
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxProviderLength))]
public string Provider { get; set; }
[Required]
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxModelNameLength))]
public string ModelName { get; set; }
[Required]
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxDisplayNameLength))]
public string DisplayName { get; set; }
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxDescriptionLength))]
public string? Description { get; set; }
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxApiKeyLength))]
public string? ApiKey { get; set; }
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxApiBaseUrlLength))]
public string? ApiBaseUrl { get; set; }
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxSystemPromptLength))]
public string? SystemPrompt { get; set; }
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxInstructionsLength))]
public string? Instructions { get; set; }
public float? Temperature { get; set; }
public int? MaxOutputTokens { get; set; }
public float? FrequencyPenalty { get; set; }
public float? PresencePenalty { get; set; }
public bool IsEnabled { get; set; }
[DynamicStringLength(typeof(WorkspaceDefinitionRecordConsts), nameof(WorkspaceDefinitionRecordConsts.MaxStateCheckersLength))]
public string? StateCheckers { get; set; }
}

39
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordDto.cs

@ -0,0 +1,39 @@
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos;
[Serializable]
public class WorkspaceDefinitionRecordDto : ExtensibleAuditedEntityDto<Guid>, IHasConcurrencyStamp
{
public string Name { get; set; }
public string Provider { get; set; }
public string ModelName { get; set; }
public string DisplayName { get; set; }
public string? Description { get; set; }
public string? ApiBaseUrl { get; set; }
public string? SystemPrompt { get; set; }
public string? Instructions { get; set; }
public float? Temperature { get; set; }
public int? MaxOutputTokens { get; set; }
public float? FrequencyPenalty { get; set; }
public float? PresencePenalty { get; set; }
public bool IsEnabled { get; set; }
public string? StateCheckers { get; set; }
public string ConcurrencyStamp { get; set; }
}

14
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordGetListInput.cs

@ -0,0 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos;
[Serializable]
public class WorkspaceDefinitionRecordGetListInput : PagedAndSortedResultRequestDto
{
public string? Filter { get; set; }
public string? Provider { get; set; }
public string? ModelName { get; set; }
}

10
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/Dtos/WorkspaceDefinitionRecordUpdateDto.cs

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.AIManagement.Workspaces.Dtos;
public class WorkspaceDefinitionRecordUpdateDto : WorkspaceDefinitionRecordCreateOrUpdateDto, IHasConcurrencyStamp
{
[Required]
[StringLength(40)]
public string ConcurrencyStamp { get; set; }
}

14
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application.Contracts/LINGYUN/Abp/AIManagement/Workspaces/IWorkspaceDefinitionAppService.cs

@ -0,0 +1,14 @@
using LINGYUN.Abp.AIManagement.Workspaces.Dtos;
using System;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.AIManagement.Workspaces;
public interface IWorkspaceDefinitionAppService :
ICrudAppService<
WorkspaceDefinitionRecordDto,
Guid,
WorkspaceDefinitionRecordGetListInput,
WorkspaceDefinitionRecordCreateDto,
WorkspaceDefinitionRecordUpdateDto>
{
}

3
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/FodyWeavers.xsd

@ -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>

26
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN.Abp.AIManagement.Application.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.AIManagement.Application</AssemblyName>
<PackageId>LINGYUN.Abp.AIManagement.Application</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.AIManagement.Application.Contracts\LINGYUN.Abp.AIManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.AIManagement.Domain\LINGYUN.Abp.AIManagement.Domain.csproj" />
</ItemGroup>
</Project>

12
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AIManagementApplicationServiceBase.cs

@ -0,0 +1,12 @@
using LINGYUN.Abp.AIManagement.Localization;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.AIManagement;
public abstract class AIManagementApplicationServiceBase : ApplicationService
{
protected AIManagementApplicationServiceBase()
{
LocalizationResource = typeof(AIManagementResource);
ObjectMapperContext = typeof(AbpAIManagementApplicationModule);
}
}

15
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationMappers.cs

@ -0,0 +1,15 @@
using LINGYUN.Abp.AIManagement.Workspaces;
using LINGYUN.Abp.AIManagement.Workspaces.Dtos;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
using Volo.Abp.ObjectExtending;
namespace LINGYUN.Abp.AIManagement;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
[MapExtraProperties(DefinitionChecks = MappingPropertyDefinitionChecks.None)]
public partial class WorkspaceDefinitionRecordToWorkspaceDefinitionRecordDtoMapper : MapperBase<WorkspaceDefinitionRecord, WorkspaceDefinitionRecordDto>
{
public override partial WorkspaceDefinitionRecordDto Map(WorkspaceDefinitionRecord source);
public override partial void Map(WorkspaceDefinitionRecord source, WorkspaceDefinitionRecordDto destination);
}

17
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/AbpAIManagementApplicationModule.cs

@ -0,0 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AIManagement;
[DependsOn(
typeof(AbpAIManagementApplicationContractsModule),
typeof(AbpAIManagementDomainModule),
typeof(AbpDddApplicationModule))]
public class AbpAIManagementApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMapperlyObjectMapper<AbpAIManagementApplicationModule>();
}
}

28
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ChatAppService.cs

@ -0,0 +1,28 @@
using LINGYUN.Abp.AI.Agent;
using LINGYUN.Abp.AI.Models;
using LINGYUN.Abp.AIManagement.Chats.Dtos;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
namespace LINGYUN.Abp.AIManagement.Chats;
public class ChatAppService : AIManagementApplicationServiceBase, IChatAppService
{
private readonly IAgentService _agentService;
public ChatAppService(IAgentService agentService)
{
_agentService = agentService;
}
public IAsyncEnumerable<string> SendMessageAsync(SendTextChatMessageDto input)
{
var chatMessage = new TextChatMessage(
input.Workspace,
input.Content,
ChatRole.User,
Clock.Now);
chatMessage.WithConversationId(input.ConversationId);
return _agentService.SendMessageAsync(chatMessage);
}
}

82
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Chats/ConversationAppService.cs

@ -0,0 +1,82 @@
using LINGYUN.Abp.AIManagement.Chats.Dtos;
using LINGYUN.Abp.AIManagement.Localization;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.AIManagement.Chats;
public class ConversationAppService :
CrudAppService<
ConversationRecord,
ConversationDto,
Guid,
ConversationGetListInput,
ConversationCreateDto,
ConversationUpdateDto>,
IConversationAppService
{
private readonly ConversationCleanupOptions _cleanupOptions;
public ConversationAppService(
IRepository<ConversationRecord, Guid> repository,
IOptions<ConversationCleanupOptions> cleanupOptions)
: base(repository)
{
_cleanupOptions = cleanupOptions.Value;
LocalizationResource = typeof(AIManagementResource);
ObjectMapperContext = typeof(AbpAIManagementApplicationModule);
}
protected async override Task<IQueryable<ConversationRecord>> CreateFilteredQueryAsync(ConversationGetListInput input)
{
var queryable = await base.CreateFilteredQueryAsync(input);
return queryable
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Name.Contains(input.Filter!));
}
protected override ConversationRecord MapToEntity(ConversationCreateDto createInput)
{
var createdAt = Clock.Now;
var expiredTime = createdAt.Add(_cleanupOptions.ExpiredTime);
var conversationName = createInput.Name ?? L["NewConversation"];
return new ConversationRecord(
GuidGenerator.Create(),
conversationName,
createdAt,
expiredTime,
CurrentTenant.Id);
}
protected override void MapToEntity(ConversationUpdateDto updateInput, ConversationRecord entity)
{
if (!string.Equals(entity.Name, updateInput.Name, StringComparison.InvariantCultureIgnoreCase))
{
entity.SetName(updateInput.Name);
}
}
protected override ConversationDto MapToGetOutputDto(ConversationRecord entity)
{
return new ConversationDto
{
Id = entity.Id,
CreatedAt = entity.CreatedAt,
ExpiredAt = entity.ExpiredAt,
CreationTime = entity.CreationTime,
CreatorId = entity.CreatorId,
LastModificationTime = entity.LastModificationTime,
LastModifierId = entity.LastModifierId,
Name = entity.Name,
UpdateAt = entity.UpdateAt,
};
}
protected override ConversationDto MapToGetListOutputDto(ConversationRecord entity)
{
return MapToGetOutputDto(entity);
}
}

152
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Application/LINGYUN/Abp/AIManagement/Workspaces/WorkspaceDefinitionAppService.cs

@ -0,0 +1,152 @@
using LINGYUN.Abp.AIManagement.Localization;
using LINGYUN.Abp.AIManagement.Workspaces.Dtos;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Data;
using Volo.Abp.Security.Encryption;
namespace LINGYUN.Abp.AIManagement.Workspaces;
public class WorkspaceDefinitionAppService :
CrudAppService<
WorkspaceDefinitionRecord,
WorkspaceDefinitionRecordDto,
Guid,
WorkspaceDefinitionRecordGetListInput,
WorkspaceDefinitionRecordCreateDto,
WorkspaceDefinitionRecordUpdateDto>,
IWorkspaceDefinitionAppService
{
protected IStringEncryptionService StringEncryptionService { get; }
protected IWorkspaceDefinitionRecordRepository WorkspaceDefinitionRecordRepository { get; }
public WorkspaceDefinitionAppService(
IStringEncryptionService stringEncryptionService,
IWorkspaceDefinitionRecordRepository repository) : base(repository)
{
StringEncryptionService = stringEncryptionService;
WorkspaceDefinitionRecordRepository = repository;
LocalizationResource = typeof(AIManagementResource);
ObjectMapperContext = typeof(AbpAIManagementApplicationModule);
}
protected async override Task<IQueryable<WorkspaceDefinitionRecord>> CreateFilteredQueryAsync(WorkspaceDefinitionRecordGetListInput input)
{
var queryable = await base.CreateFilteredQueryAsync(input);
return queryable
.WhereIf(!input.Provider.IsNullOrWhiteSpace(), x => x.Provider == input.Provider)
.WhereIf(!input.ModelName.IsNullOrWhiteSpace(), x => x.ModelName == input.ModelName)
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Provider.Contains(input.Filter!) ||
x.ModelName.Contains(input.Filter!) || x.DisplayName.Contains(input.Filter!) ||
(!x.Description.IsNullOrWhiteSpace() && x.Description.Contains(input.Filter!)) ||
(!x.SystemPrompt.IsNullOrWhiteSpace() && x.SystemPrompt.Contains(input.Filter!)) ||
(!x.Instructions.IsNullOrWhiteSpace() && x.Instructions.Contains(input.Filter!)));
}
protected async override Task<WorkspaceDefinitionRecord> MapToEntityAsync(WorkspaceDefinitionRecordCreateDto createInput)
{
if (await WorkspaceDefinitionRecordRepository.FindByNameAsync(createInput.Name) != null)
{
throw new WorkspaceAlreadyExistsException(createInput.Name);
}
var record = new WorkspaceDefinitionRecord(
GuidGenerator.Create(),
createInput.Name,
createInput.Provider,
createInput.ModelName,
createInput.DisplayName,
createInput.Description,
createInput.SystemPrompt,
createInput.Instructions,
createInput.Temperature,
createInput.MaxOutputTokens,
createInput.FrequencyPenalty,
createInput.PresencePenalty,
createInput.StateCheckers);
if (!createInput.ApiKey.IsNullOrWhiteSpace())
{
var encryptApiKey = StringEncryptionService.Encrypt(createInput.ApiKey);
record.SetApiKey(encryptApiKey, createInput.ApiBaseUrl);
}
return record;
}
protected override void MapToEntity(WorkspaceDefinitionRecordUpdateDto updateInput, WorkspaceDefinitionRecord entity)
{
if (entity.DisplayName != updateInput.DisplayName)
{
entity.SetDisplayName(updateInput.DisplayName);
}
if (entity.Description != updateInput.Description)
{
entity.Description = updateInput.Description;
}
if (entity.Provider != updateInput.Provider || entity.ModelName != updateInput.ModelName)
{
entity.SetModel(updateInput.Provider, updateInput.ModelName);
}
if (entity.SystemPrompt != updateInput.SystemPrompt)
{
entity.SystemPrompt = updateInput.SystemPrompt;
}
if (entity.Instructions != updateInput.Instructions)
{
entity.Instructions = updateInput.Instructions;
}
if (entity.IsEnabled != updateInput.IsEnabled)
{
entity.IsEnabled = updateInput.IsEnabled;
}
if (entity.Temperature != updateInput.Temperature)
{
entity.Temperature = updateInput.Temperature;
}
if (entity.MaxOutputTokens != updateInput.MaxOutputTokens)
{
entity.MaxOutputTokens = updateInput.MaxOutputTokens;
}
if (entity.FrequencyPenalty != updateInput.FrequencyPenalty)
{
entity.FrequencyPenalty = updateInput.FrequencyPenalty;
}
if (entity.PresencePenalty != updateInput.PresencePenalty)
{
entity.PresencePenalty = updateInput.PresencePenalty;
}
if (entity.StateCheckers != updateInput.StateCheckers)
{
entity.StateCheckers = updateInput.StateCheckers;
}
if (!updateInput.ApiKey.IsNullOrWhiteSpace())
{
var encryptApiKey = StringEncryptionService.Encrypt(updateInput.ApiKey);
entity.SetApiKey(encryptApiKey, updateInput.ApiBaseUrl);
}
if (!entity.HasSameExtraProperties(updateInput))
{
entity.ExtraProperties.Clear();
foreach (var property in updateInput.ExtraProperties)
{
entity.ExtraProperties.Add(property.Key, property.Value);
}
}
}
}

3
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/FodyWeavers.xsd

@ -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>

26
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN.Abp.AIManagement.Domain.Shared.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.AIManagement.Domain.Shared</AssemblyName>
<PackageId>LINGYUN.Abp.AIManagement.Domain.Shared</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\AIManagement\Localization\Resources\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\AIManagement\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" />
</ItemGroup>
</Project>

12
aspnet-core/modules/ai/LINGYUN.Abp.AIManagement.Domain.Shared/LINGYUN/Abp/AIManagement/AIManagementErrorCodes.cs

@ -0,0 +1,12 @@
namespace LINGYUN.Abp.AIManagement;
public static class AIManagementErrorCodes
{
public const string Namespace = "AIManagement";
public static class Workspace
{
public const string Prefix = Namespace + ":100";
public const string NameAlreadyExists = Prefix + "001";
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save