Files
Yi.Admin/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Jobs/ImageGenerationJob.cs

130 lines
4.3 KiB
C#
Raw Normal View History

2025-12-26 23:46:36 +08:00
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Yi.Framework.AiHub.Domain.Entities.Chat;
using Yi.Framework.AiHub.Domain.Managers;
using Yi.Framework.AiHub.Domain.Shared.Enums;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.AiHub.Application.Jobs;
/// <summary>
/// 图片生成后台任务
/// </summary>
public class ImageGenerationJob : AsyncBackgroundJob<ImageGenerationJobArgs>, ITransientDependency
{
private readonly ILogger<ImageGenerationJob> _logger;
private readonly AiGateWayManager _aiGateWayManager;
private readonly ISqlSugarRepository<ImageStoreTaskAggregateRoot> _imageStoreTaskRepository;
public ImageGenerationJob(
ILogger<ImageGenerationJob> logger,
AiGateWayManager aiGateWayManager,
ISqlSugarRepository<ImageStoreTaskAggregateRoot> imageStoreTaskRepository)
{
_logger = logger;
_aiGateWayManager = aiGateWayManager;
_imageStoreTaskRepository = imageStoreTaskRepository;
}
public override async Task ExecuteAsync(ImageGenerationJobArgs args)
{
2026-01-02 19:26:09 +08:00
var task = await _imageStoreTaskRepository.GetFirstAsync(x => x.Id == args.TaskId);
if (task is null)
{
throw new UserFriendlyException($"{args.TaskId} 图片生成任务不存在");
}
2025-12-26 23:46:36 +08:00
2026-01-02 19:26:09 +08:00
_logger.LogInformation("开始执行图片生成任务TaskId: {TaskId}, ModelId: {ModelId}, UserId: {UserId}",
task.Id, task.ModelId, task.UserId);
2025-12-26 23:46:36 +08:00
try
{
2026-01-02 19:26:09 +08:00
// 构建 Gemini API 请求对象
var parts = new List<object>
{
2026-01-03 16:00:18 +08:00
new { text = task.Prompt }
2026-01-02 19:26:09 +08:00
};
// 添加参考图(如果有)
foreach (var prefixBase64 in task.ReferenceImagesPrefixBase64)
{
var (mimeType, base64Data) = ParsePrefixBase64(prefixBase64);
parts.Add(new
{
inline_data = new
{
mime_type = mimeType,
data = base64Data
}
});
}
var requestObj = new
{
contents = new[]
{
2026-01-04 12:32:31 +08:00
new
{
role = "user", parts = new List<object>
{
new { text = "我只要图片,直接生成图片,不要询问我" }
}
},
2026-01-03 16:00:18 +08:00
new { role = "user", parts }
2026-01-02 19:26:09 +08:00
}
};
2025-12-26 23:46:36 +08:00
2026-01-02 19:26:09 +08:00
var request = JsonSerializer.Deserialize<JsonElement>(
JsonSerializer.Serialize(requestObj));
//里面生成成功已经包含扣款了
2025-12-26 23:46:36 +08:00
await _aiGateWayManager.GeminiGenerateContentImageForStatisticsAsync(
2026-01-02 19:26:09 +08:00
task.Id,
task.ModelId,
2025-12-26 23:46:36 +08:00
request,
2026-01-02 19:26:09 +08:00
task.UserId,
2026-01-03 16:00:18 +08:00
tokenId: task.TokenId);
2025-12-26 23:46:36 +08:00
_logger.LogInformation("图片生成任务完成TaskId: {TaskId}", args.TaskId);
}
catch (Exception ex)
{
var error = $"图片任务失败TaskId: {args.TaskId},错误信息: {ex.Message},错误堆栈:{ex.StackTrace}";
_logger.LogError(ex, error);
2025-12-26 23:46:36 +08:00
2026-01-02 19:26:09 +08:00
task.TaskStatus = TaskStatusEnum.Fail;
task.ErrorInfo = error;
2026-01-02 19:26:09 +08:00
await _imageStoreTaskRepository.UpdateAsync(task);
}
}
/// <summary>
/// 解析带前缀的 Base64 字符串,提取 mimeType 和纯 base64 数据
/// </summary>
private static (string mimeType, string base64Data) ParsePrefixBase64(string prefixBase64)
{
// 默认值
var mimeType = "image/png";
var base64Data = prefixBase64;
if (prefixBase64.Contains(","))
{
var parts = prefixBase64.Split(',');
if (parts.Length == 2)
2025-12-26 23:46:36 +08:00
{
2026-01-02 19:26:09 +08:00
var header = parts[0];
if (header.Contains(":") && header.Contains(";"))
{
mimeType = header.Split(':')[1].Split(';')[0];
}
base64Data = parts[1];
2025-12-26 23:46:36 +08:00
}
}
2026-01-02 19:26:09 +08:00
return (mimeType, base64Data);
2025-12-26 23:46:36 +08:00
}
2026-01-02 19:26:09 +08:00
}