using System.IO; using System.Net.Http; using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Szmedi.RvKits.LLMScript { public class OpenAiProvider : ILLMProvider { private static readonly HttpClient _client = new HttpClient(); private readonly string _endpoint; private readonly string _apiKey; private readonly string _model; public OpenAiProvider(string endpoint, string apiKey, string model) { _endpoint = endpoint; _apiKey = apiKey; _model = model; _client.DefaultRequestHeaders.Clear(); _client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}"); } public async Task GenerateStreamAsync( string systemPrompt, string userPrompt, Action onTokenReceived) { var payload = new { model = _model, messages = new[] { new { role = "system", content = systemPrompt }, new { role = "user", content = userPrompt } }, temperature = 0, stream = true }; string json = JsonConvert.SerializeObject(payload); var request = new HttpRequestMessage(HttpMethod.Post, _endpoint); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _client.SendAsync( request, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); using (var stream = await response.Content.ReadAsStreamAsync()) using (var reader = new StreamReader(stream)) { while (!reader.EndOfStream) { string line = await reader.ReadLineAsync(); if (string.IsNullOrWhiteSpace(line)) continue; if (!line.StartsWith("data:")) continue; string data = line.Substring(5).Trim(); if (data == "[DONE]") break; JObject obj = JObject.Parse(data); var delta = obj["choices"]?[0]?["delta"]?["content"]; if (delta != null) { onTokenReceived(delta.ToString()); } } } } } }