2025-12-17 18:47:28 +08:00
|
|
|
|
using System.Text.Json;
|
|
|
|
|
|
using Yi.Framework.AiHub.Domain.Shared.Dtos.OpenAi;
|
|
|
|
|
|
using Yi.Framework.AiHub.Domain.Shared.Extensions;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Yi.Framework.AiHub.Domain.Shared.Dtos.Gemini;
|
|
|
|
|
|
|
|
|
|
|
|
public static class GeminiGenerateContentAcquirer
|
|
|
|
|
|
{
|
2025-12-17 21:51:01 +08:00
|
|
|
|
public static ThorUsageResponse? GetUsage(JsonElement response)
|
2025-12-17 18:47:28 +08:00
|
|
|
|
{
|
|
|
|
|
|
var usage = response.GetPath("usageMetadata");
|
|
|
|
|
|
if (!usage.HasValue)
|
|
|
|
|
|
{
|
2025-12-17 21:51:01 +08:00
|
|
|
|
return null;
|
2025-12-17 18:47:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var inputTokens = usage.Value.GetPath("promptTokenCount").GetInt();
|
|
|
|
|
|
var outputTokens = usage.Value.GetPath("candidatesTokenCount").GetInt()
|
|
|
|
|
|
+ usage.Value.GetPath("cachedContentTokenCount").GetInt()
|
|
|
|
|
|
+ usage.Value.GetPath("thoughtsTokenCount").GetInt()
|
|
|
|
|
|
+ usage.Value.GetPath("toolUsePromptTokenCount").GetInt();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new ThorUsageResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
PromptTokens = inputTokens,
|
|
|
|
|
|
InputTokens = inputTokens,
|
|
|
|
|
|
OutputTokens = outputTokens,
|
|
|
|
|
|
CompletionTokens = outputTokens,
|
|
|
|
|
|
TotalTokens = inputTokens + outputTokens,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-12-25 23:25:54 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-12-26 18:36:55 +08:00
|
|
|
|
/// 获取图片url,包含前缀
|
2025-12-25 23:25:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2026-01-02 19:26:09 +08:00
|
|
|
|
public static string GetImagePrefixBase64(JsonElement response)
|
2025-12-25 23:25:54 +08:00
|
|
|
|
{
|
2026-01-02 19:26:09 +08:00
|
|
|
|
// 获取 candidates[0].content.parts[0].text
|
|
|
|
|
|
var text = response.GetPath("candidates", 0, "content", "parts", 0, "text").GetString();
|
|
|
|
|
|
if (string.IsNullOrEmpty(text))
|
|
|
|
|
|
{
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析 markdown 图片格式: 
|
|
|
|
|
|
// 提取括号内的 data:image/xxx;base64,xxx 部分
|
|
|
|
|
|
var startMarker = "(data:image/";
|
|
|
|
|
|
var startIndex = text.IndexOf(startMarker);
|
|
|
|
|
|
if (startIndex < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从 "data:" 开始
|
|
|
|
|
|
startIndex += 1; // 跳过 "("
|
|
|
|
|
|
var endIndex = text.IndexOf(')', startIndex);
|
|
|
|
|
|
if (endIndex < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return text.Substring(startIndex, endIndex - startIndex);
|
2025-12-25 23:25:54 +08:00
|
|
|
|
}
|
2025-12-17 18:47:28 +08:00
|
|
|
|
}
|