From 575f8c7a6192588a8cba14b7cdb2a26ad3608bc1 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 25 Apr 2024 17:51:43 +0200 Subject: [PATCH] Mejorado con el uso de mensajes de sistema. Respuestas usando json. Tambien se llen las palabras de uso tecnico para intentar que no sean traducidas. Agregado ventana de notificaciones fija para mostrar el tiempo. --- App.xaml | 4 +- App.xaml.cs | 29 +++++++++---- Obsidean.cs | 97 ++++++++++++++++++++++++++++++++++++++++++++ Ollama/Modelfile | 6 +++ gtpask.cs | 84 +++++++++++++++++++++++++++++++------- notificacion.xaml | 14 +++++++ notificacion.xaml.cs | 45 ++++++++++++++++++++ 7 files changed, 256 insertions(+), 23 deletions(-) create mode 100644 Obsidean.cs create mode 100644 Ollama/Modelfile create mode 100644 notificacion.xaml create mode 100644 notificacion.xaml.cs diff --git a/App.xaml b/App.xaml index dd3d3a5..c6f9ce0 100644 --- a/App.xaml +++ b/App.xaml @@ -3,6 +3,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:GTPCorrgir"> - - + + diff --git a/App.xaml.cs b/App.xaml.cs index 4c0915a..3839a81 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -18,14 +18,16 @@ namespace GTPCorrgir gtpask GTP = new gtpask(); NotifyIcon notificacion; System.Windows.Forms.Timer timer; - int segundos = 0; bool CorreccionFinalizada = false; Stopwatch stopwatch = new Stopwatch(); + private notificacion notificationWindow; + protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); + stopwatch.Start(); if (System.Windows.Clipboard.ContainsText()) @@ -34,7 +36,7 @@ namespace GTPCorrgir } // Muestra notificación inicial y comienza el cronómetro en el hilo de la UI - MostrarNotificacion("Espera", "Corrigiendo texto..."); + ShowCustomNotification("Espera", "Corrigiendo texto..."); IniciarCronometro(); // Ejecuta la tarea de corrección en un hilo secundario @@ -59,7 +61,8 @@ namespace GTPCorrgir if (GTP.TextoCorregido != null) { System.Windows.Clipboard.SetText(GTP.TextoCorregido); - MostrarNotificacion("Corrección Lista", GTP.TextoCorregido); + ShowCustomNotification("Se puede pegar", $" Correccion en : {Math.Round(stopwatch.ElapsedMilliseconds / 1000.0, 1)} s" ); + Thread.Sleep(5000); // Espera 5 segundos } else { @@ -71,6 +74,17 @@ namespace GTPCorrgir }); } + private void ShowCustomNotification(string title, string message) + { + if (notificationWindow == null) + { + notificationWindow = new notificacion(); + notificationWindow.Show(); + } + + notificationWindow.UpdateNotification(title, message); + } + private void MostrarNotificacion(string titulo, string mensaje) { notificacion = new NotifyIcon @@ -83,10 +97,11 @@ namespace GTPCorrgir notificacion.ShowBalloonTip(1000); } + private void IniciarCronometro() { timer = new System.Windows.Forms.Timer(); - timer.Interval = 1000; // 1000 milisegundos (1 segundo) + timer.Interval = 100; // 1000 milisegundos (1 segundo) timer.Tick += ActualizarCronometro; timer.Start(); } @@ -94,9 +109,9 @@ namespace GTPCorrgir private void ActualizarCronometro(object sender, EventArgs e) { if (!CorreccionFinalizada) { - segundos++; - notificacion.BalloonTipText = $"Texto en {GTP.IdiomaDetectado} pasados: {Math.Round(stopwatch.ElapsedMilliseconds/1000.0,1)} s"; - notificacion.ShowBalloonTip(1000); + //notificacion.BalloonTipText = $"Texto en {GTP.IdiomaDetectado} pasados: {Math.Round(stopwatch.ElapsedMilliseconds/1000.0,1)} s"; + //notificacion.ShowBalloonTip(1000); + ShowCustomNotification("Trabajando..", $"Texto en {GTP.IdiomaDetectado} pasados: {Math.Round(stopwatch.ElapsedMilliseconds / 1000.0, 1)} s"); } } diff --git a/Obsidean.cs b/Obsidean.cs new file mode 100644 index 0000000..5c9fafe --- /dev/null +++ b/Obsidean.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Newtonsoft.Json.Linq; +using System.Text.RegularExpressions; + + +namespace GTPCorrgir +{ + internal class Obsidean + { + static HashSet technicalTerms; + + static string GetObsidianConfigPath() + { + string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + return Path.Combine(appDataPath, "obsidian", "obsidian.json"); + } + + static string GetVaultPath(string vaultName) + { + try + { + string pathToJsonFile = GetObsidianConfigPath(); + string jsonContent = File.ReadAllText(pathToJsonFile); + JObject jsonObject = JObject.Parse(jsonContent); + JObject vaults = (JObject)jsonObject["vaults"]; + + foreach (var vault in vaults) + { + // 'vault' es un KeyValuePair + // 'vault.Key' es la clave (ID del vault), 'vault.Value' es el valor (detalles del vault como JToken) + string path = (string)vault.Value["path"]; + if (!string.IsNullOrEmpty(path)) + { + // Añadir una barra al final asegura que Path.GetDirectoryName funcione correctamente + string lastDirectoryName = Path.GetFileName(Path.GetDirectoryName(path.TrimEnd('\\') + "\\")); + + if (lastDirectoryName.Equals(vaultName, StringComparison.OrdinalIgnoreCase)) + { + return path; + } + } + } + } + catch (Exception ex) + { + Console.WriteLine("Error al leer o parsear el archivo JSON: " + ex.Message); + } + return null; + } + + public void LeerPalabrasTecnicas() + { + // "C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\Palabras Tecnicas\Lista.md" + string pathToMarkdown = GetVaultPath("VM"); + if (!string.IsNullOrEmpty(pathToMarkdown)) + { + string pathToLista = pathToMarkdown + "\\Palabras Tecnicas\\Lista.md"; + string[] lines = File.ReadAllLines(pathToLista); + technicalTerms = ExtractTechnicalTerms(lines); + } + + // Ahora puedes usar technicalTerms para tu lógica de corrección + } + + public HashSet ExtractTechnicalTerms(string[] lines) + { + var terms = new HashSet(); + foreach (var line in lines) + { + // Suponiendo que cada línea contiene un término técnico + terms.Add(line.Trim()); + } + return terms; + } + + public string MarkTechnicalTerms(string text) + { + // Utilizar Regex para identificar palabras individualmente + return Regex.Replace(text, @"\b(\w+)\b", match => + { + string word = match.Groups[1].Value; + // Verificar si la palabra está en el conjunto de términos técnicos + if (technicalTerms.Contains(word)) + { + return $"[[{word}]]"; // Encerrar la palabra en corchetes si es técnica + } + return word; // Devolver la palabra sin modificar si no es técnica + }); + } + } + +} diff --git a/Ollama/Modelfile b/Ollama/Modelfile new file mode 100644 index 0000000..d400c33 --- /dev/null +++ b/Ollama/Modelfile @@ -0,0 +1,6 @@ +FROM llama3 + +# set the system message +SYSTEM """ +You are an engineer who works in industrial automation. You correct the texts in a simple and concise way when asked without explanations. Respond in the language that was told please. Response in json format. +""" \ No newline at end of file diff --git a/gtpask.cs b/gtpask.cs index 0075853..8e2e3db 100644 --- a/gtpask.cs +++ b/gtpask.cs @@ -7,29 +7,44 @@ using System.Threading.Tasks; using System.Windows.Threading; using LanguageDetection; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace GTPCorrgir { internal class gtpask { private readonly string openAiApiKey = "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"; - private readonly string accionGTP = "Me puedes corregir el siguiente texto y mejorarlo para que se comprenda mejor: "; private Dictionary languageMap = new Dictionary { - { "en", "Inglés" }, - { "es", "Español" }, - { "it", "Italiano" }, - { "pt", "Portugués" } + { "en", "English" }, + { "es", "Spanish" }, + { "it", "Italian" }, + { "pt", "Portuguese" } // Agrega más idiomas según sea necesario }; + public string IdiomaDetectado; public string TextoACorregir; public string TextoCorregido; + public string TextodeSistema; + + + private string CrearMensajeDeSistema() + { + return "You are an engineer working in industrial automation. Your task is to review texts and rewrite them in a simple and concise manner, making sure to preserve important technical terms specially if they are in English. Please rewrite the following text in " + IdiomaDetectado + " and respond in the following JSON format: { 'Rewritten_text': 'Your text here' }."; + } + + private string CrearMensajeDeUsuario(string texto) + { + return "Please rewrite and improve the following text to make it clearer and more concise the words inside brackets are technical words: \"" + texto + "\""; + } + private string DetectarIdioma(string TextoACorregir) { LanguageDetector detector = new LanguageDetector(); - detector.AddLanguages("en", "es", "it", "pt"); + + detector.AddLanguages("en", "es", "it"); string detectedLanguageCode = detector.Detect(TextoACorregir); string detectedLanguageName = languageMap.ContainsKey(detectedLanguageCode) @@ -51,8 +66,7 @@ namespace GTPCorrgir } public async Task CorregirTexto() - { - var Instrucciones = accionGTP; + { if (DetectarIdioma()) { if (IdiomaDetectado == "Desconocido" || this.TextoACorregir.Length == 0) @@ -62,18 +76,55 @@ namespace GTPCorrgir return; } - TextoACorregir = "El resultado debe estar en " + IdiomaDetectado + ". " + Instrucciones + "\"" + TextoACorregir + "\""; + var md = new Obsidean(); + md.LeerPalabrasTecnicas(); - TextoCorregido = await CallOpenAiApi(TextoACorregir); - //TextoCorregido = await CallOllamaApi(TextoACorregir); + TextoACorregir = md.MarkTechnicalTerms(TextoACorregir); + + //TextoCorregido = await CallOpenAiApi(TextoACorregir); + string RespuestaLLM = await CallOllamaApi(TextoACorregir); + + TextoCorregido = ExtractCorrectedText(RespuestaLLM); // Elimina comillas al principio y al final si existen TextoCorregido = TextoCorregido.Trim('\"'); } } + + static string ExtractCorrectedText(string input) + { + try + { + // Encuentra el índice del inicio y del final del JSON + int startJson = input.IndexOf('{'); + int endJson = input.IndexOf('}') + 1; + + if (startJson == -1 || endJson == -1 || endJson <= startJson) + { + throw new Exception("No valid JSON found in the input string."); + } + + // Extrae solo la parte JSON de la entrada + string jsonString = input.Substring(startJson, endJson - startJson); + + // Parsea el JSON y extrae el campo "Rewritten_text" + JObject jsonObject = JObject.Parse(jsonString); + string rewrittenText = (string)jsonObject["Rewritten_text"]; + return rewrittenText; + } + catch (Exception ex) + { + Console.WriteLine("An error occurred: " + ex.Message); + return null; + } + } + private async Task CallOllamaApi(string input) { var httpClient = new HttpClient(); + string Mensaje_Sistema = CrearMensajeDeSistema(); + string Mensaje_Usuario = CrearMensajeDeUsuario(input); + httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {openAiApiKey}"); var requestData = new @@ -81,7 +132,8 @@ namespace GTPCorrgir model = "llama3", messages = new[] { - new { role = "user", content = input }, + new { role = "system", content = Mensaje_Sistema }, + new { role = "user", content = Mensaje_Usuario } }, stream = false }; @@ -114,9 +166,13 @@ namespace GTPCorrgir } } + private async Task CallOpenAiApi(string input) { var httpClient = new HttpClient(); + string Mensaje_Sistema = CrearMensajeDeSistema(); + string Mensaje_Usuario = CrearMensajeDeUsuario(input); + httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {openAiApiKey}"); var requestData = new @@ -124,8 +180,8 @@ namespace GTPCorrgir model = "gpt-4", messages = new[] { - new { role = "system", content = "Este es un mensaje del sistema inicializando la conversación" }, - new { role = "user", content = input } + new { role = "system", content = Mensaje_Sistema }, + new { role = "user", content = Mensaje_Usuario } } }; diff --git a/notificacion.xaml b/notificacion.xaml new file mode 100644 index 0000000..93b8ae2 --- /dev/null +++ b/notificacion.xaml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/notificacion.xaml.cs b/notificacion.xaml.cs new file mode 100644 index 0000000..cb6680c --- /dev/null +++ b/notificacion.xaml.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace GTPCorrgir +{ + /// + /// Interaction logic for notificacion.xaml + /// + public partial class notificacion : Window + { + public notificacion() + { + InitializeComponent(); + PositionWindow(); + } + private void PositionWindow() + { + // Obtener la posición del cursor + var cursorPosition = System.Windows.Forms.Cursor.Position; + + // Determinar en qué pantalla está el cursor + var screen = Screen.FromPoint(cursorPosition); + + // Configurar la ubicación de la ventana para que aparezca en la esquina inferior derecha + this.Left = screen.WorkingArea.Right - this.Width; + this.Top = screen.WorkingArea.Bottom - this.Height; + } + public void UpdateNotification(string title, string message) + { + TitleText.Text = title; + MessageText.Text = message; + } + } +}