ChatApi/Services/ResponseService/ResponseCompanyService.cs
2024-11-28 22:49:03 -03:00

100 lines
4.2 KiB
C#

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<string> 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<string> BuscarTextoRelacionado(string pergunta)
{
var embeddingService = _kernel.GetRequiredService<ITextEmbeddingGenerationService>();
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.