Files
Yi.Framework/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Jobs/ImageGenerationJob.cs
ccnetcore 88fae0cdc2 fix: 优化图片生成与上传错误处理及任务信息返回
- 图片上传接口新增状态码校验,返回明确错误信息
- 图片生成任务失败时记录完整错误信息与堆栈
- 图片任务查询结果补充发布状态、分类及错误信息
- 网关层模型名规范化与少量代码格式优化
2026-01-03 14:03:24 +08:00

123 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
{
var task = await _imageStoreTaskRepository.GetFirstAsync(x => x.Id == args.TaskId);
if (task is null)
{
throw new UserFriendlyException($"{args.TaskId} 图片生成任务不存在");
}
_logger.LogInformation("开始执行图片生成任务TaskId: {TaskId}, ModelId: {ModelId}, UserId: {UserId}",
task.Id, task.ModelId, task.UserId);
try
{
// 构建 Gemini API 请求对象
var parts = new List<object>
{
new { role="user",text = task.Prompt }
};
// 添加参考图(如果有)
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[]
{
new { parts }
}
};
var request = JsonSerializer.Deserialize<JsonElement>(
JsonSerializer.Serialize(requestObj));
//里面生成成功已经包含扣款了
await _aiGateWayManager.GeminiGenerateContentImageForStatisticsAsync(
task.Id,
task.ModelId,
request,
task.UserId,
tokenId:task.TokenId);
_logger.LogInformation("图片生成任务完成TaskId: {TaskId}", args.TaskId);
}
catch (Exception ex)
{
var error = $"图片任务失败TaskId: {args.TaskId},错误信息: {ex.Message},错误堆栈:{ex.StackTrace}";
_logger.LogError(ex, error);
task.TaskStatus = TaskStatusEnum.Fail;
task.ErrorInfo = error;
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)
{
var header = parts[0];
if (header.Contains(":") && header.Contains(";"))
{
mimeType = header.Split(':')[1].Split(';')[0];
}
base64Data = parts[1];
}
}
return (mimeType, base64Data);
}
}