using ChatApi.Models; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Embeddings; using OllamaSharp.Models.Chat; #pragma warning disable SKEXP0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. namespace ChatApi.Services.ResponseService { public class ResponseCompanyService : IResponseService { private readonly ChatHistoryService _chatHistoryService; private readonly Kernel _kernel; private readonly TextFilter _textFilter; private readonly SharepointDomvsService _sharepointDomvsService; private readonly IChatCompletionService _chatCompletionService; public ResponseCompanyService( ChatHistoryService chatHistoryService, Kernel kernel, TextFilter textFilter, SharepointDomvsService sharepointDomvsService, IChatCompletionService chatCompletionService) { this._chatHistoryService = chatHistoryService; this._kernel = kernel; this._textFilter = textFilter; this._sharepointDomvsService = sharepointDomvsService; this._chatCompletionService = chatCompletionService; } public EnumClassification Classification => EnumClassification.Company; public async Task GetResponse(HttpContext context, UserData userData, string sessionId, string question) { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); SessionIdStore sessionIdStore = new SessionIdStore(context); var resposta = await BuscarTextoRelacionado(question); question = "Para responder à pergunta: \"" + question + "\" por favor, gere um resumo com 3 linhas baseado exclusivamente no texto: \"" + resposta + "\""; ChatHistory history = _chatHistoryService.GetSumarizer(sessionId); history.AddUserMessage(question); var response = await _chatCompletionService.GetChatMessageContentAsync(history); history.AddMessage(response.Role, response.Content ?? ""); _chatHistoryService.UpdateHistory(sessionId, history); stopWatch.Stop(); return $"{response.Content ?? ""}\n\nTempo: {stopWatch.ElapsedMilliseconds / 1000}s"; } async Task BuscarTextoRelacionado(string pergunta) { var embeddingService = _kernel.GetRequiredService(); var embeddingPergunta = await embeddingService.GenerateEmbeddingAsync(_textFilter.ToLowerAndWithoutAccents(pergunta)); var embeddingArrayPergunta = embeddingPergunta.ToArray().Select(e => (double)e).ToArray(); var textos = await _sharepointDomvsService.GetAsync(); TextoComEmbedding melhorTexto = null; double melhorSimilaridade = -1.0; foreach (var texto in textos) { double similaridade = CalcularSimilaridadeCoseno(embeddingArrayPergunta, texto.Embedding); if (similaridade > melhorSimilaridade) { melhorSimilaridade = similaridade; melhorTexto = texto; } } // 4. Retornar o conteúdo mais similar, ou uma mensagem padrão return melhorTexto != null ? melhorTexto.Conteudo : "Não encontrei uma resposta adequada."; } double CalcularSimilaridadeCoseno(double[] embedding1, double[] embedding2) { double dotProduct = 0.0; double normA = 0.0; double normB = 0.0; for (int i = 0; i < embedding1.Length; i++) { dotProduct += embedding1[i] * embedding2[i]; normA += Math.Pow(embedding1[i], 2); normB += Math.Pow(embedding2[i], 2); } return dotProduct / (Math.Sqrt(normA) * Math.Sqrt(normB)); } } } #pragma warning restore SKEXP0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.