All checks were successful
Mindforge API Build and Deploy / Build Mindforge API Image (push) Successful in 3m39s
Mindforge Cronjob Build and Deploy / Build Mindforge Cronjob Image (push) Successful in 3m49s
Mindforge API Build and Deploy / Deploy Mindforge API (internal) (push) Successful in 38s
Mindforge Cronjob Build and Deploy / Deploy Mindforge Cronjob (internal) (push) Successful in 30s
95 lines
3.6 KiB
C#
95 lines
3.6 KiB
C#
using System;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace Mindforge.API.Providers
|
|
{
|
|
public class OpenAIApiProvider : ILlmApiProvider
|
|
{
|
|
private readonly HttpClient _httpClient;
|
|
private readonly IConfiguration _configuration;
|
|
private readonly ILogger<OpenAIApiProvider> _logger;
|
|
|
|
public OpenAIApiProvider(HttpClient httpClient, IConfiguration configuration, ILogger<OpenAIApiProvider> logger)
|
|
{
|
|
_httpClient = httpClient;
|
|
_httpClient.Timeout = TimeSpan.FromMinutes(5);
|
|
_configuration = configuration;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<string> SendRequestAsync(string systemPrompt, string userPrompt)
|
|
{
|
|
var apiUrl = _configuration["OPENAI_API_URL"];
|
|
if (string.IsNullOrEmpty(apiUrl))
|
|
throw new Exception("OPENAI_API_URL not found in configuration.");
|
|
|
|
var token = _configuration["OPENAI_TOKEN"];
|
|
if (string.IsNullOrEmpty(token))
|
|
throw new Exception("OPENAI_TOKEN not found in configuration.");
|
|
|
|
var model = _configuration["OPENAI_MODEL"];
|
|
if (string.IsNullOrEmpty(model))
|
|
throw new Exception("OPENAI_MODEL not found in configuration.");
|
|
|
|
var url = $"{apiUrl.TrimEnd('/')}/chat/completions";
|
|
|
|
var reqBody = new
|
|
{
|
|
model = model,
|
|
messages = new[]
|
|
{
|
|
new { role = "system", content = systemPrompt },
|
|
new { role = "user", content = userPrompt }
|
|
}
|
|
};
|
|
|
|
var jsonBody = JsonSerializer.Serialize(reqBody);
|
|
|
|
Exception? lastErr = null;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
using var request = new HttpRequestMessage(HttpMethod.Post, url);
|
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
|
request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
|
|
|
|
try
|
|
{
|
|
var response = await _httpClient.SendAsync(request);
|
|
var responseBody = await response.Content.ReadAsStringAsync();
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
lastErr = new Exception($"API error status {(int)response.StatusCode}: {responseBody}");
|
|
await Task.Delay(TimeSpan.FromSeconds(1 << i));
|
|
continue;
|
|
}
|
|
|
|
var result = JsonSerializer.Deserialize<JsonElement>(responseBody);
|
|
if (result.TryGetProperty("choices", out var choices) && choices.GetArrayLength() > 0)
|
|
{
|
|
var message = choices[0].GetProperty("message");
|
|
return message.GetProperty("content").GetString() ?? string.Empty;
|
|
}
|
|
|
|
_logger.LogWarning("API raw response: {responseBody}", responseBody);
|
|
throw new Exception("Empty response from API.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error in API request");
|
|
lastErr = ex;
|
|
await Task.Delay(TimeSpan.FromSeconds(1 << i));
|
|
}
|
|
}
|
|
|
|
throw new Exception($"Failed to get response after 5 attempts. Last error: {lastErr?.Message}", lastErr);
|
|
}
|
|
}
|
|
}
|