using System.Net.Http.Json; using System.Text; using System.Text.Json; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using UniVerse.Application.Interfaces; namespace UniVerse.Infrastructure.ExternalServices; public class LlmClient : ILlmClient { private readonly HttpClient _http; private readonly IConfiguration _config; private readonly ILogger _logger; public LlmClient(HttpClient http, IConfiguration config, ILogger logger) { _http = http; _config = config; _logger = logger; } public async Task AnalyzeReviewAsync(string reviewText, string lectureContext) { var prompt = $""" Analyze the following student review of a lecture. Return a JSON object with: - quality_score: float 0-1 indicating review quality - sentiment: "Positive", "Neutral", or "Negative" - tags: array of relevant topic tags - is_informative: boolean indicating if the review is informative Lecture context: {lectureContext} Review text: {reviewText} """; var request = new { model = _config["Llm:Model"] ?? "gpt-4o-mini", messages = new[] { new { role = "user", content = prompt } }, temperature = 0.3, response_format = new { type = "json_object" } }; var apiKey = _config["Llm:ApiKey"] ?? ""; _http.DefaultRequestHeaders.Clear(); if (!string.IsNullOrEmpty(apiKey)) _http.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}"); var response = await _http.PostAsJsonAsync("chat/completions", request); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadFromJsonAsync(); var content = json.GetProperty("choices")[0].GetProperty("message").GetProperty("content").GetString()!; var analysis = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!; return new LlmReviewAnalysis(analysis.QualityScore, analysis.Sentiment, analysis.Tags, analysis.IsInformative); } private record LlmRawResponse(double QualityScore, string Sentiment, string[] Tags, bool IsInformative); }