using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using LanguageDetection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Diagnostics; using CtrEditor.FuncionesBase; namespace GTPCorrgir { public class Opciones { public enum LLM_a_Usar { OpenAI, Ollama, Groq, Grok } public enum modoDeUso { Corregir, Ortografia, Traducir_a_Ingles, Traducir_a_Italiano, Traducir_a_Espanol, } public Dictionary nombreLLM = new Dictionary { { LLM_a_Usar.Ollama, "Ollama" }, { LLM_a_Usar.Groq, "Groq" }, { LLM_a_Usar.Grok, "Grok" }, { LLM_a_Usar.OpenAI, "OpenAI" }, }; public LLM_a_Usar LLM { get; set; } public modoDeUso modo { get; set; } public string nombreDeLLM() { return nombreLLM[LLM]; } public Opciones() { } // Changed from private to public } public class ApiSettings { public class ApiKeySection { public string OpenAI { get; set; } public string Groq { get; set; } public string Grok { get; set; } } public ApiKeySection ApiKeys { get; set; } } public class gtpask : IDisposable { private string _openAiApiKey; private string _groqApiKey; private string _grokApiKey; private readonly HttpClient _httpClient; private bool _disposed; public string IdiomaDetectado { get; private set; } public string TextoACorregir { get; set; } public string TextoCorregido { get; private set; } public string TextodeSistema { get; set; } public gtpask() { try { _httpClient = new HttpClient(); LoadApiKeys(); InitializeHttpClient(); } catch (Exception ex) { throw new ApplicationException("Failed to initialize gtpask", ex); } } private void LoadApiKeys() { try { string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "IA/appsettings.json"); if (!File.Exists(configPath)) { throw new FileNotFoundException("Configuration file (appsettings.json) not found."); } string jsonContent = File.ReadAllText(configPath); var settings = JsonConvert.DeserializeObject(jsonContent); _openAiApiKey = settings?.ApiKeys?.OpenAI; _groqApiKey = settings?.ApiKeys?.Groq; _grokApiKey = settings?.ApiKeys?.Grok; ValidateApiKeys(); } catch (Exception ex) { throw new ApplicationException("Failed to load API keys", ex); } } private void ValidateApiKeys() { var missingKeys = new List(); if (string.IsNullOrEmpty(_openAiApiKey)) missingKeys.Add("OpenAI"); if (string.IsNullOrEmpty(_groqApiKey)) missingKeys.Add("Groq"); if (string.IsNullOrEmpty(_grokApiKey)) missingKeys.Add("Grok"); if (missingKeys.Any()) { string missingKeysStr = string.Join(", ", missingKeys); throw new ApplicationException($"Missing API keys: {missingKeysStr}"); } } private void InitializeHttpClient() { _httpClient.Timeout = TimeSpan.FromSeconds(30); _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); } private bool DetectarIdioma() { try { IdiomaDetectado = Idiomas.DetectarIdioma(TextoACorregir); return IdiomaDetectado != "Unknown"; } catch { return false; } } private async Task ProcesarTextoConLLM( Opciones Modelo) { try { string respuestaLLM; switch (Modelo.LLM) { case Opciones.LLM_a_Usar.OpenAI: respuestaLLM = await CallOpenAiApi(); break; case Opciones.LLM_a_Usar.Ollama: respuestaLLM = await CallOllamaApi(); break; case Opciones.LLM_a_Usar.Groq: respuestaLLM = await CallGroqAiApi(); break; case Opciones.LLM_a_Usar.Grok: respuestaLLM = await CallGrokApi(); break; default: throw new ArgumentException("LLM no válido"); } if (string.IsNullOrEmpty(respuestaLLM)) { throw new ApplicationException("No se recibió respuesta del LLM"); } TextoCorregido = respuestaLLM; } catch (Exception ex) { throw; } } private async Task SimularCorreccion() { await Task.Delay(1000); TextoCorregido = "Texto simulado de prueba"; } private async Task CallGrokApi() { try { _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_grokApiKey}"); var requestData = new { messages = new[] { new { role = "system", content = TextodeSistema }, new { role = "user", content = TextoACorregir } }, model = "grok-beta", stream = false, temperature = 0 }; return await EnviarSolicitudLLM("https://api.x.ai/v1/chat/completions", requestData); } catch (Exception ex) { throw; } } private async Task CallOllamaApi() { try { var requestData = new { model = "llama3.2:latest", messages = new[] { new { role = "system", content = TextodeSistema }, new { role = "user", content = TextoACorregir } }, stream = false }; return await EnviarSolicitudLLM("http://127.0.0.1:11434/api/chat", requestData); } catch (Exception ex) { throw; } } private async Task CallOpenAiApi() { try { _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_openAiApiKey}"); var requestData = new { model = "gpt-4o-mini", messages = new[] { new { role = "system", content = TextodeSistema }, new { role = "user", content = TextoACorregir } } }; return await EnviarSolicitudLLM("https://api.openai.com/v1/chat/completions", requestData); } catch (Exception ex) { throw; } } private async Task CallGroqAiApi() { try { _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_groqApiKey}"); var requestData = new { model = "llama-3.2-3b-preview", messages = new[] { new { role = "system", content = TextodeSistema }, new { role = "user", content = TextoACorregir } }, max_tokens = 2048, stream = false }; return await EnviarSolicitudLLM("https://api.groq.com/openai/v1/chat/completions", requestData); } catch (Exception ex) { throw; } } private async Task EnviarSolicitudLLM(string endpoint, object requestData) { try { var content = new StringContent( JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json" ); using var response = await _httpClient.PostAsync(endpoint, content); var responseContent = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { throw new HttpRequestException( $"Error en la solicitud HTTP: {response.StatusCode} - {responseContent}" ); } var data = JsonConvert.DeserializeObject(responseContent); // Manejar diferentes formatos de respuesta según el LLM if (endpoint.Contains("ollama")) { if (data.done == true && data.message != null) { return data.message.content; } throw new ApplicationException("Formato de respuesta de Ollama inválido"); } else // OpenAI, Groq, Grok { if (data.choices != null && data.choices.Count > 0) { return data.choices[0].message.content; } throw new ApplicationException("No se encontró contenido en la respuesta del LLM"); } } catch (Exception ex) { throw; } } public async Task CorregirTexto() { try { if (string.IsNullOrEmpty(TextoACorregir)) { throw new ArgumentException("TextoACorregir cannot be null or empty"); } if (string.IsNullOrEmpty(TextodeSistema)) { throw new ArgumentException("TextodeSistema cannot be null or empty"); } var opciones = new Opciones { LLM = Opciones.LLM_a_Usar.Grok }; await ProcesarTextoConLLM(opciones); } catch (Exception ex) { throw new LLMException("Error during text correction", ex); } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { _httpClient?.Dispose(); } _disposed = true; } } ~gtpask() { Dispose(false); } } // Clase auxiliar para manejar excepciones específicas de la aplicación public class LLMException : Exception { public LLMException(string message) : base(message) { } public LLMException(string message, Exception innerException) : base(message, innerException) { } } // Clase auxiliar para validación public static class Validations { public static void ValidateNotNull(object value, string paramName) { if (value == null) { throw new ArgumentNullException(paramName); } } public static void ValidateNotNullOrEmpty(string value, string paramName) { if (string.IsNullOrEmpty(value)) { throw new ArgumentException("Value cannot be null or empty", paramName); } } } }