From 534fc3293d0a69e09b5a869d5480d7c0540df089 Mon Sep 17 00:00:00 2001 From: Mykyta Dubovyi Date: Sat, 14 Oct 2023 22:03:50 +0300 Subject: [PATCH] SA-29 bugs fixed --- .../IServices/Identity/IOpenAiService.cs | 10 -- .../Services/Identity/OpenAiService.cs | 101 ------------------ .../Services/OpenAiService.cs | 72 ++++++++++++- 3 files changed, 67 insertions(+), 116 deletions(-) delete mode 100644 ShoppingAssistantApi.Application/IServices/Identity/IOpenAiService.cs delete mode 100644 ShoppingAssistantApi.Infrastructure/Services/Identity/OpenAiService.cs diff --git a/ShoppingAssistantApi.Application/IServices/Identity/IOpenAiService.cs b/ShoppingAssistantApi.Application/IServices/Identity/IOpenAiService.cs deleted file mode 100644 index 0f5d5d1..0000000 --- a/ShoppingAssistantApi.Application/IServices/Identity/IOpenAiService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using ShoppingAssistantApi.Application.Models.OpenAi; - -namespace ShoppingAssistantApi.Application.IServices; - -public interface IOpenAiService -{ - Task GetChatCompletion(ChatCompletionRequest chat, CancellationToken cancellationToken); - - IAsyncEnumerable GetChatCompletionStream(ChatCompletionRequest chat, CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/ShoppingAssistantApi.Infrastructure/Services/Identity/OpenAiService.cs b/ShoppingAssistantApi.Infrastructure/Services/Identity/OpenAiService.cs deleted file mode 100644 index 88e4b50..0000000 --- a/ShoppingAssistantApi.Infrastructure/Services/Identity/OpenAiService.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Net.Http.Headers; -using System.Text; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using ShoppingAssistantApi.Application.IServices; -using ShoppingAssistantApi.Application.Models.OpenAi; - -namespace ShoppingAssistantApi.Infrastructure.Services; - -public class OpenaiService : IOpenAiService -{ - private readonly HttpClient _httpClient; - - private readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings - { - ContractResolver = new DefaultContractResolver - { - NamingStrategy = new SnakeCaseNamingStrategy() - }, - NullValueHandling = NullValueHandling.Ignore, - }; - - private readonly IConfiguration _configuration; - - //private readonly OpenAIClient _openAiClient; - - private readonly ILogger _logger; - - public OpenaiService( - IConfiguration configuration, - IHttpClientFactory httpClientFactory, - ILogger logger - ) - { - _httpClient = httpClientFactory.CreateClient("OpenAiHttpClient"); - _configuration = configuration; - - //var openAIApiKey = _configuration.GetSection("OpenAi")?.GetValue("ApiKey"); - //_openAiClient = new OpenAIClient(openAIApiKey, new OpenAIClientOptions()); - - _logger = logger; - } - - public async IAsyncEnumerable GetChatCompletionStream(ChatCompletionRequest chat, CancellationToken cancellationToken) - { - chat.Stream = true; - var jsonBody = JsonConvert.SerializeObject(chat, _jsonSettings); - _logger.LogInformation(jsonBody); - var body = new StringContent(jsonBody, Encoding.UTF8, "application/json"); - var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions") - { - Content = body - }; - request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream")); - - using var httpResponse = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); - - var allData = string.Empty; - - using var streamReader = new StreamReader(await httpResponse.Content.ReadAsStringAsync(cancellationToken)); - while(!streamReader.EndOfStream) - { - var line = await streamReader.ReadLineAsync(); - allData += line + "\n\n"; - if (string.IsNullOrEmpty(line)) continue; - - var json = line?.Substring(6, line.Length - 6); - if (json == "[DONE]") yield break; - - var OpenAiResponse = JsonConvert.DeserializeObject(json, _jsonSettings); - yield return OpenAiResponse; - } - } - - public async Task GetChatCompletion(ChatCompletionRequest chat, CancellationToken cancellationToken) - { - chat.Stream = false; - var jsonBody = JsonConvert.SerializeObject(chat, _jsonSettings); - var body = new StringContent(jsonBody, Encoding.UTF8, "application/json"); - - _logger.LogInformation(jsonBody); - using var httpResponse = await _httpClient.PostAsync("chat/completions", body, cancellationToken); - - var responseBody = await httpResponse.Content.ReadAsStringAsync(cancellationToken); - - var responses = new List(); - foreach (var line in responseBody.Split(new[] {"\n\n"}, StringSplitOptions.RemoveEmptyEntries)) - { - if (line.Trim() == "[DONE]") break; - - var json = line.Substring(6); - var OpenAiResponse = JsonConvert.DeserializeObject(json, _jsonSettings); - responses.Add(OpenAiResponse); - } - - return responses.Count > 0 ? responses.Last() : null; - } -} \ No newline at end of file diff --git a/ShoppingAssistantApi.Infrastructure/Services/OpenAiService.cs b/ShoppingAssistantApi.Infrastructure/Services/OpenAiService.cs index 9ed750a..1d083e4 100644 --- a/ShoppingAssistantApi.Infrastructure/Services/OpenAiService.cs +++ b/ShoppingAssistantApi.Infrastructure/Services/OpenAiService.cs @@ -1,3 +1,8 @@ +using System; +using System.Net.Http.Headers; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; using ShoppingAssistantApi.Application.IServices; using ShoppingAssistantApi.Application.Models.OpenAi; @@ -5,6 +10,16 @@ namespace ShoppingAssistantApi.Infrastructure.Services; public class OpenAiService : IOpenAiService { + + private readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings + { + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new SnakeCaseNamingStrategy() + }, + NullValueHandling = NullValueHandling.Ignore, + }; + private readonly HttpClient _httpClient; public OpenAiService(HttpClient client) @@ -12,13 +27,60 @@ public class OpenAiService : IOpenAiService _httpClient = client; } - public Task GetChatCompletion(ChatCompletionRequest chat, CancellationToken cancellationToken) + + + public async Task GetChatCompletion(ChatCompletionRequest chat, CancellationToken cancellationToken) { - throw new NotImplementedException(); + chat.Stream = false; + var jsonBody = JsonConvert.SerializeObject(chat, _jsonSettings); + var body = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + + + using var httpResponse = await _httpClient.PostAsync("chat/completions", body, cancellationToken); + + var responseBody = await httpResponse.Content.ReadAsStringAsync(cancellationToken); + + var responses = new List(); + foreach (var line in responseBody.Split(new[] {"\n\n"}, StringSplitOptions.RemoveEmptyEntries)) + { + if (line.Trim() == "[DONE]") break; + + var json = line.Substring(6); + var OpenAiMessage = JsonConvert.DeserializeObject(json, _jsonSettings); + responses.Add(OpenAiMessage); + } + + return responses.Count > 0 ? responses.Last() : null; } - public IAsyncEnumerable GetChatCompletionStream(ChatCompletionRequest chat, CancellationToken cancellationToken) + public async IAsyncEnumerable GetChatCompletionStream(ChatCompletionRequest chat, CancellationToken cancellationToken) { - throw new NotImplementedException(); + chat.Stream = true; + var jsonBody = JsonConvert.SerializeObject(chat, _jsonSettings); + + var body = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions") + { + Content = body + }; + request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream")); + + using var httpResponse = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); + + var allData = string.Empty; + + using var streamReader = new StreamReader(await httpResponse.Content.ReadAsStringAsync(cancellationToken)); + while(!streamReader.EndOfStream) + { + var line = await streamReader.ReadLineAsync(); + allData += line + "\n\n"; + if (string.IsNullOrEmpty(line)) continue; + + var json = line?.Substring(6, line.Length - 6); + if (json == "[DONE]") yield break; + + var OpenAiResponse = JsonConvert.DeserializeObject(json, _jsonSettings); + yield return OpenAiResponse; + } } -} +} \ No newline at end of file