Files
Yi.Admin/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/Gemini/GeminiGenerateContentAcquirer.cs

166 lines
5.4 KiB
C#
Raw Normal View History

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
{
/// <summary>
/// 从请求体中提取用户最后一条消息内容
/// 路径: contents[last].parts[last].text
/// </summary>
public static string GetLastUserContent(JsonElement request)
{
var contents = request.GetPath("contents");
if (!contents.HasValue || contents.Value.ValueKind != JsonValueKind.Array)
{
return string.Empty;
}
var contentsArray = contents.Value.EnumerateArray().ToList();
if (contentsArray.Count == 0)
{
return string.Empty;
}
var lastContent = contentsArray[^1];
var parts = lastContent.GetPath("parts");
if (!parts.HasValue || parts.Value.ValueKind != JsonValueKind.Array)
{
return string.Empty;
}
var partsArray = parts.Value.EnumerateArray().ToList();
if (partsArray.Count == 0)
{
return string.Empty;
}
// 获取最后一个 part 的 text
var lastPart = partsArray[^1];
return lastPart.GetPath("text").GetString() ?? string.Empty;
}
/// <summary>
/// 从响应中提取文本内容(非 thought 类型)
/// 路径: candidates[0].content.parts[].text (where thought != true)
/// </summary>
public static string GetTextContent(JsonElement response)
{
var candidates = response.GetPath("candidates");
if (!candidates.HasValue || candidates.Value.ValueKind != JsonValueKind.Array)
{
return string.Empty;
}
var candidatesArray = candidates.Value.EnumerateArray().ToList();
if (candidatesArray.Count == 0)
{
return string.Empty;
}
var parts = candidatesArray[0].GetPath("content", "parts");
if (!parts.HasValue || parts.Value.ValueKind != JsonValueKind.Array)
{
return string.Empty;
}
// 遍历所有 parts只取非 thought 的 text
foreach (var part in parts.Value.EnumerateArray())
{
var isThought = part.GetPath("thought").GetBool();
if (!isThought)
{
var text = part.GetPath("text").GetString();
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
return string.Empty;
}
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>
/// 获取图片 base64包含 data:image 前缀)
/// 从最后一个 part 开始查找 inlineData找不到再从最后一个 part 开始查找 text
2025-12-25 23:25:54 +08:00
/// </summary>
2026-01-02 19:26:09 +08:00
public static string GetImagePrefixBase64(JsonElement response)
2025-12-25 23:25:54 +08:00
{
var parts = response.GetPath("candidates", 0, "content", "parts");
if (!parts.HasValue || parts.Value.ValueKind != JsonValueKind.Array)
{
return string.Empty;
}
var partsArray = parts.Value.EnumerateArray().ToList();
if (partsArray.Count == 0)
2026-01-02 19:26:09 +08:00
{
return string.Empty;
}
// Step 1: 从最后一个 part 开始查找 inlineData
for (int i = partsArray.Count - 1; i >= 0; i--)
2026-01-02 19:26:09 +08:00
{
var inlineBase64 = partsArray[i].GetPath("inlineData", "data").GetString();
if (!string.IsNullOrEmpty(inlineBase64))
{
var mimeType = partsArray[i].GetPath("inlineData", "mimeType").GetString() ?? "image/png";
return $"data:{mimeType};base64,{inlineBase64}";
}
2026-01-02 19:26:09 +08:00
}
// Step 2: 从最后一个 part 开始查找 text 中的 markdown 图片
for (int i = partsArray.Count - 1; i >= 0; i--)
2026-01-02 19:26:09 +08:00
{
var text = partsArray[i].GetPath("text").GetString();
if (string.IsNullOrEmpty(text))
{
continue;
}
// markdown 图片格式: ![image](data:image/png;base64,xxx)
var startMarker = "(data:image/";
var startIndex = text.IndexOf(startMarker, StringComparison.Ordinal);
if (startIndex < 0)
{
continue;
}
startIndex += 1; // 跳过 "("
var endIndex = text.IndexOf(')', startIndex);
if (endIndex > startIndex)
{
return text.Substring(startIndex, endIndex - startIndex);
}
2026-01-02 19:26:09 +08:00
}
return string.Empty;
2025-12-25 23:25:54 +08:00
}
2025-12-17 18:47:28 +08:00
}