feat: 支持更多类型的图片模型

This commit is contained in:
ccnetcore
2026-01-03 03:19:31 +08:00
parent be5f57f654
commit 5a7f0ab108
3 changed files with 25 additions and 15 deletions

View File

@@ -43,7 +43,7 @@ public class ImageGenerationJob : AsyncBackgroundJob<ImageGenerationJobArgs>, IT
// 构建 Gemini API 请求对象
var parts = new List<object>
{
new { text = task.Prompt }
new { role="user",text = task.Prompt }
};
// 添加参考图(如果有)

View File

@@ -20,7 +20,6 @@ public static class GeminiGenerateContentAcquirer
+ usage.Value.GetPath("thoughtsTokenCount").GetInt()
+ usage.Value.GetPath("toolUsePromptTokenCount").GetInt();
return new ThorUsageResponse
{
PromptTokens = inputTokens,
@@ -32,32 +31,43 @@ public static class GeminiGenerateContentAcquirer
}
/// <summary>
/// 获取图片url包含前缀
/// 获取图片 base64包含 data:image 前缀
/// 优先从 inlineData.data 中获取,其次从 markdown text 中解析
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
public static string GetImagePrefixBase64(JsonElement response)
{
// 获取 candidates[0].content.parts[0].text
var text = response.GetPath("candidates", 0, "content", "parts", 0, "text").GetString();
// Step 1: 优先尝试从 candidates[0].content.parts[0].inlineData.data 获取
var inlineBase64 = response
.GetPath("candidates", 0, "content", "parts", 0, "inlineData", "data")
.GetString();
if (!string.IsNullOrEmpty(inlineBase64))
{
// 默认按 png 格式拼接前缀
return $"data:image/png;base64,{inlineBase64}";
}
// Step 2: fallback从 candidates[0].content.parts[0].text 中解析 markdown 图片
var text = response
.GetPath("candidates", 0, "content", "parts", 0, "text")
.GetString();
if (string.IsNullOrEmpty(text))
{
return string.Empty;
}
// 解析 markdown 图片格式: ![image](data:image/png;base64,xxx)
// 提取括号内的 data:image/xxx;base64,xxx 部分
// markdown 图片格式: ![image](data:image/png;base64,xxx)
var startMarker = "(data:image/";
var startIndex = text.IndexOf(startMarker);
var startIndex = text.IndexOf(startMarker, StringComparison.Ordinal);
if (startIndex < 0)
{
return string.Empty;
}
// 从 "data:" 开始
startIndex += 1; // 跳过 "("
var endIndex = text.IndexOf(')', startIndex);
if (endIndex < 0)
if (endIndex <= startIndex)
{
return string.Empty;
}

View File

@@ -92,7 +92,7 @@ public class AiGateWayManager : DomainService
{
throw new UserFriendlyException($"【{modelId}】模型当前版本【{modelApiType}】格式不支持");
}
// ✅ 统一处理 -nx 后缀(网关层模型规范化)
// ✅ 统一处理 yi- 后缀(网关层模型规范化)
if (!string.IsNullOrEmpty(aiModelDescribe.ModelId) &&
aiModelDescribe.ModelId.StartsWith("yi-", StringComparison.OrdinalIgnoreCase))
{
@@ -1005,13 +1005,13 @@ public class AiGateWayManager : DomainService
var data = await chatService.GenerateContentAsync(modelDescribe, request, cancellationToken);
//解析json获取base64字符串
var imageBase64 = GeminiGenerateContentAcquirer.GetImagePrefixBase64(data);
var imagePrefixBase64 = GeminiGenerateContentAcquirer.GetImagePrefixBase64(data);
//远程调用上传接口将base64转换为URL
var httpClient = LazyServiceProvider.LazyGetRequiredService<IHttpClientFactory>().CreateClient();
// var uploadUrl = $"https://ccnetcore.com/prod-api/ai-hub/ai-image/upload-base64";
var uploadUrl = $"{ImageStoreHost}/ai-image/upload-base64";
var content = new StringContent(JsonSerializer.Serialize(imageBase64), Encoding.UTF8, "application/json");
var content = new StringContent(JsonSerializer.Serialize(imagePrefixBase64), Encoding.UTF8, "application/json");
var uploadResponse = await httpClient.PostAsync(uploadUrl, content, cancellationToken);
uploadResponse.EnsureSuccessStatusCode();
var storeUrl = await uploadResponse.Content.ReadAsStringAsync(cancellationToken);