From fc51b23bcf94ce2946493a00bc9103f7e23dd9b3 Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Sun, 6 May 2018 19:48:10 -0500 Subject: [PATCH] fix intent is not correct when context is empty in the middle of the converstion. --- BotSharp.Core/Agents/Agent.cs | 16 ++++ BotSharp.Core/Engines/RequestExtension.cs | 97 +++++++++++--------- BotSharp.Core/Intents/IntentResponse.cs | 3 + BotSharp.UnitTest/AgentTest.cs | 4 +- BotSharp.UnitTest/IntentTest.cs | 29 +----- BotSharp.UnitTest/Settings/settings.bot.json | 2 +- 6 files changed, 77 insertions(+), 74 deletions(-) diff --git a/BotSharp.Core/Agents/Agent.cs b/BotSharp.Core/Agents/Agent.cs index ee60cb35..6a6429c1 100644 --- a/BotSharp.Core/Agents/Agent.cs +++ b/BotSharp.Core/Agents/Agent.cs @@ -13,6 +13,11 @@ namespace BotSharp.Core.Agents [Table("Bot_Agent")] public class Agent : DbRecord, IDbRecord { + public Agent() + { + CreatedDate = DateTime.UtcNow; + } + [MaxLength(64)] public String Name { get; set; } @@ -49,5 +54,16 @@ namespace BotSharp.Core.Agents [ForeignKey("AgentId")] [JsonProperty("entity_types")] public List Entities { get; set; } + + public String Birthday + { + get + { + return CreatedDate.ToShortDateString(); + } + } + + [Required] + public DateTime CreatedDate { get; set; } } } diff --git a/BotSharp.Core/Engines/RequestExtension.cs b/BotSharp.Core/Engines/RequestExtension.cs index 4403b76d..6dfc11fc 100644 --- a/BotSharp.Core/Engines/RequestExtension.cs +++ b/BotSharp.Core/Engines/RequestExtension.cs @@ -27,52 +27,12 @@ namespace BotSharp.Core.Engines public static AIResponse TextRequest(this RasaAi rasa, AIRequest request) { AIResponse aiResponse = new AIResponse(); - RasaResponse response = null; Database dc = rasa.dc; - // Merge input contexts - var contexts = dc.Table() - .Where(x => x.ConversationId == rasa.AiConfig.SessionId && x.Lifespan > 0) - .ToList() - .Select(x => new AIContext { Name = x.Context.ToLower(), Lifespan = x.Lifespan }) - .ToList(); - - contexts.AddRange(request.Contexts.Select(x => new AIContext { Name = x.Name.ToLower(), Lifespan = x.Lifespan })); - contexts = contexts.OrderBy(x => x.Name).ToList(); - - // search all potential intents which input context included in contexts - var intents = rasa.agent.Intents.Where(it => - { - if (contexts.Count == 0) - { - return it.Contexts.Count() == 0; - } - else - { - return it.Contexts.Count() > 0 && - it.Contexts.Count(x => contexts.Select(ctx => ctx.Name).Contains(x.Name.ToLower())) == it.Contexts.Count; - } - }).OrderByDescending(x => x.Contexts.Count).ToList(); - var result = CallRasa(rasa.agent.Id, request.Query.First(), rasa.agent.Id); + RasaResponse response = result.Data; + var intentResponse = HandleIntentPerContextIn(rasa, request, result.Data); - if (result.Data.IntentRanking == null) - { - result.Data.IntentRanking = new List - { - result.Data.Intent - }; - } - result.Data.IntentRanking = result.Data.IntentRanking.Where(x => intents.Select(i => i.Name).Contains(x.Name)).ToList(); - result.Data.Intent = result.Data.IntentRanking.First(); - response = result.Data; - - var intent = (dc.Table().Where(x => x.Name == response.Intent.Name) - .Include(x => x.Responses).ThenInclude(x => x.Contexts) - .Include(x => x.Responses).ThenInclude(x => x.Parameters) - .Include(x => x.Responses).ThenInclude(x => x.Messages)).First(); - - var intentResponse = ArrayHelper.GetRandom(intent.Responses); aiResponse.Id = Guid.NewGuid().ToString(); aiResponse.Lang = rasa.agent.Language; aiResponse.Status = new AIResponseStatus { }; @@ -90,7 +50,7 @@ namespace BotSharp.Core.Engines Action = intentResponse.Action, Parameters = intentResponse.Parameters.ToDictionary(x => x.Name, x=> x.Value), Score = response.Intent.Confidence, - Metadata = new AIResponseMetadata { IntentId = intent.Id, IntentName = intent.Name }, + Metadata = new AIResponseMetadata { IntentId = intentResponse.IntentId, IntentName = intentResponse.IntentName }, Fulfillment = new AIResponseFulfillment { Messages = intentResponse.Messages.Select(x => { @@ -116,6 +76,55 @@ namespace BotSharp.Core.Engines return aiResponse; } + private static IntentResponse HandleIntentPerContextIn(RasaAi rasa, AIRequest request, RasaResponse response) + { + Database dc = rasa.dc; + + // Merge input contexts + var contexts = dc.Table() + .Where(x => x.ConversationId == rasa.AiConfig.SessionId && x.Lifespan > 0) + .ToList() + .Select(x => new AIContext { Name = x.Context.ToLower(), Lifespan = x.Lifespan }) + .ToList(); + + contexts.AddRange(request.Contexts.Select(x => new AIContext { Name = x.Name.ToLower(), Lifespan = x.Lifespan })); + contexts = contexts.OrderBy(x => x.Name).ToList(); + + // search all potential intents which input context included in contexts + var intents = rasa.agent.Intents.Where(it => + { + if (contexts.Count == 0) + { + return it.Contexts.Count() == 0; + } + else + { + return it.Contexts.Count() == 0 || + it.Contexts.Count(x => contexts.Select(ctx => ctx.Name).Contains(x.Name.ToLower())) == it.Contexts.Count; + } + }).OrderByDescending(x => x.Contexts.Count).ToList(); + + if (response.IntentRanking == null) + { + response.IntentRanking = new List + { + response.Intent + }; + } + response.IntentRanking = response.IntentRanking.Where(x => intents.Select(i => i.Name).Contains(x.Name)).ToList(); + response.Intent = response.IntentRanking.First(); + + var intent = (dc.Table().Where(x => x.Name == response.Intent.Name) + .Include(x => x.Responses).ThenInclude(x => x.Contexts) + .Include(x => x.Responses).ThenInclude(x => x.Parameters) + .Include(x => x.Responses).ThenInclude(x => x.Messages)).First(); + + var intentResponse = ArrayHelper.GetRandom(intent.Responses); + intentResponse.IntentName = intent.Name; + + return intentResponse; + } + private static void HandleParameter(Agent agent, IntentResponse intentResponse, RasaResponse response, AIRequest request) { intentResponse.Parameters.ForEach(p => { @@ -210,7 +219,7 @@ namespace BotSharp.Core.Engines }); aiResponse.Result.Contexts = dc.Table() - .Where(x => x.ConversationId == rasa.AiConfig.SessionId) + .Where(x => x.Lifespan > 0 && x.ConversationId == rasa.AiConfig.SessionId) .Select(x => new AIContext { Name = x.Context.ToLower(), Lifespan = x.Lifespan }) .ToArray(); } diff --git a/BotSharp.Core/Intents/IntentResponse.cs b/BotSharp.Core/Intents/IntentResponse.cs index 0b373a1a..4fb47fdf 100644 --- a/BotSharp.Core/Intents/IntentResponse.cs +++ b/BotSharp.Core/Intents/IntentResponse.cs @@ -27,5 +27,8 @@ namespace BotSharp.Core.Intents [ForeignKey("IntentResponseId")] public List Messages { get; set; } + + [NotMapped] + public string IntentName { get; set; } } } diff --git a/BotSharp.UnitTest/AgentTest.cs b/BotSharp.UnitTest/AgentTest.cs index 4a9d7ae5..34ff01f1 100644 --- a/BotSharp.UnitTest/AgentTest.cs +++ b/BotSharp.UnitTest/AgentTest.cs @@ -20,7 +20,8 @@ namespace BotSharp.UnitTest { Id = BOT_ID, Name = BOT_NAME, - Language = "en" + Language = "en", + UserId = Guid.NewGuid().ToString() }; var rasa = new RasaAi(dc); @@ -52,6 +53,7 @@ namespace BotSharp.UnitTest agent.Id = BOT_ID; agent.ClientAccessToken = BOT_CLIENT_TOKEN; agent.DeveloperAccessToken = BOT_DEVELOPER_TOKEN; + agent.UserId = Guid.NewGuid().ToString(); int row = dc.DbTran(() => rasa.SaveAgent(agent)); } diff --git a/BotSharp.UnitTest/IntentTest.cs b/BotSharp.UnitTest/IntentTest.cs index 5396ffb5..16f6b7f5 100644 --- a/BotSharp.UnitTest/IntentTest.cs +++ b/BotSharp.UnitTest/IntentTest.cs @@ -3,6 +3,7 @@ using BotSharp.Core.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace BotSharp.UnitTest @@ -17,34 +18,6 @@ namespace BotSharp.UnitTest config.SessionId = Guid.NewGuid().ToString(); var rasa = new RasaAi(dc, config); - - // Round 1 - var response = rasa.TextRequest(new AIRequest { Query = new String[] { "Hi, Voiceweb" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Wakeup"); - - // Round 2 - response = rasa.TextRequest(new AIRequest { Query = new String[] { "I'm going to apple store to buy iphone 10" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Transfer2SalesBot"); - - // Round 3 - response = rasa.TextRequest(new AIRequest { Query = new String[] { "Yes" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Transfer2SalesBot - address"); - - // Round 4 - response = rasa.TextRequest(new AIRequest { Query = new String[] { "Sure" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Transfer2SalesBot - confirm address"); - - // Round 5 - response = rasa.TextRequest(new AIRequest { Query = new String[] { "That's right" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Transfer2SalesBot - payment"); - - // Round 6 - response = rasa.TextRequest(new AIRequest { Query = new String[] { "Yes" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Transfer2SalesBot - place work order"); - - // Round 7 - response = rasa.TextRequest(new AIRequest { Query = new String[] { "byebye" } }); - Assert.AreEqual(response.Result.Metadata.IntentName, "Byebye"); } } } diff --git a/BotSharp.UnitTest/Settings/settings.bot.json b/BotSharp.UnitTest/Settings/settings.bot.json index 96cf8614..6f5ed12c 100644 --- a/BotSharp.UnitTest/Settings/settings.bot.json +++ b/BotSharp.UnitTest/Settings/settings.bot.json @@ -1,5 +1,5 @@ { "Rasa": { - "Host": "http://rasa.local:5000" + "Nlu": "http://localhost:5000" } }