feat: 支持更多类型的图片模型
This commit is contained in:
@@ -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 }
|
||||
};
|
||||
|
||||
// 添加参考图(如果有)
|
||||
|
||||
@@ -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 图片格式: 
|
||||
// 提取括号内的 data:image/xxx;base64,xxx 部分
|
||||
// markdown 图片格式: 
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user