SeemGen/Services/DeepSeekApiService.cs

214 lines
8.0 KiB
C#

using BLAIzor.Models;
using Newtonsoft.Json;
using System.Net.Http;
using System.Text.Json;
using System.Text;
namespace BLAIzor.Services
{
public class DeepSeekApiService
{
private readonly IConfiguration _configuration;
private readonly HttpClient _httpClient;
public DeepSeekApiService(IConfiguration configuration, HttpClient httpClient)
{
_configuration = configuration;
_httpClient = httpClient;
}
private const string DeepSeekEndpoint = "https://api.deepseek.com/chat/completions";
public string _apiKey;
private Action<string> _callback;
public string GetApiKey()
{
if (_configuration == null)
{
return string.Empty;
}
if (_configuration.GetSection("DeepSeek") == null)
{
return string.Empty;
}
return _configuration.GetSection("DeepSeek").GetValue<string>("ApiKey")!;
}
public void RegisterCallback(Action<string> callback)
{
_callback = callback;
}
public async Task<string> GetSimpleChatGPTResponse(string systemMessage, string userMessage, string? assistantMessage = null)
{
_apiKey = GetApiKey();
var requestBody = new ChatGPTRequest();
if (assistantMessage == null)
{
requestBody = new ChatGPTRequest
{
Model = "deepseek-chat",
Temperature = 0.2,
Messages = new[]
{
new Message { Role = "system", Content = systemMessage },
new Message { Role = "user", Content = userMessage }
},
Stream = false
};
}
else
{
requestBody = new ChatGPTRequest
{
Model = "deepseek-chat",
Temperature = 0.2,
Messages = new[]
{
new Message { Role = "system", Content = systemMessage },
new Message {Role = "assistant", Content = assistantMessage },
new Message { Role = "user", Content = userMessage }
},
Stream = false
};
}
string requestJson = System.Text.Json.JsonSerializer.Serialize(requestBody, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false
}
);
var requestContent = new StringContent(requestJson, Encoding.UTF8, "application/json");
_httpClient.DefaultRequestHeaders.Clear();
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
var response = await _httpClient.PostAsync(DeepSeekEndpoint, requestContent);
response.EnsureSuccessStatusCode();
Console.Write(response.Content.ReadAsStringAsync());
var responseBody = await response.Content.ReadFromJsonAsync<JsonElement>();
Console.Write(responseBody.GetRawText());
var result = responseBody.GetProperty("choices")[0].GetProperty("message").GetProperty("content").GetString() ?? "No response";
Console.Write("Answer: " + result);
return result;
}
public async Task<string> GetChatGPTStreamedResponse(string sessionId, string systemMessage, string userMessage, string? assistanMessage = null)
{
_apiKey = GetApiKey();
ChatGPTRequest finalRequestBody;
if (assistanMessage == null)
{
finalRequestBody = new ChatGPTRequest
{
Model = "deepseek-chat",
Temperature = 0.2,
Messages = new[]
{
new Message { Role = "system", Content = systemMessage },
new Message { Role = "user", Content = userMessage }
},
Stream = true
};
}
else
{
finalRequestBody = new ChatGPTRequest
{
Model = "deepseek-chat",
Temperature = 0.2,
Messages = new[]
{
new Message { Role = "system", Content = systemMessage },
new Message {Role = "assistant", Content= assistanMessage},
new Message { Role = "user", Content = userMessage }
},
Stream = true
};
}
string requestJson = System.Text.Json.JsonSerializer.Serialize(finalRequestBody, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
}
);
var finalRequestContent = new StringContent(requestJson, Encoding.UTF8, "application/json");
Console.Write(finalRequestContent);
var httpRequest = new HttpRequestMessage(HttpMethod.Post, DeepSeekEndpoint)
{
Content = finalRequestContent
};
_httpClient.DefaultRequestHeaders.Clear();
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
// Use SendAsync with streamed response
var sResponse = await _httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);
sResponse.EnsureSuccessStatusCode();
using var responseStream = await sResponse.Content.ReadAsStreamAsync();
using var reader = new StreamReader(responseStream);
//Console.Write("Streamed response:");
string streamedHtmlContent = string.Empty;
while (!reader.EndOfStream)
{
var line = await reader.ReadLineAsync();
//Console.WriteLine($"Raw Stream Line: {line}"); // Log each line
if (!string.IsNullOrWhiteSpace(line) && line.StartsWith("data: "))
{
var jsonResponse = line.Substring(6); // Remove "data: " prefix
if (jsonResponse == "[DONE]")
{
Console.WriteLine("Stream ended.");
break; // End of stream
}
try
{
//Console.WriteLine($"JSON Response: {jsonResponse}"); // Debug JSON response
//TODO: do we really have to += the content, or should we just invoke with the delta?
var chunk = JsonConvert.DeserializeObject<StreamedResponse>(jsonResponse);
if (chunk?.Choices != null && chunk.Choices.Count > 0 && chunk.Choices[0].Delta?.Content != null)
{
streamedHtmlContent += chunk.Choices[0].Delta.Content; // Append the streamed content
if (!string.IsNullOrEmpty(streamedHtmlContent) && _callback != null)
{
_callback?.Invoke(streamedHtmlContent);
}
//Console.WriteLine($"Appended Text: {chunk.Choices[0].Delta.Content}"); // Debug appended text
}
else
{
Console.WriteLine("No content in this chunk.");
}
}
catch (JsonSerializationException ex)
{
Console.WriteLine($"Deserialization error: {ex.Message}");
}
}
}
Console.WriteLine("Final streamed content:");
Console.WriteLine(streamedHtmlContent);
return streamedHtmlContent;
}
}
}