feat: 兼容了用量使用显示

This commit is contained in:
chenchun
2025-07-22 10:40:23 +08:00
parent b6d670c240
commit a0eb234539
8 changed files with 97 additions and 75 deletions

View File

@@ -108,33 +108,33 @@ public class AzureDatabricksChatCompletionsService(ILogger<AzureDatabricksChatCo
continue;
}
var content = result?.Choices?.FirstOrDefault()?.Delta;
if (first && content?.Content == OpenAIConstant.ThinkStart)
{
isThink = true;
continue;
// 需要将content的内容转换到其他字段
}
if (isThink && content?.Content?.Contains(OpenAIConstant.ThinkEnd) == true)
{
isThink = false;
// 需要将content的内容转换到其他字段
continue;
}
if (isThink && result?.Choices != null)
{
// 需要将content的内容转换到其他字段
foreach (var choice in result.Choices)
{
choice.Delta.ReasoningContent = choice.Delta.Content;
choice.Delta.Content = string.Empty;
}
}
first = false;
// var content = result?.Choices?.FirstOrDefault()?.Delta;
//
// if (first && content?.Content == OpenAIConstant.ThinkStart)
// {
// isThink = true;
// continue;
// // 需要将content的内容转换到其他字段
// }
//
// if (isThink && content?.Content?.Contains(OpenAIConstant.ThinkEnd) == true)
// {
// isThink = false;
// // 需要将content的内容转换到其他字段
// continue;
// }
//
// if (isThink && result?.Choices != null)
// {
// // 需要将content的内容转换到其他字段
// foreach (var choice in result.Choices)
// {
// choice.Delta.ReasoningContent = choice.Delta.Content;
// choice.Delta.Content = string.Empty;
// }
// }
//
// first = false;
yield return result;
}

View File

@@ -93,36 +93,36 @@ public sealed class DeepSeekChatCompletionsService(ILogger<DeepSeekChatCompletio
var result = JsonSerializer.Deserialize<ThorChatCompletionsResponse>(line,
ThorJsonSerializer.DefaultOptions);
var content = result?.Choices?.FirstOrDefault()?.Delta;
if (first && string.IsNullOrWhiteSpace(content?.Content) && string.IsNullOrEmpty(content?.ReasoningContent))
{
continue;
}
if (first && content.Content == OpenAIConstant.ThinkStart)
{
isThink = true;
//continue;
// 需要将content的内容转换到其他字段
}
if (isThink && content.Content.Contains(OpenAIConstant.ThinkEnd))
{
isThink = false;
// 需要将content的内容转换到其他字段
//continue;
}
if (isThink)
{
// 需要将content的内容转换到其他字段
foreach (var choice in result.Choices)
{
//choice.Delta.ReasoningContent = choice.Delta.Content;
//choice.Delta.Content = string.Empty;
}
}
// var content = result?.Choices?.FirstOrDefault()?.Delta;
//
// // if (first && string.IsNullOrWhiteSpace(content?.Content) && string.IsNullOrEmpty(content?.ReasoningContent))
// // {
// // continue;
// // }
//
// if (first && content.Content == OpenAIConstant.ThinkStart)
// {
// isThink = true;
// //continue;
// // 需要将content的内容转换到其他字段
// }
//
// if (isThink && content.Content.Contains(OpenAIConstant.ThinkEnd))
// {
// isThink = false;
// // 需要将content的内容转换到其他字段
// //continue;
// }
//
// if (isThink)
// {
// // 需要将content的内容转换到其他字段
// foreach (var choice in result.Choices)
// {
// //choice.Delta.ReasoningContent = choice.Delta.Content;
// //choice.Delta.Content = string.Empty;
// }
// }
// first = false;

View File

@@ -29,10 +29,18 @@ public class MessageAggregateRoot : FullAuditedAggregateRoot<Guid>
ModelId = modelId;
if (tokenUsage is not null)
{
long inputTokenCount = tokenUsage.PromptTokens
?? tokenUsage.InputTokens
?? 0;
long outputTokenCount = tokenUsage.CompletionTokens
?? tokenUsage.OutputTokens
?? 0;
this.TokenUsage = new TokenUsageValueObject
{
OutputTokenCount = tokenUsage.OutputTokens ?? 0,
InputTokenCount = tokenUsage.InputTokens ?? 0,
OutputTokenCount = outputTokenCount,
InputTokenCount = inputTokenCount,
TotalTokenCount = tokenUsage.TotalTokens ?? 0
};
}

View File

@@ -37,22 +37,22 @@ public class UsageStatisticsAggregateRoot : FullAuditedAggregateRoot<Guid>
/// <summary>
/// 使用输出token总数
/// </summary>
public int UsageOutputTokenCount { get; set; }
public long UsageOutputTokenCount { get; set; }
/// <summary>
/// 使用输入总数
/// </summary>
public int UsageInputTokenCount { get; set; }
public long UsageInputTokenCount { get; set; }
/// <summary>
/// 总token使用数量
/// </summary>
public int TotalTokenCount { get; set; }
public long TotalTokenCount { get; set; }
/// <summary>
/// 新增一次聊天统计
/// </summary>
public void AddOnceChat(int inputTokenCount, int outputTokenCount)
public void AddOnceChat(long inputTokenCount, long outputTokenCount)
{
UsageTotalNumber += 1;
UsageOutputTokenCount += outputTokenCount;

View File

@@ -2,9 +2,9 @@
public class TokenUsageValueObject
{
public int OutputTokenCount { get; set; }
public long OutputTokenCount { get; set; }
public int InputTokenCount { get; set; }
public long InputTokenCount { get; set; }
public long TotalTokenCount { get; set; }
}

View File

@@ -132,8 +132,7 @@ public class AiGateWayManager : DomainService
TokenUsage = data.Usage
});
await _usageStatisticsManager.SetUsageAsync(userId.Value, request.Model, data.Usage.InputTokens ?? 0,
data.Usage.OutputTokens ?? 0);
await _usageStatisticsManager.SetUsageAsync(userId.Value, request.Model, data.Usage);
}
await response.WriteAsJsonAsync(data, cancellationToken);
@@ -200,7 +199,7 @@ public class AiGateWayManager : DomainService
{
await foreach (var data in completeChatResponse)
{
if (data.Usage is not null && data.Usage.TotalTokens is not null)
if (data.Usage is not null)
{
tokenUsage = data.Usage;
}
@@ -261,8 +260,7 @@ public class AiGateWayManager : DomainService
TokenUsage = tokenUsage
});
await _usageStatisticsManager.SetUsageAsync(userId.Value, request.Model, tokenUsage.InputTokens ?? 0,
tokenUsage.OutputTokens ?? 0);
await _usageStatisticsManager.SetUsageAsync(userId.Value, request.Model, tokenUsage);
}
}
}

View File

@@ -1,5 +1,6 @@
using Medallion.Threading;
using Volo.Abp.Domain.Services;
using Yi.Framework.AiHub.Application.Contracts.Dtos.OpenAi;
using Yi.Framework.AiHub.Domain.Entities;
using Yi.Framework.SqlSugarCore.Abstractions;
@@ -17,8 +18,16 @@ public class UsageStatisticsManager : DomainService
private IDistributedLockProvider DistributedLock =>
LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
public async Task SetUsageAsync(Guid userId, string modelId, int inputTokenCount, int outputTokenCount)
public async Task SetUsageAsync(Guid userId, string modelId, ThorUsageResponse? tokenUsage)
{
long inputTokenCount = tokenUsage?.PromptTokens
?? tokenUsage.InputTokens
?? 0;
long outputTokenCount = tokenUsage?.CompletionTokens
?? tokenUsage.OutputTokens
?? 0;
await using (await DistributedLock.AcquireLockAsync($"UsageStatistics:{userId.ToString()}"))
{
var entity = await _repository._DbQueryable.FirstAsync(x => x.UserId == userId && x.ModelId == modelId);
@@ -37,8 +46,4 @@ public class UsageStatisticsManager : DomainService
}
}
}
}
internal class LazyServiceProvider
{
}

View File

@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Domain;
using Yi.Framework.AiHub.Application.Contracts.Dtos.OpenAi;
using Yi.Framework.AiHub.Domain.AiGateWay;
using Yi.Framework.AiHub.Domain.AiGateWay.Impl.ThorAzureDatabricks.Chats;
using Yi.Framework.AiHub.Domain.AiGateWay.Impl.ThorAzureOpenAI.Chats;
@@ -48,6 +49,16 @@ namespace Yi.Framework.AiHub.Domain
request.Temperature = null;
}
});
options.Handles.Add(request =>
{
if (request.Stream == true)
{
request.StreamOptions = new ThorStreamOptions()
{
IncludeUsage = true
};
}
});
});
}