using Services.Fooocus; using Services.Models; using Services.ReActAgent; using System.Text.Json; using ToolsServices; using static Services.ReActAgent.ModelsUseCases; namespace Services { public static class ChatService { #region Variables private static string Folder => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Conversations"); private static Services.ReActAgent.ReActAgent _ReActAagent = new(); #endregion #region Constructeur static ChatService() { LoggerService.LogInfo($"ChatService"); try { if (!Directory.Exists(Folder)) { LoggerService.LogDebug($"ChatService : tentative de création du dossier de conversations : {Folder}"); Directory.CreateDirectory(Folder); LoggerService.LogInfo($"ChatService : dossier de conversations créé : {Folder}"); } } catch (Exception ex) { LoggerService.LogError($"ChatService : Erreur : {ex.Message}"); } } #endregion #region Méthodes publiques public static string GetModeleIA(ModelsUseCases.TypeUseCase useCase) { return ReActAgent.ReActAgent.GetModeleIA(useCase); } public static IEnumerable GetModelesIA(ModelsUseCases.TypeUseCase useCase) { return ReActAgent.ReActAgent.GetModelesIA(useCase); } public static async Task> GetFooocusStylesAsync() { return await _ReActAagent.GetFooocusStylesAsync(); } public static (string, string, string) LoadParametresGenerateImg() { return _ReActAagent.LoadParametresGenerateImg(); } public static bool SaveParametresGenerateImg(string url, string endpointV1, string endpointv2) { return _ReActAagent.SaveParametresGenerateImg(url, endpointV1, endpointv2); } public static FooocusRequest_Text_to_Image LoadParametresFooocus() { return _ReActAagent.LoadParametresFooocus(); } public static bool SaveParametresFooocus(FooocusRequest_Text_to_Image param, List ListeSelectedsStylesFooocus) { return _ReActAagent.SaveParametresFooocus(param, ListeSelectedsStylesFooocus); } public static void SaveConversation(ChatConversation conv) { LoggerService.LogInfo($"ChatService.Save"); Directory.CreateDirectory(Folder); var path = Path.Combine(Folder, conv.Id + ".json"); File.WriteAllText(path, JsonSerializer.Serialize(conv, new JsonSerializerOptions { WriteIndented = true })); } public static void Delete(string conversationId) { LoggerService.LogInfo($"ChatService.Delete"); var path = Path.Combine(Folder, conversationId + ".json"); if (File.Exists(path)) File.Delete(path); } public static List LoadAll(string type) { LoggerService.LogInfo($"ChatService.LoadAll"); return Directory.GetFiles(Folder, "*.json") .Select(file => JsonSerializer.Deserialize(File.ReadAllText(file))) .Where(c => c != null) .Where(c=>c.Type == type) .Cast() .ToList(); } public static async Task<(bool, string, string)> SendMessageAsync(ModelsUseCases.TypeUseCase useCase, List messages, string model, bool isApiExterne=false) { LoggerService.LogInfo($"ChatService.SendMessageAsync"); var (s,m) = await _ReActAagent.AppelerLLMAsync(useCase, model, messages, isApiExterne); return (true, s, m); } public static async Task<(bool, string, string)> SendMessageAsync(string message, string model, bool isWithAssistant, bool isGenerateParametres) { LoggerService.LogInfo($"ChatService.SendMessageAsync"); var (s,m) = await _ReActAagent.GenerateTextToImage(ModelsUseCases.TypeUseCase.PromptGenerationFooocus, message, model, isWithAssistant, isGenerateParametres); return (true, s, m); } public static async Task<(bool, string, string)> SendMessageAsync(string message, string model, bool isWithAssistant, List documentsFullFilename) { LoggerService.LogInfo($"ChatService.SendMessageAsync"); var (s,m) = await _ReActAagent.GenerateTextToImageWithIP(ModelsUseCases.TypeUseCase.PromptGenerationFooocus, message, model, isWithAssistant, documentsFullFilename); return (true, s, m); } public static async Task<(bool, string, string)> SendMessageAsync(ModelsUseCases.TypeUseCase useCase, string prompt, string model, List documentsFullFilename, bool isApiExterne = false) { if (useCase == TypeUseCase.LLM) { var (b1,s11,s12) = await SendMessageLLMAsync(prompt, model, documentsFullFilename, isApiExterne); List messages = new(); prompt = prompt + "\n" + s11; var userMessage = new ChatMessage { Role = "user", Content = prompt, Model = model }; messages.Add(userMessage); var (b2, s21, s22) = await SendMessageAsync(ModelsUseCases.TypeUseCase.LLM, messages, model, isApiExterne); return (b1 && b2, "Résumé\n------: \n" + s11 + "\n------\nFin du résumé\n\n" + s21, "Résumé : " + s12 + "\n" + "Traitement de la demande : " + s22); } else if (useCase == TypeUseCase.LLM_Coder) { return await SendMessageLLMCoderAsync(prompt, model, documentsFullFilename, isApiExterne); } else { return (false, "Erreur : Cas d'usage qui n'est ni LLM, ni LLM Coder", model); } } #endregion #region Méthodes privées private static async Task<(bool, string, string)> SendMessageLLMAsync(string prompt, string model, List documentsFullFilename, bool isApiExterne = false) { (List lstImages, List lstDocuments) = FilesService.GetListesFichiers(documentsFullFilename); // Images mais pas de documents if (lstImages.Count > 0 && lstDocuments.Count == 0) { LoggerService.LogInfo($"ChatService.SendMessageLLMAsync : {lstImages.Count} image(s) mais pas de documents"); var (s, m) = await _ReActAagent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.InterpretationImages, model, prompt, lstImages, isApiExterne); return (true, s, m); } // Documents mais pas d'image else if (lstImages.Count == 0 && lstDocuments.Count > 0) { LoggerService.LogInfo($"ChatService.SendMessageLLMAsync : {lstDocuments.Count} document(s) mais pas d'image"); var (resume, m) = await GetResume(lstDocuments); return (true, resume.ToString(), m); } // Images + documents else { LoggerService.LogInfo($"ChatService.SendMessageLLMAsync : {lstImages.Count} image(s) + {lstDocuments.Count} document(s)"); var resume = await GetResume(lstDocuments); var (reponse, m) = await _ReActAagent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.InterpretationImages, model, prompt, lstImages, isApiExterne); return (true, resume + "\n\n" + reponse, m); } } private static async Task<(bool, string, string)> SendMessageLLMCoderAsync(string prompt, string model, List documentsFullFilename, bool isApiExterne = false) { (List lstImages, List lstDocuments) = FilesService.GetListesFichiers(documentsFullFilename); // Images non prises en compte dans ce contexte if (lstImages.Count > 0 && lstDocuments.Count == 0) { LoggerService.LogDebug($"ChatService.SendMessageLLMCoderAsync : {lstImages.Count} image(s) mais pas de documents : pas pris en compte"); return (false, "Erreur : les images ne sont prises en compte dans ce contexte", model); } // Documents pris en compte else if (lstDocuments.Count > 0) { LoggerService.LogInfo($"ChatService.SendMessageLLMCoderAsync : {lstDocuments.Count} document(s)"); var codeDocs = ""; foreach (var doc in lstDocuments) { var code = $"{Path.GetFileName(doc)} : \n" + TxtService.ExtractTextFromTxt(doc); codeDocs += "\n" + code; } var (rep, m) = await _ReActAagent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.LLM_Coder, true, prompt + "\n\n" + codeDocs, "Analyse de code", model, isApiExterne); return (true, rep, m); } // cas qui ne devrait pas arriver else { LoggerService.LogInfo($"ChatService.SendMessageLLMCoderAsync : {lstImages.Count} image(s) + {lstDocuments.Count} document(s)"); return (true, "Cas qui ne devrait pas arriver", model); } } private static async Task<(string, string)> GetResume(List lstDocuments) { LoggerService.LogInfo($"ChatService.GetResume"); string resumes = ""; string model = ""; foreach (var doc in lstDocuments) { var filename = System.IO.Path.GetFileName(doc); string content = FilesService.ExtractText(doc); //agent.IngestDocument(content, doc); var (resume, m) = await _ReActAagent.SummarizeIntegralLongDocAsync("ChatRoom", content); resumes += "\n\n" + filename + " : \n" + resume; model = m; } return (resumes, model); } public static async Task> GetInstalledModelsAsync() { var models = await _ReActAagent.GetInstalledModelsAsync(true); return models; } #endregion } }