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

View File

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