Compare commits
2 Commits
bb3315625d
...
bd0f910f1b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd0f910f1b | ||
|
|
0efb2ac75d |
@ -2,6 +2,8 @@
|
|||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ActiveDebugProfile>http</ActiveDebugProfile>
|
<ActiveDebugProfile>http</ActiveDebugProfile>
|
||||||
|
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||||
|
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||||
|
|||||||
@ -50,7 +50,7 @@ namespace ChatApi
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var msg = new List<ChatMessageContent>();
|
var msg = new List<ChatMessageContent>();
|
||||||
PromptIan(msg);
|
PromptLiliana(msg);
|
||||||
string json = JsonSerializer.Serialize(msg);
|
string json = JsonSerializer.Serialize(msg);
|
||||||
var history = new ChatHistory(JsonSerializer.Deserialize<List<ChatMessageContent>>(json));
|
var history = new ChatHistory(JsonSerializer.Deserialize<List<ChatMessageContent>>(json));
|
||||||
_keyValues[sessionId] = history;
|
_keyValues[sessionId] = history;
|
||||||
@ -72,10 +72,12 @@ namespace ChatApi
|
|||||||
msg.Add(new ChatMessageContent(AuthorRole.User, "Responda sempre em portugues do Brasil as minhas perguntas."));
|
msg.Add(new ChatMessageContent(AuthorRole.User, "Responda sempre em portugues do Brasil as minhas perguntas."));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PromptIan(List<ChatMessageContent> msg)
|
public void PromptLiliana(List<ChatMessageContent> msg)
|
||||||
{
|
{
|
||||||
msg.Add(new ChatMessageContent(AuthorRole.System, "Seu nome é Ian, um assistente ajuda empresas de Consultoria e RH. "));
|
msg.Add(new ChatMessageContent(AuthorRole.System, "Seu nome é LiliAna, um assistente virtual da Domvs It (Consultoria e RH)."));
|
||||||
msg.Add(new ChatMessageContent(AuthorRole.System, "Você responde sempre em português do Brasil."));
|
msg.Add(new ChatMessageContent(AuthorRole.System, "Você responde sempre em português do Brasil e fala sobre serviços prestados pela Domvs iT."));
|
||||||
|
msg.Add(new ChatMessageContent(AuthorRole.System, "Você consegue fazer solicitações no portal do RH da Domvs iT."));
|
||||||
|
msg.Add(new ChatMessageContent(AuthorRole.System, "Você responde perguntas voltadas ao mercado de trabalho de tecnologia."));
|
||||||
msg.Add(new ChatMessageContent(AuthorRole.System, "Em breve, você será capaz de consultar o linkedin."));
|
msg.Add(new ChatMessageContent(AuthorRole.System, "Em breve, você será capaz de consultar o linkedin."));
|
||||||
msg.Add(new ChatMessageContent(AuthorRole.User, "Use sempre portugues do Brasil."));
|
msg.Add(new ChatMessageContent(AuthorRole.User, "Use sempre portugues do Brasil."));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,80 +15,62 @@ using ChatApi.Services.Classifier;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using ChatApi.Models;
|
using ChatApi.Models;
|
||||||
|
using ChatApi.Data;
|
||||||
|
|
||||||
#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.
|
#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.Controllers
|
namespace ChatApi.Controllers
|
||||||
{
|
{
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("[controller]")]
|
[Route("[controller]")]
|
||||||
|
[Authorize]
|
||||||
public class ChatController : ControllerBase
|
public class ChatController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger<ChatController> _logger;
|
private readonly ILogger<ChatController> _logger;
|
||||||
private readonly TextFilter _textFilter;
|
private readonly TextFilter _textFilter;
|
||||||
private readonly ResponseFactory _responseFactory;
|
private readonly ResponseFactory _responseFactory;
|
||||||
private readonly ClassifierPersistence _classifierPersistence;
|
private readonly ClassifierPersistence _classifierPersistence;
|
||||||
|
private readonly UserDataRepository _userDataRepository;
|
||||||
|
private readonly TextData _textData;
|
||||||
|
|
||||||
public ChatController(
|
public ChatController(
|
||||||
ILogger<ChatController> logger,
|
ILogger<ChatController> logger,
|
||||||
TextFilter textFilter,
|
TextFilter textFilter,
|
||||||
ResponseFactory responseFactory,
|
ResponseFactory responseFactory,
|
||||||
ClassifierPersistence classifierPersistence)
|
ClassifierPersistence classifierPersistence,
|
||||||
|
UserDataRepository userDataRepository,
|
||||||
|
TextData textData)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_textFilter = textFilter;
|
_textFilter = textFilter;
|
||||||
_responseFactory = responseFactory;
|
_responseFactory = responseFactory;
|
||||||
_classifierPersistence = classifierPersistence;
|
_classifierPersistence = classifierPersistence;
|
||||||
|
_userDataRepository = userDataRepository;
|
||||||
|
_textData = textData;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet(Name = "Response")]
|
[HttpGet]
|
||||||
public async Task<string?> Get([FromQuery] ChatRequest chatRequest)
|
[Route("response")]
|
||||||
|
public async Task<string?> GetResponse([FromQuery] ChatRequest chatRequest)
|
||||||
{
|
{
|
||||||
var userData = UserData.Create(User);
|
//var userData = UserData.Create(User);
|
||||||
var textClassifier = new TextClassifier(_textFilter, _classifierPersistence);
|
var textClassifier = new TextClassifier(_textFilter, _classifierPersistence);
|
||||||
var textType = await textClassifier.ClassifyQuestion(chatRequest.SessionId, chatRequest.Message);
|
var textType = await textClassifier.ClassifyQuestion(chatRequest.SessionId, chatRequest.Message);
|
||||||
|
var needsRestart = textClassifier.NeedsRestart();
|
||||||
var responseText = _responseFactory.GetService(textType);
|
var responseText = _responseFactory.GetService(textType);
|
||||||
var response = await responseText.GetResponse(HttpContext, userData, chatRequest.SessionId, chatRequest.Message);
|
var userData = await _userDataRepository.GeByToekntAsync(AppDomain.CurrentDomain.GetData("Token") as string);
|
||||||
|
var response = await responseText.GetResponse(HttpContext, userData, chatRequest.SessionId, chatRequest.Message, needsRestart);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost(Name = "LoadDBData")]
|
[HttpPost]
|
||||||
public async Task SaveData([FromQuery] DBLoadRequest loadRequest)
|
[Route("loaddata")]
|
||||||
|
//public async Task SaveData([FromQuery] DBLoadRequest loadRequest)
|
||||||
|
public async Task SaveData()
|
||||||
{
|
{
|
||||||
//string readText = System.IO.File.ReadAllText("C:\\vscode\\ChatApi\\bin\\Debug\\net8.0\\Servicos.txt");
|
string readText = System.IO.File.ReadAllText("C:\\vscode\\ChatApi\\bin\\Debug\\net8.0\\Servicos.txt");
|
||||||
string readText = loadRequest.Content;
|
//string readText = loadRequest.Content;
|
||||||
await SalvarTextoComEmbeddingNoMongoDB(readText);
|
await _textData.SalvarTextoComEmbeddingNoMongoDB(readText);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async Task SalvarTextoComEmbeddingNoMongoDB(string textoCompleto)
|
|
||||||
{
|
|
||||||
var textoArray = new List<string>();
|
|
||||||
string[] textolinhas = textoCompleto.Split(
|
|
||||||
new string[] { "\n" },
|
|
||||||
StringSplitOptions.None
|
|
||||||
);
|
|
||||||
|
|
||||||
var title = textolinhas[0];
|
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
foreach (string line in textolinhas)
|
|
||||||
{
|
|
||||||
if (line.StartsWith("**") || line.StartsWith("\r**"))
|
|
||||||
{
|
|
||||||
if (builder.Length > 0)
|
|
||||||
{
|
|
||||||
textoArray.Add(title.Replace("**", "").Replace("\r", "") + ": " + Environment.NewLine + builder.ToString());
|
|
||||||
builder = new StringBuilder();
|
|
||||||
title = line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builder.AppendLine(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,68 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.SemanticKernel;
|
|
||||||
using Microsoft.SemanticKernel.ChatCompletion;
|
|
||||||
using Microsoft.SemanticKernel.Embeddings;
|
|
||||||
using Microsoft.SemanticKernel.Memory;
|
|
||||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
|
||||||
|
|
||||||
#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.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class ChatController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ILogger<ChatController> _logger;
|
|
||||||
private readonly ChatHistoryService _chatHistoryService;
|
|
||||||
private readonly IChatCompletionService _chatCompletionService;
|
|
||||||
private readonly Kernel _kernel;
|
|
||||||
|
|
||||||
public ChatController(ILogger<ChatController> logger, ChatHistoryService chatHistoryService, IChatCompletionService chatCompletionService, Kernel kernel)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
_chatHistoryService = chatHistoryService;
|
|
||||||
_chatCompletionService = chatCompletionService;
|
|
||||||
_kernel = kernel;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet(Name = "Response")]
|
|
||||||
public async Task<string> Get([FromQuery] ChatRequest chatRequest)
|
|
||||||
{
|
|
||||||
var stopWatch = new System.Diagnostics.Stopwatch();
|
|
||||||
|
|
||||||
stopWatch.Start();
|
|
||||||
SessionIdStore sessionIdStore = new SessionIdStore(HttpContext);
|
|
||||||
var sessionId = sessionIdStore.GetSessionId();
|
|
||||||
var history = _chatHistoryService.Get(sessionId);
|
|
||||||
|
|
||||||
history.AddUserMessage(chatRequest.Message);
|
|
||||||
|
|
||||||
var embeddingGenerator = _kernel.GetRequiredService<ITextEmbeddingGenerationService>();
|
|
||||||
// Setup a memory store and create a memory out of it
|
|
||||||
#pragma warning disable SKEXP0020 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
|
||||||
var memoryStore = new InMemoryVectorStore();
|
|
||||||
#pragma warning restore SKEXP0020 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
|
||||||
var memory = new SemanticTextMemory(memoryStore, embeddingGenerator);
|
|
||||||
// Loading it for Save, Recall and other methods
|
|
||||||
_kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
|
|
||||||
string MemoryCollectionName = "MyCustomDataCollection";
|
|
||||||
|
|
||||||
var option = new PromptExecutionSettings
|
|
||||||
{
|
|
||||||
|
|
||||||
Memory = memory,
|
|
||||||
MemoryCollectionName = MemoryCollectionName
|
|
||||||
};
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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.
|
|
||||||
121
Controllers/LoginController.cs
Normal file
121
Controllers/LoginController.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
using ChatApi.Models;
|
||||||
|
using ChatApi.Services.Crypt;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace ChatApi.Controllers
|
||||||
|
{
|
||||||
|
[Route("[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class LoginController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IConfigurationManager _configuration;
|
||||||
|
private readonly UserDataRepository _userDataRepository;
|
||||||
|
private readonly CryptUtil _cryptUtil;
|
||||||
|
|
||||||
|
public LoginController(IConfigurationManager configuration, UserDataRepository userDataRepository, CryptUtil cryptUtil)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_userDataRepository = userDataRepository;
|
||||||
|
_cryptUtil = cryptUtil;
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("token")]
|
||||||
|
public async Task<IActionResult> Post([FromBody] LoginRequest loginRequest)
|
||||||
|
{
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userDataFrom = await _userDataRepository.GetAsync(loginRequest.ClientName, loginRequest.ClientId, loginRequest.ClientSecret);
|
||||||
|
if (userDataFrom==null)
|
||||||
|
{
|
||||||
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = "";
|
||||||
|
if (userDataFrom.LastToken == null && (userDataFrom.DateTimeToken != null && userDataFrom.DateTimeToken.Value.AddHours(24) > DateTime.Now))
|
||||||
|
{
|
||||||
|
token = userDataFrom.LastToken;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var claims = new[]
|
||||||
|
{
|
||||||
|
new Claim("Sub", userDataFrom.CompanyTenant),
|
||||||
|
new Claim("NameId", userDataFrom.Name),
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, loginRequest.ClientId),
|
||||||
|
new Claim("DhCriado", DateTime.Now.ToString(new CultureInfo("pt-BR"))),
|
||||||
|
new Claim("TenantId", userDataFrom.CompanyTenant),
|
||||||
|
new Claim(ClaimTypes.Role, "TeamsUser")
|
||||||
|
};
|
||||||
|
|
||||||
|
var expires = DateTime.UtcNow.AddMinutes(30);
|
||||||
|
var tokenGen = new JwtSecurityToken
|
||||||
|
(
|
||||||
|
issuer: _configuration["Issuer"],
|
||||||
|
audience: _configuration["Audience"],
|
||||||
|
claims: claims,
|
||||||
|
expires: expires,
|
||||||
|
notBefore: DateTime.UtcNow,
|
||||||
|
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SigningKey"])),
|
||||||
|
SecurityAlgorithms.HmacSha256)
|
||||||
|
);
|
||||||
|
|
||||||
|
token = new JwtSecurityTokenHandler().WriteToken(tokenGen);
|
||||||
|
}
|
||||||
|
userDataFrom.LastToken = token;
|
||||||
|
userDataFrom.DateTimeToken = DateTime.Now;
|
||||||
|
await _userDataRepository.UpdateAsync(userDataFrom.Id, userDataFrom);
|
||||||
|
|
||||||
|
return Ok(new { token = token });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("newclient")]
|
||||||
|
public async Task<IActionResult> NewClient([FromBody] UserRequest userDataFrom)
|
||||||
|
{
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userData = await _userDataRepository.GetAsync(userDataFrom.Name, userDataFrom.LocalId);
|
||||||
|
if (userData == null)
|
||||||
|
{
|
||||||
|
var secret = _cryptUtil.Encrypt(JsonSerializer.Serialize(userDataFrom));
|
||||||
|
userData = UserData.Create(userDataFrom, secret);
|
||||||
|
await _userDataRepository.CreateAsync(userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Created("newclient", userData);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Controllers/LoginRequest.cs
Normal file
9
Controllers/LoginRequest.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace ChatApi.Controllers
|
||||||
|
{
|
||||||
|
public class LoginRequest
|
||||||
|
{
|
||||||
|
public string ClientId { get; set; }
|
||||||
|
public string ClientName { get; set; }
|
||||||
|
public string ClientSecret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Controllers/UserRequest.cs
Normal file
16
Controllers/UserRequest.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace ChatApi.Controllers
|
||||||
|
{
|
||||||
|
public class UserRequest
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string CompanyTenant { get; set; }
|
||||||
|
public string LocalId { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string? Secret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
73
Data/TextData.cs
Normal file
73
Data/TextData.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using Microsoft.SemanticKernel;
|
||||||
|
using Microsoft.SemanticKernel.Embeddings;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#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.Data
|
||||||
|
{
|
||||||
|
public class TextData
|
||||||
|
{
|
||||||
|
private readonly ITextEmbeddingGenerationService _textEmbeddingGenerationService;
|
||||||
|
private readonly SharepointDomvsService _sharepointDomvsService;
|
||||||
|
|
||||||
|
public TextData(ITextEmbeddingGenerationService textEmbeddingGenerationService, SharepointDomvsService sharepointDomvsService)
|
||||||
|
{
|
||||||
|
_textEmbeddingGenerationService = textEmbeddingGenerationService;
|
||||||
|
_sharepointDomvsService = sharepointDomvsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SalvarTextoComEmbeddingNoMongoDB(string textoCompleto)
|
||||||
|
{
|
||||||
|
var textoArray = new List<string>();
|
||||||
|
string[] textolinhas = textoCompleto.Split(
|
||||||
|
new string[] { "\n" },
|
||||||
|
StringSplitOptions.None
|
||||||
|
);
|
||||||
|
|
||||||
|
var title = textolinhas[0];
|
||||||
|
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
foreach (string line in textolinhas)
|
||||||
|
{
|
||||||
|
if (line.StartsWith("**") || line.StartsWith("\r**"))
|
||||||
|
{
|
||||||
|
if (builder.Length > 0)
|
||||||
|
{
|
||||||
|
textoArray.Add(title.Replace("**", "").Replace("\r", "") + ": " + Environment.NewLine + builder.ToString());
|
||||||
|
builder = new StringBuilder();
|
||||||
|
title = line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.AppendLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var item in textoArray)
|
||||||
|
{
|
||||||
|
await SalvarNoMongoDB(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SalvarNoMongoDB(string texto)
|
||||||
|
{
|
||||||
|
// Gerar embedding para o texto
|
||||||
|
var embedding = await _textEmbeddingGenerationService.GenerateEmbeddingAsync(texto);
|
||||||
|
|
||||||
|
// Converter embedding para um formato serializável (como um array de floats)
|
||||||
|
var embeddingArray = embedding.ToArray().Select(e => (double)e).ToArray();
|
||||||
|
|
||||||
|
// Criar documento MongoDB com conteúdo e embedding
|
||||||
|
var documento = new TextoComEmbedding
|
||||||
|
{
|
||||||
|
Conteudo = texto,
|
||||||
|
Embedding = embeddingArray
|
||||||
|
};
|
||||||
|
|
||||||
|
await _sharepointDomvsService.CreateAsync(documento);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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.
|
||||||
45
Data/UserDataRepository.cs
Normal file
45
Data/UserDataRepository.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using ChatApi.Models;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace ChatApi
|
||||||
|
{
|
||||||
|
public class UserDataRepository
|
||||||
|
{
|
||||||
|
private readonly IMongoCollection<UserData> _userCollection;
|
||||||
|
|
||||||
|
public UserDataRepository(
|
||||||
|
IOptions<DomvsDatabaseSettings> bookStoreDatabaseSettings)
|
||||||
|
{
|
||||||
|
var mongoClient = new MongoClient(
|
||||||
|
bookStoreDatabaseSettings.Value.ConnectionString);
|
||||||
|
|
||||||
|
var mongoDatabase = mongoClient.GetDatabase(
|
||||||
|
bookStoreDatabaseSettings.Value.DatabaseName);
|
||||||
|
|
||||||
|
_userCollection = mongoDatabase.GetCollection<UserData>(
|
||||||
|
bookStoreDatabaseSettings.Value.UserDataName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<UserData>> GetAsync() =>
|
||||||
|
await _userCollection.Find(_ => true).ToListAsync();
|
||||||
|
|
||||||
|
public async Task<UserData?> GeByToekntAsync(string token) =>
|
||||||
|
await _userCollection.Find(x => x.LastToken == token).FirstOrDefaultAsync();
|
||||||
|
public async Task<UserData?> GetAsync(string id) =>
|
||||||
|
await _userCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
|
||||||
|
public async Task<UserData?> GetAsync(string name, string localId) =>
|
||||||
|
await _userCollection.Find(x => x.Name == name && x.LocalId == localId).FirstOrDefaultAsync();
|
||||||
|
public async Task<UserData?> GetAsync(string name, string localId, string secret) =>
|
||||||
|
await _userCollection.Find(x => x.Name == name && x.LocalId == localId && x.Secret == secret).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
public async Task CreateAsync(UserData newBook) =>
|
||||||
|
await _userCollection.InsertOneAsync(newBook);
|
||||||
|
|
||||||
|
public async Task UpdateAsync(string id, UserData updatedBook) =>
|
||||||
|
await _userCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);
|
||||||
|
|
||||||
|
public async Task RemoveAsync(string id) =>
|
||||||
|
await _userCollection.DeleteOneAsync(x => x.Id == id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
public string SharepointCollectionName { get; set; } = null!;
|
public string SharepointCollectionName { get; set; } = null!;
|
||||||
|
|
||||||
|
public string UserDataName { get; set; } = null!;
|
||||||
|
|
||||||
public string ChatBotRHCollectionName { get; set; } = null!;
|
public string ChatBotRHCollectionName { get; set; } = null!;
|
||||||
|
|
||||||
public string ClassifierCollectionName { get; set; } = null!;
|
public string ClassifierCollectionName { get; set; } = null!;
|
||||||
|
|||||||
@ -1,29 +1,37 @@
|
|||||||
using System.Security.Claims;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using ChatApi.Controllers;
|
||||||
|
|
||||||
namespace ChatApi.Models
|
namespace ChatApi.Models
|
||||||
{
|
{
|
||||||
public class UserData
|
public class UserData
|
||||||
{
|
{
|
||||||
private UserData()
|
public UserData()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Email { get; set; }
|
[BsonId]
|
||||||
|
[BsonElement("_id")]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string LocalId { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
public string Secret { get; set; }
|
||||||
|
public string CompanyTenant { get; set; }
|
||||||
|
public string? Email { get; set; }
|
||||||
|
public string? LastToken { get; set; }
|
||||||
|
public DateTime? DateTimeToken { get; set; }
|
||||||
|
|
||||||
public static UserData Create(ClaimsPrincipal user)
|
public static UserData Create(UserRequest userRequest, string secret)
|
||||||
{
|
{
|
||||||
var email = user.FindFirst(ClaimTypes.Email)?.Value
|
|
||||||
?? user.FindFirst("email")?.Value;
|
|
||||||
|
|
||||||
var name = user.FindFirst(ClaimTypes.Name)?.Value
|
|
||||||
?? user.FindFirst("name")?.Value;
|
|
||||||
|
|
||||||
|
|
||||||
return new UserData
|
return new UserData
|
||||||
{
|
{
|
||||||
Email = email,
|
Id = Guid.NewGuid().ToString("N"),
|
||||||
Name = name
|
Name = userRequest.Name,
|
||||||
|
CompanyTenant = userRequest.CompanyTenant,
|
||||||
|
LocalId = userRequest.LocalId,
|
||||||
|
Secret = secret
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
78
Program.cs
78
Program.cs
@ -1,15 +1,25 @@
|
|||||||
using ChatApi;
|
using ChatApi;
|
||||||
|
using ChatApi.Data;
|
||||||
using ChatApi.Services;
|
using ChatApi.Services;
|
||||||
using ChatApi.Services.Bot;
|
using ChatApi.Services.Bot;
|
||||||
using ChatApi.Services.Bot.Structs;
|
using ChatApi.Services.Bot.Structs;
|
||||||
using ChatApi.Services.Classifier;
|
using ChatApi.Services.Classifier;
|
||||||
|
using ChatApi.Services.Crypt;
|
||||||
using ChatApi.Services.ResponseService;
|
using ChatApi.Services.ResponseService;
|
||||||
using ChatApi.Settings;
|
using ChatApi.Settings;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.IdentityModel.JsonWebTokens;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.SemanticKernel;
|
using Microsoft.SemanticKernel;
|
||||||
using Microsoft.SemanticKernel.ChatCompletion;
|
using Microsoft.SemanticKernel.ChatCompletion;
|
||||||
using OllamaSharp;
|
using OllamaSharp;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
using System.Text;
|
||||||
|
using static OllamaSharp.OllamaApiClient;
|
||||||
|
using static System.Net.Mime.MediaTypeNames;
|
||||||
|
|
||||||
#pragma warning disable SKEXP0010 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
#pragma warning disable SKEXP0010 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||||
|
|
||||||
@ -20,7 +30,34 @@ var builder = WebApplication.CreateBuilder(args);
|
|||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1", new OpenApiInfo { Title = "apichat", Version = "v1" });
|
||||||
|
|
||||||
|
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
|
||||||
|
{
|
||||||
|
Name = "Authorization",
|
||||||
|
Type = SecuritySchemeType.ApiKey,
|
||||||
|
Scheme = "Bearer",
|
||||||
|
BearerFormat = "JWT",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer'[space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
|
||||||
|
});
|
||||||
|
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new string[] {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.Configure<DomvsDatabaseSettings>(
|
builder.Services.Configure<DomvsDatabaseSettings>(
|
||||||
builder.Configuration.GetSection("DomvsDatabase"));
|
builder.Configuration.GetSection("DomvsDatabase"));
|
||||||
@ -38,6 +75,9 @@ builder.Services.AddScoped<ChatBotRHCall>();
|
|||||||
builder.Services.AddScoped<IResponseService, ResponseChatService>();
|
builder.Services.AddScoped<IResponseService, ResponseChatService>();
|
||||||
builder.Services.AddScoped<IResponseService, ResponseCompanyService>();
|
builder.Services.AddScoped<IResponseService, ResponseCompanyService>();
|
||||||
builder.Services.AddScoped<IResponseService, ResponseBotRHService>();
|
builder.Services.AddScoped<IResponseService, ResponseBotRHService>();
|
||||||
|
builder.Services.AddTransient<UserDataRepository>();
|
||||||
|
builder.Services.AddTransient<TextData>();
|
||||||
|
builder.Services.AddSingleton<CryptUtil>();
|
||||||
|
|
||||||
|
|
||||||
//builder.Services.AddOllamaChatCompletion("phi3.5", new Uri("http://localhost:11435"));
|
//builder.Services.AddOllamaChatCompletion("phi3.5", new Uri("http://localhost:11435"));
|
||||||
@ -63,6 +103,7 @@ builder.Services.AddOllamaTextEmbeddingGeneration("all-minilm", new Uri("http://
|
|||||||
//);
|
//);
|
||||||
|
|
||||||
builder.Services.AddKernel();
|
builder.Services.AddKernel();
|
||||||
|
|
||||||
//builder.Services.AddKernel()
|
//builder.Services.AddKernel()
|
||||||
// .AddOllamaChatCompletion("phi3", new Uri("http://localhost:11435"))
|
// .AddOllamaChatCompletion("phi3", new Uri("http://localhost:11435"))
|
||||||
// .AddOllamaTextEmbeddingGeneration()
|
// .AddOllamaTextEmbeddingGeneration()
|
||||||
@ -74,22 +115,34 @@ builder.Services.AddHttpClient();
|
|||||||
|
|
||||||
var tenantId = builder.Configuration.GetSection("AppTenantId");
|
var tenantId = builder.Configuration.GetSection("AppTenantId");
|
||||||
var clientId = builder.Configuration.GetSection("AppClientID");
|
var clientId = builder.Configuration.GetSection("AppClientID");
|
||||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
||||||
.AddJwtBearer(options =>
|
|
||||||
{
|
|
||||||
options.Authority = $"https://login.microsoftonline.com/{tenantId}/v2.0";
|
|
||||||
options.Audience = "api://" + clientId; // Client ID da sua API
|
|
||||||
|
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(jwtBearerOptions =>
|
||||||
|
{
|
||||||
|
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
|
||||||
{
|
{
|
||||||
ValidateIssuer = true,
|
ValidateActor = true,
|
||||||
ValidateAudience = true,
|
ValidateAudience = true,
|
||||||
ValidateLifetime = true,
|
ValidateLifetime = true,
|
||||||
ValidateIssuerSigningKey = true,
|
ValidateIssuerSigningKey = true,
|
||||||
ValidIssuer = $"https://login.microsoftonline.com/{tenantId}/v2.0",
|
ValidIssuer = builder.Configuration["Issuer"],
|
||||||
ValidAudience = "api://" + clientId
|
ValidAudience = builder.Configuration["Audience"],
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["SigningKey"]))
|
||||||
};
|
};
|
||||||
});
|
jwtBearerOptions.Events = new JwtBearerEvents()
|
||||||
|
{
|
||||||
|
OnTokenValidated = async context =>
|
||||||
|
{
|
||||||
|
var token = context.SecurityToken as JsonWebToken;
|
||||||
|
context.HttpContext.Items["Token"] = token.EncodedToken;
|
||||||
|
AppDomain.CurrentDomain.SetData("Token", token.EncodedToken);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
//builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
// .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
@ -119,6 +172,7 @@ builder.Services.AddControllers();
|
|||||||
// };
|
// };
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IConfigurationManager>(builder.Configuration);
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
@ -131,8 +185,6 @@ if (app.Environment.IsDevelopment())
|
|||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
app.Use(async (context, next) =>
|
app.Use(async (context, next) =>
|
||||||
|
|||||||
@ -20,6 +20,7 @@ namespace ChatApi.Services.Bot
|
|||||||
public Task<Result<string>> Call()
|
public Task<Result<string>> Call()
|
||||||
{
|
{
|
||||||
var httpClient =_httpClientFactory.CreateClient();
|
var httpClient =_httpClientFactory.CreateClient();
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(120);
|
||||||
var url = new Uri(new Uri(_configuration.Url), _configuration.Create);
|
var url = new Uri(new Uri(_configuration.Url), _configuration.Create);
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
||||||
request.Content = new StringContent(System.Text.Json.JsonSerializer.Serialize(_callRH), Encoding.UTF8, "application/json");
|
request.Content = new StringContent(System.Text.Json.JsonSerializer.Serialize(_callRH), Encoding.UTF8, "application/json");
|
||||||
@ -35,6 +36,7 @@ namespace ChatApi.Services.Bot
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
errorContent = response.Content.ReadAsStringAsync().Result;
|
errorContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
if (errorContent.ToLower().Contains("timeout")) errorContent = "O servidor do pipefy demorou um pouco para responder. Verifique se a solicitação foi aberta em seu email!";
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -51,10 +53,10 @@ namespace ChatApi.Services.Bot
|
|||||||
_callRH = new
|
_callRH = new
|
||||||
{
|
{
|
||||||
Nome = knowParameters["Nome"],
|
Nome = knowParameters["Nome"],
|
||||||
Email = knowParameters["Email"],
|
Email = answers[2],
|
||||||
WhatsApp = answers[0],
|
WhatsApp = answers[1],
|
||||||
TipoSolicitacao = answers[1],
|
TipoSolicitacao = answers[3],
|
||||||
Descricao = answers[2],
|
Descricao = answers[4],
|
||||||
};
|
};
|
||||||
|
|
||||||
return Task.FromResult(Result.Ok());
|
return Task.FromResult(Result.Ok());
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using ChatApi.Models;
|
using ChatApi.Models;
|
||||||
using ChatApi.Services.Bot.Structs;
|
using ChatApi.Services.Bot.Structs;
|
||||||
|
using ChatApi.Services.Emails;
|
||||||
using ChatApi.Settings;
|
using ChatApi.Settings;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.SemanticKernel.ChatCompletion;
|
using Microsoft.SemanticKernel.ChatCompletion;
|
||||||
@ -51,7 +52,7 @@ namespace ChatApi.Services.Bot
|
|||||||
_chatRHApiConfig = chatRHApiConfig;
|
_chatRHApiConfig = chatRHApiConfig;
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
public string SetAnswer(string sessionId, string resposta)
|
public string SetAnswer(string sessionId, string resposta, bool needsRestart = false)
|
||||||
{
|
{
|
||||||
if (_chatbot==null)
|
if (_chatbot==null)
|
||||||
{
|
{
|
||||||
@ -61,7 +62,7 @@ namespace ChatApi.Services.Bot
|
|||||||
return _chatbot.SetAnswer(resposta);
|
return _chatbot.SetAnswer(resposta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetNextQuestion()
|
public async Task<string?> GetNextQuestion()
|
||||||
{
|
{
|
||||||
return await _chatbot.GetNextQuestion();
|
return await _chatbot.GetNextQuestion();
|
||||||
}
|
}
|
||||||
@ -76,6 +77,11 @@ namespace ChatApi.Services.Bot
|
|||||||
return _chatbot.HasNextQuestion();
|
return _chatbot.HasNextQuestion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<string?> CallFinalAction()
|
||||||
|
{
|
||||||
|
return await _chatbot.CallFinalAction();
|
||||||
|
}
|
||||||
|
|
||||||
public void Init(string sessionId)
|
public void Init(string sessionId)
|
||||||
{
|
{
|
||||||
var persist = ChatPersistence.Create(_config.Value).SetBotName("RHCall");
|
var persist = ChatPersistence.Create(_config.Value).SetBotName("RHCall");
|
||||||
@ -92,20 +98,27 @@ namespace ChatApi.Services.Bot
|
|||||||
"Qual seu número de celular (com WhatsApp)?",
|
"Qual seu número de celular (com WhatsApp)?",
|
||||||
resposta => !string.IsNullOrEmpty(resposta) && resposta.Length >= 10));
|
resposta => !string.IsNullOrEmpty(resposta) && resposta.Length >= 10));
|
||||||
|
|
||||||
|
_chatbot.AddQuestion(new Question(
|
||||||
|
"Qual seu e-mail?",
|
||||||
|
resposta => EmailValidate.IsValidEmail(resposta)));
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
_opcoesSolicitação.Select(s => s.Value).ToList().ForEach(s => builder.AppendLine(s));
|
_opcoesSolicitação.Select(s => s.Value).ToList().ForEach(s => builder.AppendLine(s));
|
||||||
|
var validNumbers = _opcoesSolicitação.Select(s => s.Value.Substring(0, s.Value.IndexOf("-")-1)).ToList();
|
||||||
|
|
||||||
_chatbot.AddQuestion(new Question(
|
_chatbot.AddQuestion(new Question(
|
||||||
$"Indique o tipo de solicitação: \n {builder}",
|
$"Indique o tipo de solicitação: \n {builder}",
|
||||||
resposta => resposta == "1" || resposta == "2" || resposta == "3"));
|
resposta => validNumbers.IndexOf(resposta) != -1,
|
||||||
|
null,
|
||||||
|
text => _opcoesSolicitação.FirstOrDefault(s => s.Value.Substring(0, s.Value.IndexOf("-")-1) == text).Key));
|
||||||
|
|
||||||
_chatbot.AddQuestion(new Question(
|
_chatbot.AddQuestion(new Question(
|
||||||
"Texto/Descrição da solicitação (em caso de dúvidas)",
|
"Texto/Descrição da solicitação (em caso de dúvidas)",
|
||||||
resposta => !string.IsNullOrEmpty(resposta)));
|
resposta => !string.IsNullOrEmpty(resposta)));
|
||||||
|
|
||||||
_chatbot.AddQuestion(new Question(
|
_chatbot.AddQuestion(new Question(
|
||||||
"Tudo bem? Posso enviar sua solicitação? Ou prefere que eu tente fazer algum ajuste no texto da descrição?",
|
"Tudo bem? Posso enviar sua solicitação? Ou prefere que eu tente fazer algum ajuste no texto da descrição? (SIM ou NÃO)",
|
||||||
resposta => !string.IsNullOrEmpty(resposta)));
|
resposta => resposta.ToUpper() == "SIM" || resposta.ToUpper() == "NÃO"));
|
||||||
}
|
}
|
||||||
private void AddNumbersBeforShow(Dictionary<string, string> dict)
|
private void AddNumbersBeforShow(Dictionary<string, string> dict)
|
||||||
{
|
{
|
||||||
|
|||||||
171
Services/Bot/Structs/4c0w1xuj.h1l~
Normal file
171
Services/Bot/Structs/4c0w1xuj.h1l~
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
using Amazon.Auth.AccessControlPolicy;
|
||||||
|
using ChatApi.Models;
|
||||||
|
using Microsoft.SemanticKernel.ChatCompletion;
|
||||||
|
|
||||||
|
namespace ChatApi.Services.Bot.Structs
|
||||||
|
{
|
||||||
|
public class ChatBot
|
||||||
|
{
|
||||||
|
private readonly List<Question> _questions;
|
||||||
|
private readonly ChatPersistence _persistence;
|
||||||
|
private readonly Dictionary<int, string> _answers;
|
||||||
|
private readonly IChatCompletionService _chatCompletionService;
|
||||||
|
private readonly IActionCall _actionCall;
|
||||||
|
private readonly string _usuarioId;
|
||||||
|
private readonly UserData _userData;
|
||||||
|
private Dictionary<string, string> _knowParameters;
|
||||||
|
private int _indiceAtual;
|
||||||
|
|
||||||
|
public ChatBot(ChatPersistence persistence, string usuarioId, UserData userData, 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;
|
||||||
|
_userData = userData;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_knowParameters = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "Nome", _userData.Name }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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] = perguntaAtual.ConvertToSave == null ? resposta : perguntaAtual.ConvertToSave(resposta);
|
||||||
|
_indiceAtual++;
|
||||||
|
|
||||||
|
if (_indiceAtual < _questions.Count())
|
||||||
|
{
|
||||||
|
_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,
|
||||||
|
DadosConhecidos = _knowParameters,
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//_knowParameters = new Dictionary<string, string>()
|
||||||
|
// {
|
||||||
|
// { "Nome", _userData.Name }
|
||||||
|
// };
|
||||||
|
|
||||||
|
//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 async Task<string?> CallFinalAction()
|
||||||
|
{
|
||||||
|
_knowParameters = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "Nome", _userData.Name }
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
using Amazon.Auth.AccessControlPolicy;
|
using Amazon.Auth.AccessControlPolicy;
|
||||||
using ChatApi.Models;
|
using ChatApi.Models;
|
||||||
using Microsoft.SemanticKernel.ChatCompletion;
|
using Microsoft.SemanticKernel.ChatCompletion;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ChatApi.Services.Bot.Structs
|
namespace ChatApi.Services.Bot.Structs
|
||||||
{
|
{
|
||||||
@ -49,11 +50,27 @@ namespace ChatApi.Services.Bot.Structs
|
|||||||
_questions.Add(Question);
|
_questions.Add(Question);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SetAnswer(string resposta)
|
public string SetAnswer(string resposta, bool needsRestart = false)
|
||||||
{
|
{
|
||||||
if (!this.HasNextQuestion()) return "";
|
var stops = new List<string>()
|
||||||
|
{
|
||||||
|
"ABORTAR",
|
||||||
|
"ABORTE",
|
||||||
|
"SAIR",
|
||||||
|
"SAIA",
|
||||||
|
"REINICIAR",
|
||||||
|
"REINICIE"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!this.HasNextQuestion()) {
|
||||||
|
SetQuestionIndex(_usuarioId, true);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
var state = _persistence.GetState(_usuarioId);
|
var state = _persistence.GetState(_usuarioId);
|
||||||
|
|
||||||
|
SetQuestionIndex(_usuarioId, needsRestart);
|
||||||
|
|
||||||
if (state != null)
|
if (state != null)
|
||||||
{
|
{
|
||||||
_questions[_indiceAtual].CountTry = state.TentativasPerguntaAtual;
|
_questions[_indiceAtual].CountTry = state.TentativasPerguntaAtual;
|
||||||
@ -62,20 +79,33 @@ namespace ChatApi.Services.Bot.Structs
|
|||||||
{
|
{
|
||||||
_knowParameters = new Dictionary<string, string>()
|
_knowParameters = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
{ "Nome", _userData.Name },
|
{ "Nome", _userData.Name }
|
||||||
{ "Email", _userData.Email }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//var testAll = TestAllQuestions(resposta);
|
||||||
|
|
||||||
|
//if (int.TryParse(testAll, out int index))
|
||||||
|
// _indiceAtual = index < 0 ? _indiceAtual : index - 1;
|
||||||
|
|
||||||
|
//var abort = resposta.ToUpper();
|
||||||
|
//if (index < 0) abort= "ABORTAR";
|
||||||
|
|
||||||
|
//var perguntaAtual = _questions[_indiceAtual];
|
||||||
|
//var testByChat = TestAnswerByChat(resposta);
|
||||||
|
|
||||||
var perguntaAtual = _questions[_indiceAtual];
|
var perguntaAtual = _questions[_indiceAtual];
|
||||||
var testByChat = TestAnswerByChat(resposta);
|
var abort = resposta.ToUpper();
|
||||||
var abort = TestIfWantToAbort(resposta);
|
|
||||||
var validResp = perguntaAtual.TryToAnswer(resposta);
|
var validResp = perguntaAtual.TryToAnswer(resposta);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(validResp) && !abort.Contains("ABORTAR") && perguntaAtual.Validator(resposta) && testByChat.Contains("SIM"))
|
//if (string.IsNullOrEmpty(validResp) && !abort.Contains("ABORTAR") && perguntaAtual.Validator(resposta) && testByChat.Contains("SIM"))
|
||||||
|
if (string.IsNullOrEmpty(validResp) && !stops.Contains(abort))
|
||||||
{
|
{
|
||||||
_answers[_indiceAtual] = resposta;
|
_answers[_indiceAtual] = perguntaAtual.ConvertToSave == null ? resposta : perguntaAtual.ConvertToSave(resposta);
|
||||||
_indiceAtual++;
|
_indiceAtual++;
|
||||||
|
|
||||||
|
if (_indiceAtual < _questions.Count())
|
||||||
|
{
|
||||||
_persistence.SaveState(new ChatState
|
_persistence.SaveState(new ChatState
|
||||||
{
|
{
|
||||||
Id = _usuarioId,
|
Id = _usuarioId,
|
||||||
@ -84,6 +114,7 @@ namespace ChatApi.Services.Bot.Structs
|
|||||||
TentativasPerguntaAtual = _questions[_indiceAtual].CountTry,
|
TentativasPerguntaAtual = _questions[_indiceAtual].CountTry,
|
||||||
Respostas = new Dictionary<int, string>(_answers)
|
Respostas = new Dictionary<int, string>(_answers)
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -103,7 +134,8 @@ namespace ChatApi.Services.Bot.Structs
|
|||||||
Respostas = new Dictionary<int, string>(_answers)
|
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}";
|
//return $"Resposta inválida. Tente novamente. {(testByChat.Contains("NÃO") ? "Motivo: " + testByChat.Replace("NÂO", "") : "")} \n\n {perguntaAtual.Text}";
|
||||||
|
return $"Resposta inválida. Tente novamente. \n{perguntaAtual.Text} \nSua resposta: {resposta}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCurrentQuestion() => _questions[_indiceAtual].Text;
|
public string GetCurrentQuestion() => _questions[_indiceAtual].Text;
|
||||||
@ -119,6 +151,16 @@ namespace ChatApi.Services.Bot.Structs
|
|||||||
_indiceAtual++;
|
_indiceAtual++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string?> CallFinalAction()
|
||||||
|
{
|
||||||
|
_knowParameters = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "Nome", _userData.Name }
|
||||||
|
};
|
||||||
|
|
||||||
var resp = await _actionCall.Populate(_knowParameters, _answers);
|
var resp = await _actionCall.Populate(_knowParameters, _answers);
|
||||||
if (!resp.Success) return "Obrigado por responder a nossas perguntas!";
|
if (!resp.Success) return "Obrigado por responder a nossas perguntas!";
|
||||||
|
|
||||||
@ -135,14 +177,42 @@ namespace ChatApi.Services.Bot.Structs
|
|||||||
|
|
||||||
public string TestIfWantToAbort(string resposta)
|
public string TestIfWantToAbort(string resposta)
|
||||||
{
|
{
|
||||||
if (_indiceAtual==0) return "";
|
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;
|
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" : "";
|
return resp.Content.Contains("SIM") ? "ABORTAR" : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? TestAllQuestions(string resposta)
|
||||||
|
{
|
||||||
|
if (_indiceAtual == 0) return "";
|
||||||
|
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
for (int i = 0; i < _questions.Count; i++)
|
||||||
|
{
|
||||||
|
builder.AppendLine($"{i + 1} - {_questions[i].Text}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp = _chatCompletionService.GetChatMessageContentAsync($"Este é um chatbot. Você pode identificar se a resposta do usuario: \"{resposta}\" tem a inteção de responder uma das perguntas: { builder.ToString() } ? Por favor, reponda com o número da pergunta que o usuário tentou responder, ou com a palavra -1 se não identificou, ou por ultimo com -2 se identificar que o usuário não quis responder nenhuma das perguntas.").Result;
|
||||||
|
return resp.Content;
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasNextQuestion()
|
public bool HasNextQuestion()
|
||||||
{
|
{
|
||||||
return _indiceAtual < _questions.Count;
|
return _indiceAtual < _questions.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetQuestionIndex(string usuarioId, bool needsRestart)
|
||||||
|
{
|
||||||
|
var estado = _persistence.GetState(usuarioId);
|
||||||
|
if (estado != null && !needsRestart)
|
||||||
|
{
|
||||||
|
_indiceAtual = estado.IndicePerguntaAtual;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_indiceAtual = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,15 +6,17 @@
|
|||||||
public Func<string, bool> Validator { get; }
|
public Func<string, bool> Validator { get; }
|
||||||
public int CountTry { get; set; }
|
public int CountTry { get; set; }
|
||||||
public Func<Dictionary<int, string>, bool> Condition { get; }
|
public Func<Dictionary<int, string>, bool> Condition { get; }
|
||||||
|
public Func<string, string> ConvertToSave { get; }
|
||||||
|
|
||||||
private const int MaxTentativas = 2;
|
private const int MaxTentativas = 2;
|
||||||
|
|
||||||
public Question(string texto, Func<string, bool> validador, Func<Dictionary<int, string>, bool> condition=null)
|
public Question(string texto, Func<string, bool> validador, Func<Dictionary<int, string>, bool> condition=null, Func<string,string> convertToSave = null)
|
||||||
{
|
{
|
||||||
Text = texto;
|
Text = texto;
|
||||||
Validator = validador;
|
Validator = validador;
|
||||||
CountTry = 0;
|
CountTry = 0;
|
||||||
Condition = condition;
|
Condition = condition;
|
||||||
|
ConvertToSave = convertToSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MustShow(Dictionary<int, string> respostasAnteriores)
|
public bool MustShow(Dictionary<int, string> respostasAnteriores)
|
||||||
|
|||||||
@ -13,5 +13,6 @@ namespace ChatApi.Services.Classifier
|
|||||||
public EnumClassification Classification { get; set; }
|
public EnumClassification Classification { get; set; }
|
||||||
public DateTime DhInicio { get; set; }
|
public DateTime DhInicio { get; set; }
|
||||||
public EnumClassificationType ClassificationType { get; set; }
|
public EnumClassificationType ClassificationType { get; set; }
|
||||||
|
public EnumClassification LastClassification { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
Services/Crypt/CryptUtil.cs
Normal file
66
Services/Crypt/CryptUtil.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ChatApi.Services.Crypt
|
||||||
|
{
|
||||||
|
public class CryptUtil
|
||||||
|
{
|
||||||
|
private readonly IConfigurationManager _configuration;
|
||||||
|
|
||||||
|
public CryptUtil(IConfigurationManager configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
public string Encrypt(string text)
|
||||||
|
{
|
||||||
|
string key = _configuration.GetSection("DataKey").Value;
|
||||||
|
using (Aes aes = Aes.Create())
|
||||||
|
{
|
||||||
|
aes.Key = Encoding.UTF8.GetBytes(key.PadRight(32).Substring(0, 32));
|
||||||
|
aes.GenerateIV(); // Cria um vetor de inicialização aleatório
|
||||||
|
byte[] iv = aes.IV;
|
||||||
|
|
||||||
|
using (var encryptor = aes.CreateEncryptor(aes.Key, iv))
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
// Primeiro, escreva o IV para o fluxo (será necessário para descriptografia)
|
||||||
|
ms.Write(iv, 0, iv.Length);
|
||||||
|
|
||||||
|
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
|
||||||
|
using (var writer = new StreamWriter(cs))
|
||||||
|
{
|
||||||
|
writer.Write(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Convert.ToBase64String(ms.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Descrypt(string text)
|
||||||
|
{
|
||||||
|
string key = _configuration.GetSection("DataKey").Value;
|
||||||
|
byte[] bytes = Convert.FromBase64String(text);
|
||||||
|
|
||||||
|
using (Aes aes = Aes.Create())
|
||||||
|
{
|
||||||
|
aes.Key = Encoding.UTF8.GetBytes(key.PadRight(32).Substring(0, 32));
|
||||||
|
|
||||||
|
// Extrair o IV do início dos dados criptografados
|
||||||
|
byte[] iv = new byte[aes.BlockSize / 8];
|
||||||
|
Array.Copy(bytes, 0, iv, 0, iv.Length);
|
||||||
|
aes.IV = iv;
|
||||||
|
|
||||||
|
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
||||||
|
using (var ms = new MemoryStream(bytes, iv.Length, bytes.Length - iv.Length))
|
||||||
|
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
|
||||||
|
using (var reader = new StreamReader(cs))
|
||||||
|
{
|
||||||
|
return reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Services/Emails/EmailValidate.cs
Normal file
24
Services/Emails/EmailValidate.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
namespace ChatApi.Services.Emails
|
||||||
|
{
|
||||||
|
public class EmailValidate
|
||||||
|
{
|
||||||
|
public static bool IsValidEmail(string email)
|
||||||
|
{
|
||||||
|
var trimmedEmail = email.Trim();
|
||||||
|
|
||||||
|
if (trimmedEmail.EndsWith("."))
|
||||||
|
{
|
||||||
|
return false; // suggested by @TK-421
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var addr = new System.Net.Mail.MailAddress(email);
|
||||||
|
return addr.Address == trimmedEmail;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,6 @@ namespace ChatApi.Services.ResponseService
|
|||||||
public interface IResponseService
|
public interface IResponseService
|
||||||
{
|
{
|
||||||
EnumClassification Classification { get; }
|
EnumClassification Classification { get; }
|
||||||
Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question);
|
Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question, bool needsRestart = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,42 +32,61 @@ namespace ChatApi.Services.ResponseService
|
|||||||
}
|
}
|
||||||
public EnumClassification Classification => EnumClassification.BotRHCall;
|
public EnumClassification Classification => EnumClassification.BotRHCall;
|
||||||
|
|
||||||
public async Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question)
|
public async Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question, bool needsRestart = false)
|
||||||
{
|
{
|
||||||
var stopWatch = new System.Diagnostics.Stopwatch();
|
var stopWatch = new System.Diagnostics.Stopwatch();
|
||||||
stopWatch.Start();
|
stopWatch.Start();
|
||||||
|
|
||||||
SessionIdStore sessionIdStore = new SessionIdStore(context);
|
SessionIdStore sessionIdStore = new SessionIdStore(context);
|
||||||
ChatHistory history = _chatHistoryService.GetSumarizer(sessionId);
|
ChatHistory history = _chatHistoryService.GetSumarizer(sessionId);
|
||||||
_chatBotCall.UserData = userData;
|
_chatBotCall.UserData = userData;
|
||||||
var resp = _chatBotCall.SetAnswer(sessionId, question);
|
var resp = _chatBotCall.SetAnswer(sessionId, question, needsRestart);
|
||||||
var resposta = "";
|
var resposta = "";
|
||||||
if (string.IsNullOrEmpty(resp) && resp!="REINICIAR")
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(resp) && resp != "REINICIAR" && ( question.ToUpper() != "REINICIAR" && question.ToUpper() != "SAIR"))
|
||||||
{
|
{
|
||||||
resposta = await _chatBotCall.GetNextQuestion();
|
resposta = await _chatBotCall.GetNextQuestion();
|
||||||
history.AddUserMessage(question);
|
|
||||||
|
|
||||||
history.AddMessage(AuthorRole.Assistant, resposta ?? "");
|
history.AddUserMessage(question);
|
||||||
|
history.AddMessage(AuthorRole.Assistant, resposta ?? question);
|
||||||
|
|
||||||
_chatHistoryService.UpdateHistory(sessionId, history);
|
_chatHistoryService.UpdateHistory(sessionId, history);
|
||||||
|
|
||||||
if (!_chatBotCall.HasNextQuestion())
|
if (!_chatBotCall.HasNextQuestion())
|
||||||
{
|
{
|
||||||
|
resposta = await _chatBotCall.CallFinalAction();
|
||||||
_classifierPersistence.DeleteState(sessionId);
|
_classifierPersistence.DeleteState(sessionId);
|
||||||
|
_chatBotCall.SetAnswer(sessionId, "REINICIAR", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (resp == "REINICIAR")
|
if (!needsRestart && resp == "REINICIAR" || (question.ToUpper() != "REINICIAR" || question.ToUpper() != "SAIR"))
|
||||||
{
|
{
|
||||||
_classifierPersistence.DeleteState(sessionId);
|
_classifierPersistence.DeleteState(sessionId);
|
||||||
|
_chatBotCall.SetAnswer(sessionId, "REINICIAR", true);
|
||||||
resp = "Ok! Parece que você não quer continuar e/ou eu não entendi sua resposta. Tudo bem! Se quiser, tente novamente depois...";
|
resp = "Ok! Parece que você não quer continuar e/ou eu não entendi sua resposta. Tudo bem! Se quiser, tente novamente depois...";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resp = "Quero abrir uma nova solicitação ao RH.";
|
||||||
|
await GetResponse(context, userData, sessionId, resp, true);
|
||||||
|
}
|
||||||
|
|
||||||
resposta = resp;
|
resposta = resp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
resposta = "Tivemos um problema. Teremos que reiniciar as perguntas se vc disser que precisa de uma solicitação de rh novamente. Desculpe!";
|
||||||
|
_classifierPersistence.DeleteState(sessionId);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
stopWatch.Stop();
|
stopWatch.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
return $"{resposta ?? ""}\n\nTempo: {stopWatch.ElapsedMilliseconds / 1000}s";
|
return $"{resposta ?? ""}\n\nTempo: {stopWatch.ElapsedMilliseconds / 1000}s";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ namespace ChatApi.Services.ResponseService
|
|||||||
}
|
}
|
||||||
public EnumClassification Classification => EnumClassification.Chat;
|
public EnumClassification Classification => EnumClassification.Chat;
|
||||||
|
|
||||||
public async Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question)
|
public async Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question, bool needsRestart = false)
|
||||||
{
|
{
|
||||||
var stopWatch = new System.Diagnostics.Stopwatch();
|
var stopWatch = new System.Diagnostics.Stopwatch();
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ namespace ChatApi.Services.ResponseService
|
|||||||
}
|
}
|
||||||
public EnumClassification Classification => EnumClassification.Company;
|
public EnumClassification Classification => EnumClassification.Company;
|
||||||
|
|
||||||
public async Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question)
|
public async Task<string> GetResponse(HttpContext context, UserData userData, string sessionId, string question, bool needsRestart = false)
|
||||||
{
|
{
|
||||||
var stopWatch = new System.Diagnostics.Stopwatch();
|
var stopWatch = new System.Diagnostics.Stopwatch();
|
||||||
stopWatch.Start();
|
stopWatch.Start();
|
||||||
|
|||||||
@ -19,6 +19,11 @@ namespace ChatApi.Services
|
|||||||
{
|
{
|
||||||
private readonly TextFilter _textFilter;
|
private readonly TextFilter _textFilter;
|
||||||
private readonly ClassifierPersistence _classifierPersistence;
|
private readonly ClassifierPersistence _classifierPersistence;
|
||||||
|
private bool _needsRestart = false;
|
||||||
|
public bool NeedsRestart()
|
||||||
|
{
|
||||||
|
return _needsRestart;
|
||||||
|
}
|
||||||
|
|
||||||
public TextClassifier(TextFilter textFilter, ClassifierPersistence classifierPersistence)
|
public TextClassifier(TextFilter textFilter, ClassifierPersistence classifierPersistence)
|
||||||
{
|
{
|
||||||
@ -45,11 +50,14 @@ namespace ChatApi.Services
|
|||||||
|
|
||||||
var classify = classifyCompany.Handle(question);
|
var classify = classifyCompany.Handle(question);
|
||||||
|
|
||||||
|
_needsRestart = state != null && classify == EnumClassification.BotRHCall && state.Classification != classify;
|
||||||
|
|
||||||
_classifierPersistence.SaveState(new ClassifierSate
|
_classifierPersistence.SaveState(new ClassifierSate
|
||||||
{
|
{
|
||||||
Id = sessionId,
|
Id = sessionId,
|
||||||
UsuarioId = sessionId,
|
UsuarioId = sessionId,
|
||||||
Classification = classify,
|
Classification = classify,
|
||||||
|
LastClassification = state != null ? state.Classification : classify,
|
||||||
DhInicio = DateTime.Now,
|
DhInicio = DateTime.Now,
|
||||||
ClassificationType = botChat.MyClassification == classify ? EnumClassificationType.Stay : EnumClassificationType.Free
|
ClassificationType = botChat.MyClassification == classify ? EnumClassificationType.Stay : EnumClassificationType.Free
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"DomvsDatabase": {
|
"DomvsDatabase": {
|
||||||
"ConnectionString": "mongodb://localhost:27017",
|
"ConnectionString": "mongodb+srv://rrcgoncalves:zSYxeWCcY7QlmAmF@cluster0.bmjlo.mongodb.net/?authMechanism=DEFAULT",
|
||||||
"DatabaseName": "DomvsSites",
|
"DatabaseName": "DomvsSites",
|
||||||
"SharepointCollectionName": "SharepointSite",
|
"SharepointCollectionName": "SharepointSite",
|
||||||
"ChatBotRHCollectionName": "ChatBotRHData",
|
"ChatBotRHCollectionName": "ChatBotRHData",
|
||||||
"ClassifierCollectionName": "ClassifierData"
|
"ClassifierCollectionName": "ClassifierData"
|
||||||
},
|
},
|
||||||
"ChatRHSettings": {
|
"ChatRHSettings": {
|
||||||
"Url": "https://localhost:7070/",
|
"Url": "http://localhost:8070/",
|
||||||
"Create": "/CallRH"
|
"Create": "/CallRH"
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
{
|
{
|
||||||
"DomvsDatabase": {
|
"DomvsDatabase": {
|
||||||
"ConnectionString": "mongodb://localhost:27017",
|
"ConnectionString": "mongodb+srv://rrcgoncalves:zSYxeWCcY7QlmAmF@cluster0.bmjlo.mongodb.net/?authMechanism=DEFAULT",
|
||||||
"DatabaseName": "DomvsSites",
|
"DatabaseName": "DomvsSites",
|
||||||
"SharepointCollectionName": "SharepointSite",
|
"SharepointCollectionName": "SharepointSite",
|
||||||
"ChatBotRHCollectionName": "ChatBotRHData",
|
"ChatBotRHCollectionName": "ChatBotRHData",
|
||||||
"ClassifierCollectionName": "ClassifierData"
|
"ClassifierCollectionName": "ClassifierData",
|
||||||
|
"UserDataName": "UserData"
|
||||||
},
|
},
|
||||||
"ChatRHSettings": {
|
"ChatRHSettings": {
|
||||||
"Url": "mongodb://localhost:27017",
|
"Url": "http://localhost:8070/",
|
||||||
"Create": "DomvsSites"
|
"Create": "DomvsSites"
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
@ -18,5 +19,16 @@
|
|||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"AppTenantId": "20190830-5fd4-4a72-b8fd-1c1cb35b25bc",
|
"AppTenantId": "20190830-5fd4-4a72-b8fd-1c1cb35b25bc",
|
||||||
"AppClientID": "8f4248fc-ee30-4f54-8793-66edcca3fd20"
|
"AppClientID": "8f4248fc-ee30-4f54-8793-66edcca3fd20",
|
||||||
|
|
||||||
|
"AzureAd": {
|
||||||
|
"Instance": "https://login.microsoftonline.com/",
|
||||||
|
"Domain": "domvsitbr.onmicrosoft.com",
|
||||||
|
"TenantId": "20190830-5fd4-4a72-b8fd-1c1cb35b25bc",
|
||||||
|
"ClientId": "8f4248fc-ee30-4f54-8793-66edcca3fd20"
|
||||||
|
},
|
||||||
|
"Issuer": "domvsit.com.br",
|
||||||
|
"Audience": "domvsit.com.br",
|
||||||
|
"SigningKey": "D57Ls16KxMPdF4P7qTQtV29slWjJqIJZ",
|
||||||
|
"DataKey": "NOxGacYtZRJTYCPdSQM75HVSNp3qfH05mPalaE/pL4A6FwxWKQiBhLxhu++LrKsI"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user