138 lines
5.4 KiB
Plaintext
138 lines
5.4 KiB
Plaintext
using Amazon.Auth.AccessControlPolicy;
|
|
using Microsoft.SemanticKernel.ChatCompletion;
|
|
|
|
namespace ChatApi.Services.Bot.Structs
|
|
{
|
|
public class ChatBot
|
|
{
|
|
private readonly List<Question> _questions;
|
|
private readonly ChatPersistence _persistence;
|
|
private readonly Dictionary<string, string> _knowParameters;
|
|
private readonly Dictionary<int, string> _answers;
|
|
private readonly IChatCompletionService _chatCompletionService;
|
|
private readonly IActionCall _actionCall;
|
|
private readonly string _usuarioId;
|
|
private int _indiceAtual;
|
|
|
|
public ChatBot(ChatPersistence persistence, string usuarioId, IChatCompletionService chatCompletionService, IActionCall actionCall)
|
|
{
|
|
_chatCompletionService = chatCompletionService;
|
|
_actionCall = actionCall;
|
|
_questions = new List<Question>();
|
|
_answers = new Dictionary<int, string>();
|
|
_knowParameters = new Dictionary<string, string>();
|
|
_indiceAtual = 0;
|
|
_persistence = persistence;
|
|
_usuarioId = usuarioId;
|
|
|
|
var estado = _persistence.GetState(_usuarioId);
|
|
if (estado != null)
|
|
{
|
|
_indiceAtual = estado.IndicePerguntaAtual;
|
|
_answers = estado.Respostas;
|
|
}
|
|
else
|
|
{
|
|
_indiceAtual = 0;
|
|
}
|
|
}
|
|
|
|
public void SetParameter(string key, string value)
|
|
{
|
|
_knowParameters[key] = value;
|
|
}
|
|
|
|
public void AddQuestion(Question Question)
|
|
{
|
|
_questions.Add(Question);
|
|
}
|
|
|
|
public string SetAnswer(string resposta)
|
|
{
|
|
if (!this.HasNextQuestion()) return "";
|
|
|
|
var state = _persistence.GetState(_usuarioId);
|
|
if (state != null)
|
|
{
|
|
_questions[_indiceAtual].CountTry = state.TentativasPerguntaAtual;
|
|
}
|
|
|
|
var perguntaAtual = _questions[_indiceAtual];
|
|
var testByChat = TestAnswerByChat(resposta);
|
|
var abort = TestIfWantToAbort(resposta);
|
|
var validResp = perguntaAtual.TryToAnswer(resposta);
|
|
|
|
if (string.IsNullOrEmpty(validResp) && !abort.Contains("ABORTAR") && perguntaAtual.Validator(resposta) && testByChat.Contains("SIM"))
|
|
{
|
|
_answers[_indiceAtual] = resposta;
|
|
_indiceAtual++;
|
|
_persistence.SaveState(new ChatState
|
|
{
|
|
Id = _usuarioId,
|
|
UsuarioId = _usuarioId,
|
|
IndicePerguntaAtual = _indiceAtual,
|
|
TentativasPerguntaAtual = _questions[_indiceAtual].CountTry,
|
|
Respostas = new Dictionary<int, string>(_answers)
|
|
});
|
|
|
|
return "";
|
|
}
|
|
else if (validResp.Contains("reiniciar") || abort.Contains("ABORTAR"))
|
|
{
|
|
_persistence.DeleteState(_usuarioId);
|
|
return "REINICIAR";
|
|
}
|
|
|
|
_persistence.SaveState(new ChatState
|
|
{
|
|
Id = _usuarioId,
|
|
UsuarioId = _usuarioId,
|
|
IndicePerguntaAtual = _indiceAtual,
|
|
TentativasPerguntaAtual = _questions[_indiceAtual].CountTry,
|
|
Respostas = new Dictionary<int, string>(_answers)
|
|
});
|
|
|
|
return $"Resposta inválida. Tente novamente. {(testByChat.Contains("NÃO") ? "Motivo: " + testByChat.Replace("NÂO", "") : "")} \n\n {perguntaAtual.Text}";
|
|
}
|
|
|
|
public string GetCurrentQuestion() => _questions[_indiceAtual].Text;
|
|
public async Task<string> GetNextQuestion()
|
|
{
|
|
while (_indiceAtual < _questions.Count)
|
|
{
|
|
var perguntaAtual = _questions[_indiceAtual];
|
|
if (perguntaAtual.MustShow(_answers))
|
|
{
|
|
return perguntaAtual.Text;
|
|
}
|
|
_indiceAtual++;
|
|
}
|
|
|
|
var resp = await _actionCall.Populate(_knowParameters, _answers);
|
|
if (!resp.Success) return "Obrigado por responder a nossas perguntas!";
|
|
|
|
var result = await _actionCall.Call();
|
|
|
|
return result.Success ? result.Value : "Obrigado por responder a nossas perguntas!";
|
|
}
|
|
|
|
public string TestAnswerByChat(string resposta)
|
|
{
|
|
var resp = _chatCompletionService.GetChatMessageContentAsync($"Por favor, responda com SIM/NÂO e o motivo para eu saber se a pergunta: ({this.GetCurrentQuestion()}) foi respondida pelo usuário quando ele digitou: ({resposta})? É um chatbot, por isso preciso saber apenas se a resposta faz sentido e/ou tem o formato certo.").Result;
|
|
return resp.Content;
|
|
}
|
|
|
|
public string TestIfWantToAbort(string resposta)
|
|
{
|
|
if (_indiceAtual==0) return "";
|
|
var resp = _chatCompletionService.GetChatMessageContentAsync($"Este é um chatbot. Foi feita a pergunta para o usuario: ({this.GetCurrentQuestion()}) e ele digitou: ({resposta})? Ele respondeu a pergunta com a informação solicitada, ou ele está pedindo para sair do chat? Responda com (SIM = Ele quer sair ou não quer responder) ou (NÃO = Ele responde a pergunta de maneira coerente) e indique o motivo.").Result;
|
|
return resp.Content.Contains("SIM") ? "ABORTAR" : "";
|
|
}
|
|
|
|
public bool HasNextQuestion()
|
|
{
|
|
return _indiceAtual < _questions.Count;
|
|
}
|
|
}
|
|
}
|