Le code décrit ici permet d'ajouter dans l'éditeur HTML deux accès qui offrent une liaison avec ChatGPT pour
- vérifier l'orthographe
- revoir la formulation

Pour la reformulation, Mercator demande d'abord le contexte que l'on souhaite indiquer à ChatGPT afin de réorienter la formulation. Dans les deux situations, lorsqu'un résultat est obtenu :
- le bouton "OK" permet d'accepter la proposition de ChatGPT.
- le bouton "Annuler" arrête le processus et laisse le texte d'origine inchangé.
- le bouton "Interroger" permet de poser une question supplémentaire et de donner une nouvelle consigne via le champ situé dans le bas de cet écran.
Ceci requiert l'installation du plugin MercatorAI.OpenAI et ne fonctionne qu'avec une version Core de Mercator. (Le code est toutefois compilable dans une version classique).
Le code s'établit comme suit :
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using MercatorApi;
using MercatorUi;
using MercatorExtensions;
using MercatorDatabase;
using MercatorAI;
// <CompileWithRoslyn />
namespace Action
{
public class Customizer : MercatorUi.ICustomizers.IActionEngineCreated, MercatorUi.ICustomizers.IActionEngineClosed
{
public void ActionEngineCreated(MercatorUi.Engine.Crm.ActionEngine actionEngine)
{
actionEngine.ActionFormLoaded += actionEngine_ActionFormLoaded;
}
public void ActionEngineClosed(MercatorUi.Engine.Crm.ActionEngine actionEngine)
{
actionEngine.ActionFormLoaded -= actionEngine_ActionFormLoaded;
}
void actionEngine_ActionFormLoaded(object sender, EventArgs arg)
{
MercatorUi.Engine.Crm.ActionEngine actionEngine = (MercatorUi.Engine.Crm.ActionEngine)sender;
foreach (MercatorUi.MovableControls.MovableHtmlBox2 htmlBox in actionEngine.ActionForm.MovableControls.Values.OfType<MercatorUi.MovableControls.MovableHtmlBox2>())
{
ToolStripDropDownButton toolStripDropDownButtonAI = new ToolStripDropDownButton("", GraphicKit.CurrentGraphicKit.Images.AI16) { AutoSize = true, Padding = new Padding(3) };
ToolStripItem[] items = new ToolStripItem[2]
{
new ToolStripSeparator(),
toolStripDropDownButtonAI
};
htmlBox.AddToolStripItems(items);
ToolStripMenuItem menuItemSpelling = new ToolStripMenuItem(_Divers.Iif_langue(Globals.Langue, "Rechtschreibung prüfen", "Check spelling", "Spelling controleren", "Vérifier orthographe"), null, (s, e) =>
{
string htmlText = System.Net.WebUtility.HtmlDecode(htmlBox.HtmlText);
if (string.IsNullOrWhiteSpace(htmlText))
return;
FactoryOpenAI factory = new FactoryOpenAI();
MercatorAI.Interfaces.IOpenAiChat openAiChat = factory.CreateOpenAiChat("gpt-4o-mini", out string error);
if (!string.IsNullOrEmpty(error))
{
Dialogs.Stop("Impossible d'initialiser le chat d'OpenAI : " + error, actionEngine.ActionForm);
return;
}
string systemMessage = _Divers.Iif_langue(Globals.Langue,
"Du bist ein Experte für Rechtschreibung. Du antwortest ausschließlich in der angeforderten JSON-Struktur.",
"You are an expert in spelling. You respond only in the requested JSON structure.",
"Je bent een expert in spelling. Je antwoordt uitsluitend in de gevraagde JSON-structuur.",
"Tu es un expert en orthographe. Tu réponds uniquement dans la structure json demandée.");
string prompt = _Divers.Iif_langue(Globals.Langue, "Kannst du die Rechtschreibfehler in diesem Text korrigieren, ohne den Stil zu ändern?", "Can you correct the spelling mistakes in this text without changing the style?", "Kan je de spelfouten in deze tekst corrigeren zonder de stijl te wijzigen?", "Peux-tu corriger les fautes d'orthographe dans ce texte sans modifier le style.") + "\n" + htmlText;
FactoryOpenAI.ChatOptions chatOptions = new FactoryOpenAI.ChatOptions
{
Temperature = 0f, // déterministe
TopP = 1.0f // Aucun besoin de restreindre davantage, la température suffit
};
while (true)
{
ResponseDescriptor r = null;
MercatorUi.Wait.WaitStatic.WaitWindowBaseThread(Api.Iif_langue(Globals.Langue, IifLangueEnum.AIisThinking));
MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync exclusiveBackgroundWorkerAsync = new MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync(async () => r = await openAiChat.AskAsync<ResponseDescriptor>(prompt, "SpellCheck", systemMessage: systemMessage, chatOptions: chatOptions), formWhereToCenterLoadingCircle: actionEngine.ActionForm);
MercatorUi.Wait.WaitStatic.WaitClearBaseThread();
if (exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork != null)
{
Dialogs.Stop(exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork.Message, actionEngine.ActionForm);
return;
}
if (r.IsCorrect)
{
Dialogs.Stop(_Divers.Iif_langue(Globals.Langue, "Der Text darf nicht verändert werden!", "The text must not be modified!", "De tekst mag niet worden gewijzigd!", "Le texte ne doit pas être modifié !"), actionEngine.ActionForm);
return;
}
systemMessage = null;
DialogResult dialogResult = Dialogs.MiniChat(r.Comment, r.Content, out prompt);
if (dialogResult == DialogResult.Cancel)
{
return;
}
else if (dialogResult == DialogResult.OK)
{
htmlBox.HtmlText = r.Content;
return;
}
}
});
ToolStripMenuItem menuItemReformulate = new ToolStripMenuItem(_Divers.Iif_langue(Globals.Langue, "Text umformulieren", "Reformulate text", "Tekst herformuleren", "Reformuler texte"), null, (s, e) =>
{
string htmlText = System.Net.WebUtility.HtmlDecode(htmlBox.HtmlText);
if (string.IsNullOrWhiteSpace(htmlText))
return;
FactoryOpenAI factory = new FactoryOpenAI();
MercatorAI.Interfaces.IOpenAiChat openAiChat = factory.CreateOpenAiChat("gpt-4o-mini", out string error);
if (!string.IsNullOrEmpty(error))
{
Dialogs.Stop("Impossible d'initialiser le chat d'OpenAI : " + error, actionEngine.ActionForm);
return;
}
string systemMessage = _Divers.Iif_langue(Globals.Langue,
"Du bist ein Assistent für Texterstellung. Du formulierst diesen Text für den angegebenen Kontext um.",
"You are a writing assistant. You rephrase this text for the given context.",
"Je bent een tekstschrijfassistent. Je herformuleert deze tekst voor de aangegeven context.",
"Tu es un assistant en rédaction de texte. Tu reformules ce texte pour le contexte indiqué.");
string prompt = Dialogs.AskMemo(_Divers.Iif_langue(Globals.Langue, "Ihre Anweisung für die KI?", "Your instruction for the AI?", "Uw instructie voor de AI?", "Votre consigne pour l'IA ?"),
_Divers.Iif_langue(Globals.Langue, "Formulieren Sie den Text um, um ihn professioneller zu gestalten.", "Revise the wording to make it more professional.", "Herformuleer de tekst om deze professioneler te maken.", "Revoir la formulation pour la rendre plus professionnelle."));
if (string.IsNullOrWhiteSpace(prompt))
return;
prompt += "\n" + htmlText;
FactoryOpenAI.ChatOptions chatOptions = new FactoryOpenAI.ChatOptions
{
Temperature = 0.2f, // Reformulation très sobre / proche du texte original
TopP = 1.0f // Aucun besoin de tronquer le spectre probabiliste, ça limiterait inutilement les nuances
};
while (true)
{
ResponseDescriptor r = null;
MercatorUi.Wait.WaitStatic.WaitWindowBaseThread(Api.Iif_langue(Globals.Langue, IifLangueEnum.AIisThinking));
MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync exclusiveBackgroundWorkerAsync = new MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync(async () => r = await openAiChat.AskAsync<ResponseDescriptor>(prompt, "Reformulate", systemMessage: systemMessage, chatOptions: chatOptions), formWhereToCenterLoadingCircle: actionEngine.ActionForm);
MercatorUi.Wait.WaitStatic.WaitClearBaseThread();
if (exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork != null)
{
Dialogs.Stop(exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork.Message, actionEngine.ActionForm);
return;
}
if (r.IsCorrect)
{
Dialogs.Stop(_Divers.Iif_langue(Globals.Langue, "Der Text darf nicht verändert werden!", "The text must not be modified!", "De tekst mag niet worden gewijzigd!", "Le texte ne doit pas être modifié !"), actionEngine.ActionForm);
return;
}
systemMessage = null;
DialogResult dialogResult = Dialogs.MiniChat(r.Comment, r.Content, out prompt);
if (dialogResult == DialogResult.Cancel)
{
return;
}
else if (dialogResult == DialogResult.OK)
{
htmlBox.HtmlText = r.Content;
return;
}
}
});
toolStripDropDownButtonAI.DropDownItems.AddRange(new ToolStripItem[] { menuItemSpelling, menuItemReformulate });
}
}
}
public class ResponseDescriptor
{
[FactoryOpenAI.ChatJsonFormat(DescriptionF = "True si le texte ne doit pas être modifié", DescriptionN = "True als de tekst niet gewijzigd hoeft te worden", DescriptionE = "True if the text does not need to be modified", DescriptionD = "True, wenn der Text nicht geändert werden muss", IsRequired = false)]
public bool IsCorrect { get; set; }
[FactoryOpenAI.ChatJsonFormat(DescriptionF = "Contenu HTML corrigé/modifié", DescriptionN = "Gewijzigde/gecorrigeerde HTML-inhoud", DescriptionE = "Corrected/modified HTML content", DescriptionD = "Korrigierter/geänderter HTML-Inhalt", IsRequired = false)]
public string Content { get; set; }
[FactoryOpenAI.ChatJsonFormat(DescriptionF = "Commentaire ou remarque", DescriptionN = "Commentaar of opmerking", DescriptionE = "Comment or remark", DescriptionD = "Kommentar oder Bemerkung", IsRequired = false)]
public string Comment { get; set; }
}
}
Les informations à corriger sont envoyées à un tiers (OpenAI). Il ne faut donc en aucun cas transmettre des données revêtant un caractère confidentiel.
Les corrections effectuées par ce code sont générées automatiquement à l’aide d’un modèle d’intelligence artificielle (IA). Bien que conçu pour fournir des réponses utiles et pertinentes, ces traductions peuvent être incomplètes, inexactes, partiellement ou totalement.
L’utilisateur reste seul responsable de l'évaluation et de l’utilisation de ces traductions. En aucun cas Mercator ou le fournisseur du service IA ne saurait être tenu responsable des conséquences qui découleraient de l'utilisation de ces traductions.
L'usage de ce service doit être rendu compatible avec les normes relatives au RGPD qui sont en place dans l'entreprise.