Files
GreenHomeBack/src/GreenHome.Infrastructure/AIQueryService.cs
2025-12-16 16:52:40 +03:30

127 lines
3.9 KiB
C#

using GreenHome.Application;
using GreenHome.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace GreenHome.Infrastructure;
public sealed class AIQueryService : IAIQueryService
{
private readonly GreenHomeDbContext dbContext;
private readonly ILogger<AIQueryService> logger;
public AIQueryService(
GreenHomeDbContext dbContext,
ILogger<AIQueryService> logger)
{
this.dbContext = dbContext;
this.logger = logger;
}
public async Task<AIQuery> SaveQueryAsync(AIQuery query, CancellationToken cancellationToken = default)
{
try
{
dbContext.AIQueries.Add(query);
await dbContext.SaveChangesAsync(cancellationToken);
logger.LogInformation("AI query saved: {QueryId}, Tokens: {TotalTokens}",
query.Id, query.TotalTokens);
return query;
}
catch (Exception ex)
{
logger.LogError(ex, "Error saving AI query");
throw;
}
}
public async Task<List<AIQuery>> GetDeviceQueriesAsync(
int deviceId,
int take = 50,
CancellationToken cancellationToken = default)
{
return await dbContext.AIQueries
.Where(q => q.DeviceId == deviceId)
.OrderByDescending(q => q.CreatedAt)
.Take(take)
.ToListAsync(cancellationToken);
}
public async Task<List<AIQuery>> GetUserQueriesAsync(
int userId,
int take = 50,
CancellationToken cancellationToken = default)
{
return await dbContext.AIQueries
.Where(q => q.UserId == userId)
.OrderByDescending(q => q.CreatedAt)
.Take(take)
.ToListAsync(cancellationToken);
}
public async Task<int> GetDeviceTotalTokensAsync(
int deviceId,
CancellationToken cancellationToken = default)
{
return await dbContext.AIQueries
.Where(q => q.DeviceId == deviceId)
.SumAsync(q => q.TotalTokens, cancellationToken);
}
public async Task<int> GetUserTotalTokensAsync(
int userId,
CancellationToken cancellationToken = default)
{
return await dbContext.AIQueries
.Where(q => q.UserId == userId)
.SumAsync(q => q.TotalTokens, cancellationToken);
}
public async Task<List<AIQuery>> GetRecentQueriesAsync(
int take = 20,
CancellationToken cancellationToken = default)
{
return await dbContext.AIQueries
.Include(q => q.Device)
.Include(q => q.User)
.OrderByDescending(q => q.CreatedAt)
.Take(take)
.ToListAsync(cancellationToken);
}
public async Task<AIQueryStats> GetStatsAsync(CancellationToken cancellationToken = default)
{
var today = DateTime.UtcNow.Date;
var allQueries = await dbContext.AIQueries
.Select(q => new
{
q.TotalTokens,
q.PromptTokens,
q.CompletionTokens,
q.ResponseTimeMs,
q.CreatedAt
})
.ToListAsync(cancellationToken);
var todayQueries = allQueries.Where(q => q.CreatedAt >= today).ToList();
return new AIQueryStats
{
TotalQueries = allQueries.Count,
TotalTokensUsed = allQueries.Sum(q => q.TotalTokens),
TotalPromptTokens = allQueries.Sum(q => q.PromptTokens),
TotalCompletionTokens = allQueries.Sum(q => q.CompletionTokens),
AverageResponseTimeMs = allQueries.Any()
? allQueries.Where(q => q.ResponseTimeMs.HasValue)
.Average(q => q.ResponseTimeMs ?? 0)
: 0,
TodayQueries = todayQueries.Count,
TodayTokens = todayQueries.Sum(q => q.TotalTokens)
};
}
}