From bd30a40a6f6212218d6fea27fd4603a9a90f8d0e Mon Sep 17 00:00:00 2001 From: chenchun Date: Sun, 4 Jan 2026 12:32:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=8D=95=E7=8B=AC=E6=89=A3=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Jobs/ImageGenerationJob.cs | 7 ++++ .../Services/Chat/AiImageService.cs | 26 +++++++++---- .../Dtos/AiModelDescribe.cs | 9 ++++- .../Managers/AiGateWayManager.cs | 37 +++++++++++++++++-- 4 files changed, 68 insertions(+), 11 deletions(-) diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Jobs/ImageGenerationJob.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Jobs/ImageGenerationJob.cs index 67f9856d..61931017 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Jobs/ImageGenerationJob.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Jobs/ImageGenerationJob.cs @@ -64,6 +64,13 @@ public class ImageGenerationJob : AsyncBackgroundJob, IT { contents = new[] { + new + { + role = "user", parts = new List + { + new { text = "我只要图片,直接生成图片,不要询问我" } + } + }, new { role = "user", parts } } }; diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs index 5a8f3acb..d92485be 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs @@ -264,7 +264,7 @@ public class AiImageService : ApplicationService ErrorInfo = x.ErrorInfo, UserName = x.UserName, UserId = x.UserId, - IsAnonymous =x.IsAnonymous + IsAnonymous = x.IsAnonymous }) .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); @@ -272,6 +272,17 @@ public class AiImageService : ApplicationService return new PagedResult(total, output); } + /// + /// 删除个人图片 + /// + /// + [HttpDelete("ai-image/my-tasks")] + public async Task DeleteMyTaskAsync([FromBody] List ids) + { + var userId = CurrentUser.GetId(); + await _imageTaskRepository.DeleteAsync(x => ids.Contains(x.Id) && x.UserId == userId); + } + /// /// 分页查询图片广场(已发布的图片) /// @@ -285,8 +296,9 @@ public class AiImageService : ApplicationService .Where(x => x.TaskStatus == TaskStatusEnum.Success) .WhereIF(input.TaskStatus is not null, x => x.TaskStatus == input.TaskStatus) .WhereIF(!string.IsNullOrWhiteSpace(input.Prompt), x => x.Prompt.Contains(input.Prompt)) - .WhereIF(!string.IsNullOrWhiteSpace(input.Categories), x => SqlFunc.JsonLike(x.Categories, input.Categories)) - .WhereIF(!string.IsNullOrWhiteSpace(input.UserName),x=>x.UserName.Contains(input.UserName) ) + .WhereIF(!string.IsNullOrWhiteSpace(input.Categories), + x => SqlFunc.JsonLike(x.Categories, input.Categories)) + .WhereIF(!string.IsNullOrWhiteSpace(input.UserName), x => x.UserName.Contains(input.UserName)) .WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime) .OrderByDescending(x => x.CreationTime) @@ -303,9 +315,9 @@ public class AiImageService : ApplicationService ErrorInfo = null, UserName = x.UserName, UserId = x.UserId, - }) - .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); ; + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + ; output.ForEach(x => @@ -316,7 +328,7 @@ public class AiImageService : ApplicationService x.UserId = null; } }); - + return new PagedResult(total, output); } @@ -345,7 +357,7 @@ public class AiImageService : ApplicationService } //设置发布 - task.SetPublish(input.IsAnonymous,input.Categories); + task.SetPublish(input.IsAnonymous, input.Categories); await _imageTaskRepository.UpdateAsync(task); } diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs index 1b00d8e0..c587a927 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs @@ -1,4 +1,6 @@ -namespace Yi.Framework.AiHub.Domain.Shared.Dtos; +using Yi.Framework.AiHub.Domain.Shared.Enums; + +namespace Yi.Framework.AiHub.Domain.Shared.Dtos; public class AiModelDescribe { @@ -66,4 +68,9 @@ public class AiModelDescribe /// 是否为尊享模型 /// public bool IsPremium { get; set; } + + /// + /// 模型类型(聊天/图片等) + /// + public ModelTypeEnum ModelType { get; set; } } \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs index 9cbbedc6..d5ab1499 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs @@ -86,7 +86,8 @@ public class AiGateWayManager : DomainService AppExtraUrl = app.ExtraUrl, ModelExtraInfo = model.ExtraInfo, Multiplier = model.Multiplier, - IsPremium = model.IsPremium + IsPremium = model.IsPremium, + ModelType = model.ModelType }) .FirstAsync(); if (aiModelDescribe is null) @@ -871,7 +872,20 @@ public class AiGateWayManager : DomainService var data = await chatService.GenerateContentAsync(modelDescribe, request, cancellationToken); var tokenUsage = GeminiGenerateContentAcquirer.GetUsage(data); - tokenUsage.SetSupplementalMultiplier(modelDescribe.Multiplier); + //如果是图片模型,单独扣费 + if (modelDescribe.ModelType == ModelTypeEnum.Image) + { + tokenUsage = new ThorUsageResponse + { + InputTokens = (int)modelDescribe.Multiplier, + OutputTokens = (int)modelDescribe.Multiplier, + TotalTokens = (int)modelDescribe.Multiplier + }; + } + else + { + tokenUsage.SetSupplementalMultiplier(modelDescribe.Multiplier); + } if (userId is not null) { @@ -944,7 +958,20 @@ public class AiGateWayManager : DomainService if (responseResult!.Value.GetPath("candidates", 0, "finishReason").GetString() == "STOP") { tokenUsage = GeminiGenerateContentAcquirer.GetUsage(responseResult!.Value); - tokenUsage.SetSupplementalMultiplier(modelDescribe.Multiplier); + //如果是图片模型,单独扣费 + if (modelDescribe.ModelType == ModelTypeEnum.Image) + { + tokenUsage = new ThorUsageResponse + { + InputTokens = (int)modelDescribe.Multiplier, + OutputTokens = (int)modelDescribe.Multiplier, + TotalTokens = (int)modelDescribe.Multiplier + }; + } + else + { + tokenUsage.SetSupplementalMultiplier(modelDescribe.Multiplier); + } } await response.WriteAsync($"data: {JsonSerializer.Serialize(responseResult)}\n\n", Encoding.UTF8, @@ -1019,6 +1046,10 @@ public class AiGateWayManager : DomainService //解析json,获取base64字符串 var imagePrefixBase64 = GeminiGenerateContentAcquirer.GetImagePrefixBase64(data); + if (string.IsNullOrWhiteSpace(imagePrefixBase64)) + { + throw new UserFriendlyException("大模型没有返回图片,请调整提示词或稍后再试"); + } //远程调用上传接口,将base64转换为URL var httpClient = LazyServiceProvider.LazyGetRequiredService().CreateClient();