Merge remote-tracking branch 'origin/ai-hub' into ai-hub
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每日任务配置缓存DTO
|
||||||
|
/// </summary>
|
||||||
|
public class DailyTaskConfigCacheDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 任务配置列表
|
||||||
|
/// </summary>
|
||||||
|
public List<DailyTaskConfigItem> Tasks { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每日任务配置项
|
||||||
|
/// </summary>
|
||||||
|
public class DailyTaskConfigItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 任务等级
|
||||||
|
/// </summary>
|
||||||
|
public int Level { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 需要消耗的Token数量
|
||||||
|
/// </summary>
|
||||||
|
public long RequiredTokens { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 奖励的Token数量
|
||||||
|
/// </summary>
|
||||||
|
public long RewardTokens { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务名称
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务描述
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.Users;
|
using Volo.Abp.Users;
|
||||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
using Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
||||||
using Yi.Framework.AiHub.Domain.Entities;
|
using Yi.Framework.AiHub.Domain.Entities;
|
||||||
@@ -25,27 +27,33 @@ public class DailyTaskService : ApplicationService
|
|||||||
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
||||||
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
||||||
private readonly ILogger<DailyTaskService> _logger;
|
private readonly ILogger<DailyTaskService> _logger;
|
||||||
|
private readonly IDistributedCache<DailyTaskConfigCacheDto> _taskConfigCache;
|
||||||
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||||
private readonly ISqlSugarRepository<AiModelEntity> _aiModelRepository;
|
private readonly ISqlSugarRepository<AiModelEntity> _aiModelRepository;
|
||||||
// 任务配置
|
|
||||||
private readonly Dictionary<int, (long RequiredTokens, long RewardTokens, string Name, string Description)>
|
private const string TaskConfigCacheKey = "AiHub:DailyTaskConfig";
|
||||||
_taskConfigs = new()
|
|
||||||
{
|
// 默认任务配置(当Redis中没有配置时使用)
|
||||||
{ 1, (10000000, 1000000, "尊享包1000w token任务", "累积使用尊享包 1000w token") }, // 1000w消耗 -> 100w奖励
|
private static readonly List<DailyTaskConfigItem> DefaultTaskConfigs = new()
|
||||||
{ 2, (30000000, 2000000, "尊享包3000w token任务", "累积使用尊享包 3000w token") } // 3000w消耗 -> 200w奖励
|
{
|
||||||
};
|
new DailyTaskConfigItem { Level = 1, RequiredTokens = 10000000, RewardTokens = 1000000, Name = "尊享包1000w token任务", Description = "累积使用尊享包 1000w token" },
|
||||||
|
new DailyTaskConfigItem { Level = 2, RequiredTokens = 30000000, RewardTokens = 2000000, Name = "尊享包3000w token任务", Description = "累积使用尊享包 3000w token" }
|
||||||
|
};
|
||||||
|
|
||||||
public DailyTaskService(
|
public DailyTaskService(
|
||||||
ISqlSugarRepository<DailyTaskRewardRecordAggregateRoot> dailyTaskRepository,
|
ISqlSugarRepository<DailyTaskRewardRecordAggregateRoot> dailyTaskRepository,
|
||||||
ISqlSugarRepository<MessageAggregateRoot> messageRepository,
|
ISqlSugarRepository<MessageAggregateRoot> messageRepository,
|
||||||
ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository,
|
ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository,
|
||||||
ILogger<DailyTaskService> logger, ISqlSugarRepository<AiModelEntity> aiModelRepository)
|
ILogger<DailyTaskService> logger,
|
||||||
|
ISqlSugarRepository<AiModelEntity> aiModelRepository,
|
||||||
|
IDistributedCache<DailyTaskConfigCacheDto> taskConfigCache)
|
||||||
{
|
{
|
||||||
_dailyTaskRepository = dailyTaskRepository;
|
_dailyTaskRepository = dailyTaskRepository;
|
||||||
_messageRepository = messageRepository;
|
_messageRepository = messageRepository;
|
||||||
_premiumPackageRepository = premiumPackageRepository;
|
_premiumPackageRepository = premiumPackageRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_aiModelRepository = aiModelRepository;
|
_aiModelRepository = aiModelRepository;
|
||||||
|
_taskConfigCache = taskConfigCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -57,20 +65,23 @@ public class DailyTaskService : ApplicationService
|
|||||||
var userId = CurrentUser.GetId();
|
var userId = CurrentUser.GetId();
|
||||||
var today = DateTime.Today;
|
var today = DateTime.Today;
|
||||||
|
|
||||||
// 1. 统计今日尊享包Token消耗量
|
// 1. 获取任务配置
|
||||||
|
var taskConfigs = await GetTaskConfigsAsync();
|
||||||
|
|
||||||
|
// 2. 统计今日尊享包Token消耗量
|
||||||
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
||||||
|
|
||||||
// 2. 查询今日已领取的任务
|
// 3. 查询今日已领取的任务
|
||||||
var claimedTasks = await _dailyTaskRepository._DbQueryable
|
var claimedTasks = await _dailyTaskRepository._DbQueryable
|
||||||
.Where(x => x.UserId == userId && x.TaskDate == today)
|
.Where(x => x.UserId == userId && x.TaskDate == today)
|
||||||
.Select(x => new { x.TaskLevel, x.IsRewarded })
|
.Select(x => new { x.TaskLevel, x.IsRewarded })
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
// 3. 构建任务列表
|
// 4. 构建任务列表
|
||||||
var tasks = new List<DailyTaskItem>();
|
var tasks = new List<DailyTaskItem>();
|
||||||
foreach (var (level, config) in _taskConfigs)
|
foreach (var config in taskConfigs)
|
||||||
{
|
{
|
||||||
var claimed = claimedTasks.FirstOrDefault(x => x.TaskLevel == level);
|
var claimed = claimedTasks.FirstOrDefault(x => x.TaskLevel == config.Level);
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (claimed != null && claimed.IsRewarded)
|
if (claimed != null && claimed.IsRewarded)
|
||||||
@@ -92,7 +103,7 @@ public class DailyTaskService : ApplicationService
|
|||||||
|
|
||||||
tasks.Add(new DailyTaskItem
|
tasks.Add(new DailyTaskItem
|
||||||
{
|
{
|
||||||
Level = level,
|
Level = config.Level,
|
||||||
Name = config.Name,
|
Name = config.Name,
|
||||||
Description = config.Description,
|
Description = config.Description,
|
||||||
RequiredTokens = config.RequiredTokens,
|
RequiredTokens = config.RequiredTokens,
|
||||||
@@ -121,16 +132,19 @@ public class DailyTaskService : ApplicationService
|
|||||||
await using var handle =
|
await using var handle =
|
||||||
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ClaimTaskRewardLock:{userId}");
|
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ClaimTaskRewardLock:{userId}");
|
||||||
|
|
||||||
|
|
||||||
var today = DateTime.Today;
|
var today = DateTime.Today;
|
||||||
|
|
||||||
// 1. 验证任务等级
|
// 1. 获取任务配置
|
||||||
if (!_taskConfigs.TryGetValue(input.TaskLevel, out var taskConfig))
|
var taskConfigs = await GetTaskConfigsAsync();
|
||||||
|
var taskConfig = taskConfigs.FirstOrDefault(x => x.Level == input.TaskLevel);
|
||||||
|
|
||||||
|
// 2. 验证任务等级
|
||||||
|
if (taskConfig == null)
|
||||||
{
|
{
|
||||||
throw new UserFriendlyException($"无效的任务等级: {input.TaskLevel}");
|
throw new UserFriendlyException($"无效的任务等级: {input.TaskLevel}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 检查是否已领取
|
// 3. 检查是否已领取
|
||||||
var existingRecord = await _dailyTaskRepository._DbQueryable
|
var existingRecord = await _dailyTaskRepository._DbQueryable
|
||||||
.Where(x => x.UserId == userId && x.TaskDate == today && x.TaskLevel == input.TaskLevel)
|
.Where(x => x.UserId == userId && x.TaskDate == today && x.TaskLevel == input.TaskLevel)
|
||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
@@ -140,7 +154,7 @@ public class DailyTaskService : ApplicationService
|
|||||||
throw new UserFriendlyException("今日该任务奖励已领取,请明天再来!");
|
throw new UserFriendlyException("今日该任务奖励已领取,请明天再来!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 验证今日Token消耗是否达标
|
// 4. 验证今日Token消耗是否达标
|
||||||
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
||||||
if (todayConsumed < taskConfig.RequiredTokens)
|
if (todayConsumed < taskConfig.RequiredTokens)
|
||||||
{
|
{
|
||||||
@@ -148,18 +162,17 @@ public class DailyTaskService : ApplicationService
|
|||||||
$"Token消耗未达标!需要 {taskConfig.RequiredTokens / 10000}w,当前 {todayConsumed / 10000}w");
|
$"Token消耗未达标!需要 {taskConfig.RequiredTokens / 10000}w,当前 {todayConsumed / 10000}w");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 创建奖励包(使用 PremiumPackageManager)
|
// 5. 创建奖励包
|
||||||
|
|
||||||
var premiumPackage =
|
var premiumPackage =
|
||||||
new PremiumPackageAggregateRoot(userId, taskConfig.RewardTokens, $"每日任务:{taskConfig.Name}")
|
new PremiumPackageAggregateRoot(userId, taskConfig.RewardTokens, $"每日任务:{taskConfig.Name}")
|
||||||
{
|
{
|
||||||
PurchaseAmount = 0, // 奖励不需要付费
|
PurchaseAmount = 0,
|
||||||
Remark = $"{today:yyyy-MM-dd} 每日任务奖励"
|
Remark = $"{today:yyyy-MM-dd} 每日任务奖励"
|
||||||
};
|
};
|
||||||
|
|
||||||
await _premiumPackageRepository.InsertAsync(premiumPackage);
|
await _premiumPackageRepository.InsertAsync(premiumPackage);
|
||||||
|
|
||||||
// 5. 记录领取记录
|
// 6. 记录领取记录
|
||||||
var record = new DailyTaskRewardRecordAggregateRoot(userId, input.TaskLevel, today, taskConfig.RewardTokens)
|
var record = new DailyTaskRewardRecordAggregateRoot(userId, input.TaskLevel, today, taskConfig.RewardTokens)
|
||||||
{
|
{
|
||||||
Remark = $"完成任务{input.TaskLevel},名称:{taskConfig.Name},消耗 {todayConsumed / 10000}w token"
|
Remark = $"完成任务{input.TaskLevel},名称:{taskConfig.Name},消耗 {todayConsumed / 10000}w token"
|
||||||
@@ -197,4 +210,21 @@ public class DailyTaskService : ApplicationService
|
|||||||
|
|
||||||
return totalTokens;
|
return totalTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从Redis获取任务配置,如果不存在则写入默认配置
|
||||||
|
/// </summary>
|
||||||
|
private async Task<List<DailyTaskConfigItem>> GetTaskConfigsAsync()
|
||||||
|
{
|
||||||
|
var cacheData = await _taskConfigCache.GetOrAddAsync(
|
||||||
|
TaskConfigCacheKey,
|
||||||
|
() => Task.FromResult(new DailyTaskConfigCacheDto { Tasks = DefaultTaskConfigs }),
|
||||||
|
() => new DistributedCacheEntryOptions
|
||||||
|
{
|
||||||
|
// 不设置过期时间,永久缓存,需要手动更新
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return cacheData?.Tasks ?? DefaultTaskConfigs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +94,7 @@ public class AiChatService : ApplicationService
|
|||||||
public async Task<List<ModelGetListOutput>> GetModelAsync()
|
public async Task<List<ModelGetListOutput>> GetModelAsync()
|
||||||
{
|
{
|
||||||
var output = await _aiModelRepository._DbQueryable
|
var output = await _aiModelRepository._DbQueryable
|
||||||
|
.Where(x=>x.IsEnabled==true)
|
||||||
.Where(x => x.ModelType == ModelTypeEnum.Chat)
|
.Where(x => x.ModelType == ModelTypeEnum.Chat)
|
||||||
.Where(x => x.ModelApiType == ModelApiTypeEnum.OpenAi)
|
.Where(x => x.ModelApiType == ModelApiTypeEnum.OpenAi)
|
||||||
.OrderByDescending(x => x.OrderNum)
|
.OrderByDescending(x => x.OrderNum)
|
||||||
|
|||||||
Reference in New Issue
Block a user