diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs
index 6358985b..bc694245 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs
@@ -40,6 +40,11 @@ public class TokenGetListOutputDto
///
public bool IsDisabled { get; set; }
+ ///
+ /// 是否启用请求日志记录
+ ///
+ public bool IsEnableLog { get; set; }
+
///
/// 创建时间
///
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs
index 204fda55..26aec796 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs
@@ -83,6 +83,7 @@ public class TokenService : ApplicationService
PremiumQuotaLimit = t.PremiumQuotaLimit,
PremiumUsedQuota = usedQuota,
IsDisabled = t.IsDisabled,
+ IsEnableLog = t.IsEnableLog,
CreationTime = t.CreationTime
};
}).ToList();
@@ -158,6 +159,7 @@ public class TokenService : ApplicationService
PremiumQuotaLimit = token.PremiumQuotaLimit,
PremiumUsedQuota = 0,
IsDisabled = token.IsDisabled,
+ IsEnableLog = token.IsEnableLog,
CreationTime = token.CreationTime
};
}
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs
index 5e4b0cf9..92a06773 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs
@@ -1,12 +1,15 @@
using System.Text.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Services;
+using Volo.Abp.Uow;
using Volo.Abp.Users;
using Yi.Framework.AiHub.Domain.Entities;
using Yi.Framework.AiHub.Domain.Entities.Chat;
using Yi.Framework.AiHub.Domain.Entities.Model;
+using Yi.Framework.AiHub.Domain.Entities.OpenApi;
using Yi.Framework.AiHub.Domain.Extensions;
using Yi.Framework.AiHub.Domain.Managers;
using Yi.Framework.AiHub.Domain.Shared.Consts;
@@ -33,10 +36,12 @@ public class OpenApiService : ApplicationService
private readonly PremiumPackageManager _premiumPackageManager;
private readonly ISqlSugarRepository _imageStoreRepository;
private readonly ISqlSugarRepository _aiModelRepository;
+ private readonly IServiceScopeFactory _serviceScopeFactory;
public OpenApiService(IHttpContextAccessor httpContextAccessor, ILogger logger,
TokenManager tokenManager, AiGateWayManager aiGateWayManager,
ModelManager modelManager, AiBlacklistManager aiBlacklistManager,
- IAccountService accountService, PremiumPackageManager premiumPackageManager, ISqlSugarRepository imageStoreRepository, ISqlSugarRepository aiModelRepository)
+ IAccountService accountService, PremiumPackageManager premiumPackageManager, ISqlSugarRepository imageStoreRepository, ISqlSugarRepository aiModelRepository,
+ IServiceScopeFactory serviceScopeFactory)
{
_httpContextAccessor = httpContextAccessor;
_logger = logger;
@@ -48,6 +53,7 @@ public class OpenApiService : ApplicationService
_premiumPackageManager = premiumPackageManager;
_imageStoreRepository = imageStoreRepository;
_aiModelRepository = aiModelRepository;
+ _serviceScopeFactory = serviceScopeFactory;
}
///
@@ -91,6 +97,12 @@ public class OpenApiService : ApplicationService
null, tokenId,
CancellationToken.None);
}
+
+ // 记录请求日志
+ if (tokenValidation.IsEnableLog)
+ {
+ FireAndForgetMessageLog(JsonSerializer.Serialize(input), tokenValidation.Token, tokenValidation.TokenName, input.Model, ModelApiTypeEnum.Completions);
+ }
}
@@ -206,6 +218,12 @@ public class OpenApiService : ApplicationService
null, tokenId,
CancellationToken.None);
}
+
+ // 记录请求日志
+ if (tokenValidation.IsEnableLog)
+ {
+ FireAndForgetMessageLog(JsonSerializer.Serialize(input), tokenValidation.Token, tokenValidation.TokenName, input.Model, ModelApiTypeEnum.Messages);
+ }
}
@@ -258,6 +276,12 @@ public class OpenApiService : ApplicationService
null, tokenId,
CancellationToken.None);
}
+
+ // 记录请求日志
+ if (tokenValidation.IsEnableLog)
+ {
+ FireAndForgetMessageLog(JsonSerializer.Serialize(input), tokenValidation.Token, tokenValidation.TokenName, input.Model, ModelApiTypeEnum.Responses);
+ }
}
@@ -318,6 +342,12 @@ public class OpenApiService : ApplicationService
null, tokenId,
CancellationToken.None);
}
+
+ // 记录请求日志
+ if (tokenValidation.IsEnableLog)
+ {
+ FireAndForgetMessageLog(input.GetRawText(), tokenValidation.Token, tokenValidation.TokenName, modelId, ModelApiTypeEnum.GenerateContent);
+ }
}
#region 私有
@@ -357,5 +387,25 @@ public class OpenApiService : ApplicationService
}
}
+ private void FireAndForgetMessageLog(string requestBody, string apiKey, string apiKeyName, string modelId, ModelApiTypeEnum apiType)
+ {
+ _ = Task.Run(async () =>
+ {
+ try
+ {
+ using var scope = _serviceScopeFactory.CreateScope();
+ var uowManager = scope.ServiceProvider.GetRequiredService();
+ var manager = scope.ServiceProvider.GetRequiredService();
+ using var uow = uowManager.Begin(requiresNew: true);
+ await manager.CreateAsync(requestBody, apiKey, apiKeyName, modelId, apiType);
+ await uow.CompleteAsync();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "记录消息日志失败, 请求体长度: {RequestBodyLength}", requestBody?.Length ?? 0);
+ }
+ });
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs
new file mode 100644
index 00000000..038e6316
--- /dev/null
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs
@@ -0,0 +1,49 @@
+using SqlSugar;
+using Volo.Abp.Domain.Entities;
+using Yi.Framework.AiHub.Domain.Shared.Enums;
+
+namespace Yi.Framework.AiHub.Domain.Entities.OpenApi;
+
+[SugarTable("Ai_Message_Log")]
+public class MessageLogAggregateRoot : Entity
+{
+ ///
+ /// 请求内容(httpbody)
+ ///
+ [SugarColumn(ColumnDataType = "text")]
+ public string? RequestBody { get; set; }
+
+ ///
+ /// 请求apikey
+ ///
+ [SugarColumn(Length = 255)]
+ public string ApiKey { get; set; }
+
+ ///
+ /// 请求apikey名称
+ ///
+ [SugarColumn(Length = 255)]
+ public string ApiKeyName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreationTime { get; set; }
+
+ ///
+ /// 模型id
+ ///
+ [SugarColumn(Length = 64)]
+ public string ModelId { get; set; }
+
+ ///
+ /// api类型
+ ///
+ public ModelApiTypeEnum ApiType { get; set; }
+
+ ///
+ /// api类型名称
+ ///
+ [SugarColumn(Length = 16)]
+ public string ApiTypeName { get; set; }
+}
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs
index d5217ca9..6fbe3656 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs
@@ -51,6 +51,11 @@ public class TokenAggregateRoot : FullAuditedAggregateRoot
///
public bool IsDisabled { get; set; }
+ ///
+ /// 是否启用请求日志记录(仅数据库手动修改)
+ ///
+ public bool IsEnableLog { get; set; }
+
///
/// 检查Token是否可用
///
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs
new file mode 100644
index 00000000..4737be73
--- /dev/null
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs
@@ -0,0 +1,34 @@
+using Volo.Abp.Domain.Services;
+using Yi.Framework.AiHub.Domain.Entities.OpenApi;
+using Yi.Framework.AiHub.Domain.Shared.Enums;
+using Yi.Framework.SqlSugarCore.Abstractions;
+
+namespace Yi.Framework.AiHub.Domain.Managers;
+
+public class MessageLogManager : DomainService
+{
+ private readonly ISqlSugarRepository _repository;
+
+ public MessageLogManager(ISqlSugarRepository repository)
+ {
+ _repository = repository;
+ }
+
+ ///
+ /// 创建消息日志
+ ///
+ public async Task CreateAsync(string requestBody, string apiKey, string apiKeyName, string modelId, ModelApiTypeEnum apiType)
+ {
+ var entity = new MessageLogAggregateRoot
+ {
+ RequestBody = requestBody,
+ ApiKey = apiKey,
+ ApiKeyName = apiKeyName,
+ ModelId = modelId,
+ ApiType = apiType,
+ ApiTypeName = apiType.ToString(),
+ CreationTime = DateTime.Now
+ };
+ await _repository.InsertAsync(entity);
+ }
+}
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs
index 9dc1fad9..0145f671 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs
@@ -27,6 +27,16 @@ public class TokenValidationResult
/// token
///
public string Token { get; set; }
+
+ ///
+ /// Token名称
+ ///
+ public string TokenName { get; set; }
+
+ ///
+ /// 是否启用请求日志记录
+ ///
+ public bool IsEnableLog { get; set; }
}
public class TokenManager : DomainService
@@ -117,7 +127,9 @@ public class TokenManager : DomainService
{
UserId = entity.UserId,
TokenId = entity.Id,
- Token = entity.Token
+ Token = entity.Token,
+ TokenName = entity.Name,
+ IsEnableLog = entity.IsEnableLog
};
}
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
index afaa6969..e9f4e792 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
+++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
@@ -361,7 +361,7 @@ namespace Yi.Abp.Web
var app = context.GetApplicationBuilder();
app.UseRouting();
- // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
+ //app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
// app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
// app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();