using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MercatorUi;
using MercatorApi;
using MercatorExtensions;
// <CompileWithRoslyn />
namespace MyAssembly
{
public static class ChatGPT
{
private const string tutosCollectionName = "Tutos";
public static async Task SearchInTutos()
{
MercatorAI.FactoryOpenAI factoryOpenAI = new MercatorAI.FactoryOpenAI();
MercatorAI.Interfaces.IOpenAiEmbeddingGeneratorClient openAiEmbeddingGeneratorClient = factoryOpenAI.CreateOpenAiEmbeddingGeneratorClient<string>("text-embedding-3-small", out string error);
if (!string.IsNullOrEmpty(error))
{
Dialogs.Stop("Impossible d'initialiser le générateur d'embeddings d'OpenAI : " + error);
return;
}
MercatorAI.FactoryQdrant factoryQdrant = new MercatorAI.FactoryQdrant();
MercatorAI.Interfaces.IQdrantClient qdrantClient = factoryQdrant.CreateQdrantClient("http://192.168...:6334", out error);
if (!string.IsNullOrEmpty(error))
{
Dialogs.Stop("Impossible d'initialiser le client Qdrant : " + error);
return;
}
MercatorUi.Wait.WaitStatic.WaitWindow(Api.Iif_langue(Globals.Langue, IifLangueEnum.AIisThinking));
if (!await qdrantClient.CollectionExistsAsync(tutosCollectionName))
{
qdrantClient.Dispose();
MercatorUi.Wait.WaitStatic.WaitClear();
Dialogs.Stop($"La collection \"{tutosCollectionName}\" n'existe pas sur le serveur Qdrant !");
return;
}
MercatorUi.Forms.Other.ChatForm chatForm = MercatorUi.Forms.Other.ChatForm.SimpleOpenAiChat("gpt-4o", tutosCollectionName, systemMessage: null, question: "", false, chatOptions: null, standardStreamingAction: MercatorUi.Forms.Other.ChatForm.StandardStreamingActionEnum.RawStreamShow);
MercatorUi.Wait.WaitStatic.WaitClear();
if (chatForm == null)
{
qdrantClient.Dispose();
return;
}
chatForm.Disposed += (s, e) =>
{
qdrantClient.Dispose();
};
MercatorUi.Forms.Other.ChatForm.BeforeAskEventHandler beforeAskEventHandler = null;
beforeAskEventHandler = (s, e) =>
{
if (string.IsNullOrWhiteSpace(chatForm.TextBoxQuestion.Text))
{
_Divers.FocusError(chatForm.TextBoxQuestion);
return;
}
(double? score, DocChunk docChunk)[] hits = null;
MercatorUi.Wait.WaitStatic.WaitWindowBaseThread(Api.Iif_langue(Globals.Langue, IifLangueEnum.AIisThinking));
MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync exclusiveBackgroundWorkerAsync = new MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync(async () =>
{
float[] questionAsVectors = await openAiEmbeddingGeneratorClient.GenerateEmbeddingAsync(chatForm.TextBoxQuestion.Text);
hits = await qdrantClient.ClientSearchAsync<Guid, DocChunk>(tutosCollectionName, questionAsVectors, top: 5);
}, formWhereToCenterLoadingCircle: chatForm);
MercatorUi.Wait.WaitStatic.WaitClearBaseThread();
if (exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork != null)
{
Dialogs.Stop(exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork.Message, chatForm);
return;
}
if ((hits == null) || !hits.Any())
{
Dialogs.Stop("Aucune correspondance trouvée dans la documentation !", chatForm);
return;
}
var sb = new StringBuilder();
foreach ((double? score, DocChunk docChunk) hit in hits)
{
sb.AppendLine(hit.docChunk.Content);
}
chatForm.SimpleChatSystemMessage = "Tu es un assistant. Réponds en t'appuyant uniquement sur le CONTEXTE qui est extrait de tutos expliquant certaines procédure comptables dans notre entreprise. Si l'info n’y est pas, dis-le clairement. \nCONTEXTE:\n" + sb;
chatForm.BeforeAsk -= beforeAskEventHandler; // SimpleChatSystemMessage uniquement lors de la première interaction dans le chat
};
chatForm.BeforeAsk += beforeAskEventHandler;
}
}
}