From 3fcd6a399653a835a343765ded7bf84be098b81e Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Sun, 15 Jul 2018 07:31:52 -0500 Subject: [PATCH] Abstract bot platform infrastrature, decouple modules. --- BotSharp.Core/Abstractions/IAgentImporter.cs | 4 +- BotSharp.Core/Abstractions/IBotPlatform.cs | 2 + BotSharp.Core/BotSharp.Core.csproj | 7 +- BotSharp.Core/Engines/AgentImportHeader.cs | 15 +++ .../BotEngineBase.cs} | 121 +++++++++++------- BotSharp.Core/Engines/BotSharp/BotSharpAi.cs | 20 +++ .../CRFsuite/CRFsuiteEntityRecognizer.cs | 2 +- .../Engines/Dialogflow/AIConfiguration.cs | 2 + .../Dialogflow/AgentImporterInDialogflow.cs | 17 ++- BotSharp.Core/Engines/Rasa/RasaAi.cs | 85 ++---------- .../Engines/Rasa/RasaIntentExpression.cs | 15 +-- .../Engines/Rasa/RasaIntentExpressionPart.cs | 9 +- .../Engines/Rasa/RasaTraningEntity.cs | 11 +- .../Engines/SpaCy/SpaCyEntityRecognizer.cs | 4 +- BotSharp.Core/Engines/SpaCy/SpaCyTokenizer.cs | 4 +- .../Engines/SpaCy/SpacyFeaturizer.cs | 4 +- BotSharp.Core/Engines/TrainingCorpus.cs | 14 ++ BotSharp.Core/Engines/TrainingEntity.cs | 15 +++ .../Engines/TrainingIntentExpression.cs | 18 +++ .../Engines/TrainingIntentExpressionPart.cs | 14 ++ BotSharp.RestApi/AgentController.cs | 35 ++++- BotSharp.RestApi/BotSharp.RestApi.csproj | 4 + BotSharp.RestApi/ConversationController.cs | 13 ++ BotSharp.RestApi/IntentController.cs | 12 ++ BotSharp.UnitTest/AgentTest.cs | 36 ++---- BotSharp.UnitTest/BotSharp.UnitTest.csproj | 2 +- BotSharp.UnitTest/BotTrainerTest.cs | 6 +- BotSharp.UnitTest/ConversationTest.cs | 7 +- BotSharp.UnitTest/TestEssential.cs | 3 - BotSharp.WebHost/BotSharp.WebHost.csproj | 5 + BotSharp.WebHost/Settings/app.json | 14 +- BotSharp.WebHost/Settings/logging.json | 15 +++ BotSharp.WebHost/Settings/swagger.json | 19 +++ BotSharp.WebHost/Startup.cs | 36 +++++- BotSharp.WebHost/wwwroot/images/BotSharp.png | Bin 0 -> 11445 bytes BotSharp.WebHost/wwwroot/images/BotSharp.psd | Bin 0 -> 128892 bytes BotSharp.WebHost/wwwroot/swagger.css | 3 + 37 files changed, 385 insertions(+), 208 deletions(-) create mode 100644 BotSharp.Core/Engines/AgentImportHeader.cs rename BotSharp.Core/{Agents/AgentDriver.cs => Engines/BotEngineBase.cs} (50%) create mode 100644 BotSharp.Core/Engines/BotSharp/BotSharpAi.cs create mode 100644 BotSharp.Core/Engines/TrainingCorpus.cs create mode 100644 BotSharp.Core/Engines/TrainingEntity.cs create mode 100644 BotSharp.Core/Engines/TrainingIntentExpression.cs create mode 100644 BotSharp.Core/Engines/TrainingIntentExpressionPart.cs create mode 100644 BotSharp.RestApi/ConversationController.cs create mode 100644 BotSharp.RestApi/IntentController.cs create mode 100644 BotSharp.WebHost/Settings/logging.json create mode 100644 BotSharp.WebHost/Settings/swagger.json create mode 100644 BotSharp.WebHost/wwwroot/images/BotSharp.png create mode 100644 BotSharp.WebHost/wwwroot/images/BotSharp.psd create mode 100644 BotSharp.WebHost/wwwroot/swagger.css diff --git a/BotSharp.Core/Abstractions/IAgentImporter.cs b/BotSharp.Core/Abstractions/IAgentImporter.cs index 584b4e22..e2ea0acf 100644 --- a/BotSharp.Core/Abstractions/IAgentImporter.cs +++ b/BotSharp.Core/Abstractions/IAgentImporter.cs @@ -10,10 +10,10 @@ namespace BotSharp.Core.Engines /// /// Load agent summary /// - /// agent guid or name + /// /// /// - Agent LoadAgent(string agentId, string agentDir); + Agent LoadAgent(AgentImportHeader agentHeader, string agentDir); /// /// Load user customized entity type diff --git a/BotSharp.Core/Abstractions/IBotPlatform.cs b/BotSharp.Core/Abstractions/IBotPlatform.cs index 48275a7a..df6ee8bd 100644 --- a/BotSharp.Core/Abstractions/IBotPlatform.cs +++ b/BotSharp.Core/Abstractions/IBotPlatform.cs @@ -1,4 +1,5 @@ using BotSharp.Core.Models; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; @@ -8,6 +9,7 @@ namespace BotSharp.Core.Engines public interface IBotPlatform { AIResponse TextRequest(AIRequest request); + void Train(); } } diff --git a/BotSharp.Core/BotSharp.Core.csproj b/BotSharp.Core/BotSharp.Core.csproj index 35f376ef..0d8a8e26 100644 --- a/BotSharp.Core/BotSharp.Core.csproj +++ b/BotSharp.Core/BotSharp.Core.csproj @@ -25,7 +25,7 @@ - TRACE;MODEL_PER_CONTEXTS;NETCOREAPP;NETCOREAPP2_1 + TRACE;DEBUG @@ -43,9 +43,4 @@ - - - - - diff --git a/BotSharp.Core/Engines/AgentImportHeader.cs b/BotSharp.Core/Engines/AgentImportHeader.cs new file mode 100644 index 00000000..b73c7d4c --- /dev/null +++ b/BotSharp.Core/Engines/AgentImportHeader.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Engines +{ + public class AgentImportHeader + { + public String Id { get; set; } + public String Name { get; set; } + public String UserId { get; set; } + public String ClientAccessToken { get; set; } + public String DeveloperAccessToken { get; set; } + } +} diff --git a/BotSharp.Core/Agents/AgentDriver.cs b/BotSharp.Core/Engines/BotEngineBase.cs similarity index 50% rename from BotSharp.Core/Agents/AgentDriver.cs rename to BotSharp.Core/Engines/BotEngineBase.cs index ba48b6a5..73235248 100644 --- a/BotSharp.Core/Agents/AgentDriver.cs +++ b/BotSharp.Core/Engines/BotEngineBase.cs @@ -1,5 +1,4 @@ -using BotSharp.Core.Adapters.Rasa; -using BotSharp.Core.Engines; +using BotSharp.Core.Agents; using BotSharp.Core.Entities; using BotSharp.Core.Intents; using BotSharp.Core.Models; @@ -7,58 +6,90 @@ using EntityFrameworkCore.BootKit; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; -namespace BotSharp.Core.Agents +namespace BotSharp.Core.Engines { - public static class AgentDriver + /// + /// Bot engine/ platform base class + /// + public abstract class BotEngineBase { - public static Agent LoadAgentById(this IBotPlatform engine, Database dc, string agentId) + protected Database dc; + + public AIConfiguration AiConfig { get; set; } + + protected Agent agent { get; set; } + + public String DbInitializerPath { get; private set; } + + public BotEngineBase() { - var clientAccessToken = dc.Table().Find(agentId).ClientAccessToken; - - var config = new AIConfiguration(clientAccessToken, SupportedLanguage.English); - - var rasa = new RasaAi(dc, config); - rasa.agent = rasa.LoadAgent(dc, config); - - return rasa.agent; + dc = new DefaultDataContextLoader().GetDefaultDc(); + DbInitializerPath = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}"; } - public static Agent LoadAgent(this IBotPlatform engine, Database dc, AIConfiguration aiConfig) + /// + /// Load Agent + /// + /// agentId, clientAccessToken, developerAccessToken + /// + public Agent LoadAgent(string id) { - return dc.Table() - .Include(x => x.Intents).ThenInclude(x => x.Contexts) - .Include(x => x.Entities).ThenInclude(x => x.Entries).ThenInclude(x => x.Synonyms) - .Include(x => x.MlConfig) - .FirstOrDefault(x => x.ClientAccessToken == aiConfig.ClientAccessToken || x.DeveloperAccessToken == aiConfig.ClientAccessToken); + if (agent == null) + { + agent = dc.Table() + .Include(x => x.Intents).ThenInclude(x => x.Contexts) + .Include(x => x.Entities).ThenInclude(x => x.Entries).ThenInclude(x => x.Synonyms) + .Include(x => x.MlConfig) + .FirstOrDefault(x => x.Id == id || + x.ClientAccessToken == id || + x.DeveloperAccessToken == id); + } + else + { + return agent; + } + + return agent; } /// /// Restore a agent instance from backup json files /// - /// - /// + /// + /// + /// /// - public static Agent RestoreAgent(this IBotPlatform engine, IAgentImporter importer, String agentId, string dataDir) + public bool RestoreAgent(AgentImportHeader agentHeader) where TAgentImporter : IAgentImporter, new() { - // Load agent summary - var agent = importer.LoadAgent(agentId, dataDir); + var importer = new TAgentImporter(); - // Load user custom entities - importer.LoadCustomEntities(agent, dataDir); + string dataDir = $"{DbInitializerPath}Agents{Path.DirectorySeparatorChar}"; - // Load agent intents - importer.LoadIntents(agent, dataDir); + int row = dc.DbTran(() => { - // Load system buildin entities - importer.LoadBuildinEntities(agent, dataDir); + // Load agent summary + agent = importer.LoadAgent(agentHeader, dataDir); - return agent; + // Load user custom entities + importer.LoadCustomEntities(agent, dataDir); + + // Load agent intents + importer.LoadIntents(agent, dataDir); + + // Load system buildin entities + importer.LoadBuildinEntities(agent, dataDir); + + SaveAgent(); + }); + + return row > 0; } - public static String SaveAgent(this Agent agent, Database dc) + public String SaveAgent() { var existedAgent = dc.Table().FirstOrDefault(x => x.Id == agent.Id || x.Name == agent.Name); if (existedAgent == null) @@ -73,12 +104,12 @@ namespace BotSharp.Core.Agents } } - public static RasaTrainingData GrabCorpus(this Agent agent, Database dc) + public TrainingCorpus GetIntentExpressions() { - var trainingData = new RasaTrainingData + TrainingCorpus corpus = new TrainingCorpus() { - Entities = new List(), - UserSays = new List() + UserSays = new List>(), + Entities = new List() }; var expressParts = new List(); @@ -93,7 +124,7 @@ namespace BotSharp.Core.Agents { intent.UserSays.ForEach(exp => { - var say = new RasaIntentExpression + var say = new TrainingIntentExpression { Intent = intent.Name, Text = String.Join("", exp.Data.OrderBy(x => x.UpdatedTime).Select(x => x.Text)), @@ -107,7 +138,7 @@ namespace BotSharp.Core.Agents { int start = say.Text.IndexOf(x.Text); - var part = new RasaIntentExpressionPart + var part = new TrainingIntentExpressionPart { Value = x.Text, Entity = $"{x.Meta}:{x.Alias}", @@ -115,11 +146,11 @@ namespace BotSharp.Core.Agents End = start + x.Text.Length }; - if (say.Entities == null) say.Entities = new List(); + if (say.Entities == null) say.Entities = new List(); say.Entities.Add(part); // assemble entity synonmus - if (!trainingData.Entities.Any(y => y.EntityType == x.Alias && y.EntityValue == x.Text)) + /*if (!trainingData.Entities.Any(y => y.EntityType == x.Alias && y.EntityValue == x.Text)) { var allSynonyms = (from e in dc.Table() join ee in dc.Table() on e.Id equals ee.EntityId @@ -127,7 +158,7 @@ namespace BotSharp.Core.Agents where e.Name == x.Alias && ee.Value == x.Text & ees.Synonym != x.Text select ees.Synonym).ToList(); - var te = new RasaTraningEntity + var te = new TrainingEntity { EntityType = $"{x.Meta}:{x.Alias}", EntityValue = x.Text, @@ -135,17 +166,17 @@ namespace BotSharp.Core.Agents }; trainingData.Entities.Add(te); - } + }*/ }); - trainingData.UserSays.Add(say); + corpus.UserSays.Add(say); }); }); // remove Default Fallback Intent - trainingData.UserSays = trainingData.UserSays.Where(x => x.Intent != "Default Fallback Intent").ToList(); + corpus.UserSays = corpus.UserSays.Where(x => x.Intent != "Default Fallback Intent").ToList(); - return trainingData; + return corpus; } } } diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpAi.cs b/BotSharp.Core/Engines/BotSharp/BotSharpAi.cs new file mode 100644 index 00000000..da88bf23 --- /dev/null +++ b/BotSharp.Core/Engines/BotSharp/BotSharpAi.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BotSharp.Core.Models; + +namespace BotSharp.Core.Engines.BotSharp +{ + public class BotSharpAi : BotEngineBase, IBotPlatform + { + public AIResponse TextRequest(AIRequest request) + { + throw new NotImplementedException(); + } + + public void Train() + { + throw new NotImplementedException(); + } + } +} diff --git a/BotSharp.Core/Engines/CRFsuite/CRFsuiteEntityRecognizer.cs b/BotSharp.Core/Engines/CRFsuite/CRFsuiteEntityRecognizer.cs index c50cb7c6..54ad91a9 100644 --- a/BotSharp.Core/Engines/CRFsuite/CRFsuiteEntityRecognizer.cs +++ b/BotSharp.Core/Engines/CRFsuite/CRFsuiteEntityRecognizer.cs @@ -18,7 +18,7 @@ namespace BotSharp.Core.Engines.CRFsuite public bool Process(Agent agent, JObject data) { var dc = new DefaultDataContextLoader().GetDefaultDc(); - var corpus = agent.GrabCorpus(dc); + //var corpus = agent.GrabCorpus(dc); // Mock Data List train_sent = new List(); diff --git a/BotSharp.Core/Engines/Dialogflow/AIConfiguration.cs b/BotSharp.Core/Engines/Dialogflow/AIConfiguration.cs index 1d4978b4..77df4aa2 100644 --- a/BotSharp.Core/Engines/Dialogflow/AIConfiguration.cs +++ b/BotSharp.Core/Engines/Dialogflow/AIConfiguration.cs @@ -13,6 +13,8 @@ namespace BotSharp.Core.Models public string ClientAccessToken { get; private set; } + public string AgentId { get; set; } + public SupportedLanguage Language { get; set; } public bool VoiceActivityDetectionEnabled { get; set; } diff --git a/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs b/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs index a43cfc6a..41581cb0 100644 --- a/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs +++ b/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs @@ -22,18 +22,25 @@ namespace BotSharp.Core.Engines /// /// Load agent meta /// - /// + /// /// /// - public Agent LoadAgent(string agentId, string agentDir) + public Agent LoadAgent(AgentImportHeader agentHeader, string agentDir) { // load agent profile - string data = File.ReadAllText($"{agentDir}{Path.DirectorySeparatorChar}Dialogflow{Path.DirectorySeparatorChar}{agentId}{Path.DirectorySeparatorChar}agent.json"); + string data = File.ReadAllText($"{agentDir}{Path.DirectorySeparatorChar}Dialogflow{Path.DirectorySeparatorChar}{agentHeader.Name}{Path.DirectorySeparatorChar}agent.json"); var agent = JsonConvert.DeserializeObject(data); - agent.Id = Guid.NewGuid().ToString(); - agent.Name = agentId; + agent.Name = agentHeader.Name; + agent.Id = agentHeader.Id; var result = agent.ToObject(); + result.ClientAccessToken = agentHeader.ClientAccessToken; + result.DeveloperAccessToken = agentHeader.DeveloperAccessToken; + if(agentHeader.UserId != null) + { + result.UserId = agentHeader.UserId; + } + result.MlConfig = agent.ToObject(); result.MlConfig.MinConfidence = agent.MlMinConfidence; result.MlConfig.AgentId = agent.Id; diff --git a/BotSharp.Core/Engines/Rasa/RasaAi.cs b/BotSharp.Core/Engines/Rasa/RasaAi.cs index 71530e07..0d23c3e8 100644 --- a/BotSharp.Core/Engines/Rasa/RasaAi.cs +++ b/BotSharp.Core/Engines/Rasa/RasaAi.cs @@ -1,4 +1,5 @@ -using BotSharp.Core.Agents; +using BotSharp.Core.Adapters.Rasa; +using BotSharp.Core.Agents; using BotSharp.Core.Entities; using BotSharp.Core.Intents; using BotSharp.Core.Models; @@ -19,39 +20,17 @@ using System.Text; namespace BotSharp.Core.Engines { /// - /// Rasa nlu 0.12.x + /// Rasa nlu >= 0.12 /// - public class RasaAi : IBotPlatform + public class RasaAi : BotEngineBase, IBotPlatform { - public Database dc { get; set; } - public AIConfiguration AiConfig { get; set; } - - public Agent agent { get; set; } - - public RasaAi(Database dc) - { - this.dc = dc; - } - - public RasaAi(Database dc, AIConfiguration aiConfig) - { - this.dc = dc; - - AiConfig = aiConfig; - agent = this.LoadAgent(dc, aiConfig); - aiConfig.DevMode = agent.DeveloperAccessToken == aiConfig.ClientAccessToken; - } - public AIResponse TextRequest(AIRequest request) { AIResponse aiResponse = new AIResponse(); -#if MODEL_PER_CONTEXTS string model = RasaRequestExtension.GetModelPerContexts(agent, AiConfig, request, dc); var result = CallRasa(agent.Id, request.Query.First(), model); -#else - var result = CallRasa(rasa.agent.Id, request.Query.First(), rasa.agent.Id); -#endif + result.Content.Log(); RasaResponse response = result.Data; @@ -119,7 +98,13 @@ namespace BotSharp.Core.Engines public void Train() { - var corpus = agent.GrabCorpus(dc); + var trainingData = new RasaTrainingData + { + Entities = new List(), + UserSays = new List() + }; + + var corpus = GetIntentExpressions(); var client = new RestClient($"{Database.Configuration.GetSection("Rasa:Nlu").Value}"); var contextHashs = corpus.UserSays @@ -146,8 +131,8 @@ namespace BotSharp.Core.Engines var data = new RasaTrainingData { - Entities = entity_synonyms, - UserSays = common_examples + Entities = entity_synonyms.Select(x => x.ToObject()).ToList(), + UserSays = common_examples.Select(x => x.Intent.ToObject()).ToList() }; // meet minimal requirement @@ -231,47 +216,5 @@ namespace BotSharp.Core.Engines }); } - - [Obsolete] - public string TrainWithoutContext() - { - var client = new RestClient($"{Database.Configuration.GetSection("Rasa:Nlu").Value}"); - var rest = new RestRequest("train", Method.POST); - rest.AddQueryParameter("project", agent.Id); - - var corpus = agent.GrabCorpus(dc); - - string json = JsonConvert.SerializeObject(new { rasa_nlu_data = corpus }, - new JsonSerializerSettings - { - ContractResolver = new CamelCasePropertyNamesContractResolver(), - NullValueHandling = NullValueHandling.Ignore - }); - - string trainingConfig = agent.Language == "zh" ? "config_jieba_mitie_sklearn.yml" : "config_spacy.yml"; - string body = File.ReadAllText($"{Database.ContentRootPath}{Path.DirectorySeparatorChar}Settings{Path.DirectorySeparatorChar}{trainingConfig}"); - body = $"{body}\r\ndata: {json}"; - rest.AddParameter("application/x-yml", body, ParameterType.RequestBody); - - var response = client.Execute(rest); - - if (response.IsSuccessful) - { - var result = JObject.Parse(response.Content); - - string modelName = result["info"].Value().Split(": ")[1]; - - return modelName; - } - else - { - var result = JObject.Parse(response.Content); - - Console.WriteLine(result["error"]); - - return String.Empty; - } - } - } } diff --git a/BotSharp.Core/Engines/Rasa/RasaIntentExpression.cs b/BotSharp.Core/Engines/Rasa/RasaIntentExpression.cs index b3dfcd4c..414f0b50 100644 --- a/BotSharp.Core/Engines/Rasa/RasaIntentExpression.cs +++ b/BotSharp.Core/Engines/Rasa/RasaIntentExpression.cs @@ -1,22 +1,13 @@ -using Newtonsoft.Json; +using BotSharp.Core.Engines; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Text; namespace BotSharp.Core.Models { - public class RasaIntentExpression + public class RasaIntentExpression : TrainingIntentExpression { - public RasaIntentExpression() - { - } - public String Text { get; set; } - public String Intent { get; set; } - - [JsonIgnore] - public String ContextHash { get; set; } - - public List Entities { get; set; } } } diff --git a/BotSharp.Core/Engines/Rasa/RasaIntentExpressionPart.cs b/BotSharp.Core/Engines/Rasa/RasaIntentExpressionPart.cs index d4c254c2..4925df0e 100644 --- a/BotSharp.Core/Engines/Rasa/RasaIntentExpressionPart.cs +++ b/BotSharp.Core/Engines/Rasa/RasaIntentExpressionPart.cs @@ -1,14 +1,11 @@ -using System; +using BotSharp.Core.Engines; +using System; using System.Collections.Generic; using System.Text; namespace BotSharp.Core.Models { - public class RasaIntentExpressionPart + public class RasaIntentExpressionPart : TrainingIntentExpressionPart { - public int Start { get; set; } - public int End { get; set; } - public String Value { get; set; } - public String Entity { get; set; } } } diff --git a/BotSharp.Core/Engines/Rasa/RasaTraningEntity.cs b/BotSharp.Core/Engines/Rasa/RasaTraningEntity.cs index 67a38a28..6ac97ebc 100644 --- a/BotSharp.Core/Engines/Rasa/RasaTraningEntity.cs +++ b/BotSharp.Core/Engines/Rasa/RasaTraningEntity.cs @@ -1,18 +1,17 @@ -using Newtonsoft.Json; +using BotSharp.Core.Engines; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Text; namespace BotSharp.Core.Adapters.Rasa { - public class RasaTraningEntity + public sealed class RasaTraningEntity : TrainingEntity { [JsonIgnore] - public String EntityType { get; set; } + public override String EntityType { get; set; } [JsonProperty("value")] - public String EntityValue { get; set; } - - public List Synonyms { get; set; } + public override String EntityValue { get; set; } } } diff --git a/BotSharp.Core/Engines/SpaCy/SpaCyEntityRecognizer.cs b/BotSharp.Core/Engines/SpaCy/SpaCyEntityRecognizer.cs index a1862712..d0338412 100644 --- a/BotSharp.Core/Engines/SpaCy/SpaCyEntityRecognizer.cs +++ b/BotSharp.Core/Engines/SpaCy/SpaCyEntityRecognizer.cs @@ -27,7 +27,7 @@ namespace BotSharp.Core.Engines.SpaCy List trainingData = new List(); var dc = new DefaultDataContextLoader().GetDefaultDc(); - var corpus = agent.GrabCorpus(dc); + /*var corpus = agent.GrabCorpus(dc); corpus.UserSays.ForEach(userSay => { @@ -40,7 +40,7 @@ namespace BotSharp.Core.Engines.SpaCy }); trainingData.Add(new TrainingNode(userSay.Text, entityLabel)); } - }); + });*/ entitiesInTrainingSet = entitiesInTrainingSet.Distinct().ToList(); var client = new RestClient(Configuration.GetSection("SpaCyProvider:Url").Value); var request = new RestRequest("entityrecognizer", Method.POST); diff --git a/BotSharp.Core/Engines/SpaCy/SpaCyTokenizer.cs b/BotSharp.Core/Engines/SpaCy/SpaCyTokenizer.cs index b36e19d1..0fc22991 100644 --- a/BotSharp.Core/Engines/SpaCy/SpaCyTokenizer.cs +++ b/BotSharp.Core/Engines/SpaCy/SpaCyTokenizer.cs @@ -23,14 +23,14 @@ namespace BotSharp.Core.Engines.SpaCy List> tokens = new List>(); Boolean res = true; var dc = new DefaultDataContextLoader().GetDefaultDc(); - var corpus = agent.GrabCorpus(dc); + /*var corpus = ; corpus.UserSays.ForEach(usersay => { request.AddParameter("text", usersay.Text); var response = client.Execute(request); tokens.Add(response.Data.Tokens); res = res && response.IsSuccessful; - }); + });*/ diff --git a/BotSharp.Core/Engines/SpaCy/SpacyFeaturizer.cs b/BotSharp.Core/Engines/SpaCy/SpacyFeaturizer.cs index 1602141f..f456b8a2 100644 --- a/BotSharp.Core/Engines/SpaCy/SpacyFeaturizer.cs +++ b/BotSharp.Core/Engines/SpaCy/SpacyFeaturizer.cs @@ -21,14 +21,14 @@ namespace BotSharp.Core.Engines.SpaCy List> vectors = new List>(); Boolean res = true; var dc = new DefaultDataContextLoader().GetDefaultDc(); - var corpus = agent.GrabCorpus(dc); + /*var corpus = agent.GrabCorpus(dc); corpus.UserSays.ForEach(usersay => { request.AddParameter("text", usersay.Text); var response = client.Execute(request); vectors.Add(response.Data.Vectors); res = res && response.IsSuccessful; - }); + });*/ data.Add("Features", JToken.FromObject(vectors)); diff --git a/BotSharp.Core/Engines/TrainingCorpus.cs b/BotSharp.Core/Engines/TrainingCorpus.cs new file mode 100644 index 00000000..c2d9c69f --- /dev/null +++ b/BotSharp.Core/Engines/TrainingCorpus.cs @@ -0,0 +1,14 @@ +using BotSharp.Core.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Engines +{ + public class TrainingCorpus + { + public List> UserSays { get; set; } + + public List Entities { get; set; } + } +} diff --git a/BotSharp.Core/Engines/TrainingEntity.cs b/BotSharp.Core/Engines/TrainingEntity.cs new file mode 100644 index 00000000..8c73135a --- /dev/null +++ b/BotSharp.Core/Engines/TrainingEntity.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Engines +{ + public class TrainingEntity + { + public virtual String EntityType { get; set; } + + public virtual String EntityValue { get; set; } + + public List Synonyms { get; set; } + } +} diff --git a/BotSharp.Core/Engines/TrainingIntentExpression.cs b/BotSharp.Core/Engines/TrainingIntentExpression.cs new file mode 100644 index 00000000..1a8fa034 --- /dev/null +++ b/BotSharp.Core/Engines/TrainingIntentExpression.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Engines +{ + public class TrainingIntentExpression where TPart : TrainingIntentExpressionPart + { + public String Text { get; set; } + public String Intent { get; set; } + + [JsonIgnore] + public String ContextHash { get; set; } + + public List Entities { get; set; } + } +} diff --git a/BotSharp.Core/Engines/TrainingIntentExpressionPart.cs b/BotSharp.Core/Engines/TrainingIntentExpressionPart.cs new file mode 100644 index 00000000..d5cf5d2a --- /dev/null +++ b/BotSharp.Core/Engines/TrainingIntentExpressionPart.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Engines +{ + public class TrainingIntentExpressionPart + { + public int Start { get; set; } + public int End { get; set; } + public String Value { get; set; } + public String Entity { get; set; } + } +} diff --git a/BotSharp.RestApi/AgentController.cs b/BotSharp.RestApi/AgentController.cs index 2cea7483..49bc2de2 100644 --- a/BotSharp.RestApi/AgentController.cs +++ b/BotSharp.RestApi/AgentController.cs @@ -1,11 +1,21 @@ -using Microsoft.AspNetCore.Mvc; +using BotSharp.Core.Agents; +using BotSharp.Core.Engines; +using BotSharp.Core.Models; +using EntityFrameworkCore.BootKit; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Text; namespace BotSharp.RestApi { - [Route("[controller]/[action]")] + /// + /// Agent + /// + [Route("v1/[controller]/[action]")] public class AgentController : ControllerBase { /// @@ -16,7 +26,28 @@ namespace BotSharp.RestApi [HttpGet("{agentId}")] public ActionResult Restore([FromRoute] String agentId) { + var botsHeaderFilePath = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json"; + var agents = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(botsHeaderFilePath)); + + var rasa = new RasaAi(); + var agentHeader = agents.First(x => x.Id == agentId); + rasa.RestoreAgent(agentHeader); + return Ok(); } + + /// + /// Dump agent + /// + /// + /// + [HttpGet("{agentId}")] + public ActionResult Dump([FromRoute] String agentId) + { + var rasa = new RasaAi(); + var agent = rasa.LoadAgent(agentId); + + return Ok(agent); + } } } diff --git a/BotSharp.RestApi/BotSharp.RestApi.csproj b/BotSharp.RestApi/BotSharp.RestApi.csproj index e2d8172e..ed3204a0 100644 --- a/BotSharp.RestApi/BotSharp.RestApi.csproj +++ b/BotSharp.RestApi/BotSharp.RestApi.csproj @@ -4,6 +4,10 @@ netcoreapp2.1 + + bin\Debug\netcoreapp2.1\BotSharp.RestApi.xml + + diff --git a/BotSharp.RestApi/ConversationController.cs b/BotSharp.RestApi/ConversationController.cs new file mode 100644 index 00000000..98786113 --- /dev/null +++ b/BotSharp.RestApi/ConversationController.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.RestApi +{ + [Route("v1/[controller]/[action]")] + public class ConversationController : ControllerBase + { + + } +} diff --git a/BotSharp.RestApi/IntentController.cs b/BotSharp.RestApi/IntentController.cs new file mode 100644 index 00000000..9dbaea48 --- /dev/null +++ b/BotSharp.RestApi/IntentController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.RestApi +{ + [Route("v1/[controller]/[action]")] + public class IntentController : ControllerBase + { + } +} diff --git a/BotSharp.UnitTest/AgentTest.cs b/BotSharp.UnitTest/AgentTest.cs index 1792906e..1ea9d696 100644 --- a/BotSharp.UnitTest/AgentTest.cs +++ b/BotSharp.UnitTest/AgentTest.cs @@ -5,6 +5,7 @@ using BotSharp.Core.Models; using EntityFrameworkCore.BootKit; using Microsoft.EntityFrameworkCore; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; @@ -22,13 +23,11 @@ namespace BotSharp.UnitTest var agent = new Agent { Id = BOT_ID, - Name = BOT_NAME, Language = "en", UserId = Guid.NewGuid().ToString() }; - var rasa = new RasaAi(dc); - rasa.agent = agent; - int row = dc.DbTran(() => rasa.agent.SaveAgent(dc)); + var rasa = new RasaAi(); + //int row = dc.DbTran(() => rasa.agent.SaveAgent(dc)); } [TestMethod] @@ -37,38 +36,31 @@ namespace BotSharp.UnitTest var agent = new Agent { Id = BOT_ID, - Name = BOT_NAME, Language = "en" }; - var rasa = new RasaAi(dc); - rasa.agent = agent; - int row = dc.DbTran(() => rasa.agent.SaveAgent(dc)); + var rasa = new RasaAi(); + //int row = dc.DbTran(() => rasa.agent.SaveAgent(dc)); } [TestMethod] - public void RestoreAgentTest() + public void RestoreAgentFromDialogflowToRasaTest() { - var rasa = new RasaAi(dc); - var importer = new AgentImporterInDialogflow(); + var botsHeaderFilePath = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json"; + var agents = JsonConvert.DeserializeObject>(File.ReadAllText(botsHeaderFilePath)); - string dataDir = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}"; - var agent = rasa.RestoreAgent(importer, BOT_NAME, dataDir); - agent.Id = BOT_ID; - agent.ClientAccessToken = BOT_CLIENT_TOKEN; - agent.DeveloperAccessToken = BOT_DEVELOPER_TOKEN; - agent.UserId = Guid.NewGuid().ToString(); - rasa.agent = agent; - - int row = dc.DbTran(() => rasa.agent.SaveAgent(dc)); + agents.ForEach(agentHeader => { + var rasa = new RasaAi(); + rasa.RestoreAgent(agentHeader); + }); } [TestMethod] public void TrainAgentTest() { - var config = new AIConfiguration(BOT_CLIENT_TOKEN, SupportedLanguage.English); + var config = new AIConfiguration("", SupportedLanguage.English) { AgentId = BOT_ID }; config.SessionId = Guid.NewGuid().ToString(); - var rasa = new RasaAi(dc, config); + var rasa = new RasaAi(); rasa.Train(); } diff --git a/BotSharp.UnitTest/BotSharp.UnitTest.csproj b/BotSharp.UnitTest/BotSharp.UnitTest.csproj index 5ed76d0e..ca7277c4 100644 --- a/BotSharp.UnitTest/BotSharp.UnitTest.csproj +++ b/BotSharp.UnitTest/BotSharp.UnitTest.csproj @@ -9,7 +9,7 @@ - + diff --git a/BotSharp.UnitTest/BotTrainerTest.cs b/BotSharp.UnitTest/BotTrainerTest.cs index 4b006bf5..f7d25bcc 100644 --- a/BotSharp.UnitTest/BotTrainerTest.cs +++ b/BotSharp.UnitTest/BotTrainerTest.cs @@ -13,13 +13,13 @@ namespace BotSharp.UnitTest [TestMethod] public void TrainingTest() { - var config = new AIConfiguration(BOT_CLIENT_TOKEN, SupportedLanguage.English); + var config = new AIConfiguration("", SupportedLanguage.English) { AgentId = BOT_ID }; config.SessionId = Guid.NewGuid().ToString(); - var rasa = new RasaAi(dc, config); + var rasa = new RasaAi(); var trainer = new BotTrainer(BOT_ID, dc); - trainer.Train(rasa.agent); + trainer.Train(rasa.LoadAgent(BOT_ID)); } } } diff --git a/BotSharp.UnitTest/ConversationTest.cs b/BotSharp.UnitTest/ConversationTest.cs index 0452d544..c412c005 100644 --- a/BotSharp.UnitTest/ConversationTest.cs +++ b/BotSharp.UnitTest/ConversationTest.cs @@ -14,10 +14,11 @@ namespace BotSharp.UnitTest [TestMethod] public void TextRequest() { - var config = new AIConfiguration(BOT_CLIENT_TOKEN, SupportedLanguage.English); - config.SessionId = Guid.NewGuid().ToString(); + var rasa = new RasaAi(); + var agent = rasa.LoadAgent(BOT_ID); - var rasa = new RasaAi(dc, config); + var config = new AIConfiguration(agent.ClientAccessToken, SupportedLanguage.English) { AgentId = BOT_ID }; + config.SessionId = Guid.NewGuid().ToString(); // Round 1 var response = rasa.TextRequest(new AIRequest { Query = new String[] { "Can you play country music?" } }); diff --git a/BotSharp.UnitTest/TestEssential.cs b/BotSharp.UnitTest/TestEssential.cs index 885065c8..61f03cfc 100644 --- a/BotSharp.UnitTest/TestEssential.cs +++ b/BotSharp.UnitTest/TestEssential.cs @@ -11,9 +11,6 @@ namespace BotSharp.UnitTest public abstract class TestEssential { public static String BOT_ID = "6a9fd374-c43d-447a-97f2-f37540d0c725"; - public static String BOT_CLIENT_TOKEN = "43a0f48e3f1e41da822092e7e699426b"; - public static String BOT_DEVELOPER_TOKEN = "cd1e4685c6a04d7db1f59e6853fd597b"; - public static String BOT_NAME = "Spotify"; protected Database dc { get; set; } protected string contentRoot; diff --git a/BotSharp.WebHost/BotSharp.WebHost.csproj b/BotSharp.WebHost/BotSharp.WebHost.csproj index efcd6af0..458f02fd 100644 --- a/BotSharp.WebHost/BotSharp.WebHost.csproj +++ b/BotSharp.WebHost/BotSharp.WebHost.csproj @@ -100,6 +100,11 @@ + + + + + diff --git a/BotSharp.WebHost/Settings/app.json b/BotSharp.WebHost/Settings/app.json index 26bb0ac7..497ba711 100644 --- a/BotSharp.WebHost/Settings/app.json +++ b/BotSharp.WebHost/Settings/app.json @@ -1,15 +1,3 @@ { - "Logging": { - "IncludeScopes": false, - "Debug": { - "LogLevel": { - "Default": "Warning" - } - }, - "Console": { - "LogLevel": { - "Default": "Warning" - } - } - } + "Assemblies": "BotSharp.Core" } diff --git a/BotSharp.WebHost/Settings/logging.json b/BotSharp.WebHost/Settings/logging.json new file mode 100644 index 00000000..26bb0ac7 --- /dev/null +++ b/BotSharp.WebHost/Settings/logging.json @@ -0,0 +1,15 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + } +} diff --git a/BotSharp.WebHost/Settings/swagger.json b/BotSharp.WebHost/Settings/swagger.json new file mode 100644 index 00000000..8d3b771c --- /dev/null +++ b/BotSharp.WebHost/Settings/swagger.json @@ -0,0 +1,19 @@ +{ + "Swagger": { + "Contact": { + "Email": "haiping008@gmail.com", + "Name": "Haiping Chen", + "Url": "https://github.com/Oceania2018" + }, + "Description": "BotSharp is a chatbot platform written in C# (.net core), and it's developed for enterprise usage.", + "Endpoint": "/swagger/v1/swagger.json", + "License": { + "Name": "Apache License 2.0", + "Url": "https://github.com/Oceania2018/BotSharp/blob/master/LICENSE" + }, + "TermsOfService": "http://www.apache.org/licenses/", + "Title": "BotSharp API", + "Version": "v1", + "Stylesheet": "/swagger.css" + } +} diff --git a/BotSharp.WebHost/Startup.cs b/BotSharp.WebHost/Startup.cs index 43fd69d7..509ac10f 100644 --- a/BotSharp.WebHost/Startup.cs +++ b/BotSharp.WebHost/Startup.cs @@ -7,7 +7,9 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.PlatformAbstractions; using Newtonsoft.Json.Serialization; +using Swashbuckle.AspNetCore.Swagger; namespace BotSharp.WebHost { @@ -22,6 +24,8 @@ namespace BotSharp.WebHost public void ConfigureServices(IServiceCollection services) { + services.AddCors(); + services.AddMvc(options => { options.RespectBrowserAcceptHeader = true; @@ -30,6 +34,15 @@ namespace BotSharp.WebHost options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }); + + services.AddSwaggerGen(c => + { + var info = Configuration.GetSection("Swagger").Get(); + c.SwaggerDoc(info.Version, info); + + var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "BotSharp.RestApi.xml"); + c.IncludeXmlComments(filePath); + }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) @@ -39,11 +52,32 @@ namespace BotSharp.WebHost app.UseDeveloperExceptionPage(); } + app.UseDefaultFiles(); + app.UseStaticFiles(); + + app.UseSwagger(c => + { + + }); + app.UseSwaggerUI(c => + { + var info = Configuration.GetSection("Swagger").Get(); + + c.SupportedSubmitMethods(SubmitMethod.Get, SubmitMethod.Post, SubmitMethod.Put, SubmitMethod.Patch, SubmitMethod.Delete); + c.ShowExtensions(); + c.SwaggerEndpoint(Configuration.GetValue("Swagger:Endpoint"), info.Title); + c.RoutePrefix = String.Empty; + c.DocumentTitle = info.Title; + c.InjectStylesheet(Configuration.GetValue("Swagger:Stylesheet")); + }); + + app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials()); + app.UseMvc(); Database.Configuration = Configuration; Database.ContentRootPath = env.ContentRootPath; - Database.Assemblies = new String[] { "BotSharp.Core" }; + Database.Assemblies = Configuration.GetValue("Assemblies").Split(','); } } } diff --git a/BotSharp.WebHost/wwwroot/images/BotSharp.png b/BotSharp.WebHost/wwwroot/images/BotSharp.png new file mode 100644 index 0000000000000000000000000000000000000000..defe10f9c253227fbc0d4945c8cd095269e00bca GIT binary patch literal 11445 zcmX|ncQ{*r*mvx$wxV_^wQAR{O{qOgepc;Gh`qPkd#{$7Mb(JCY6hXUptc&ZV|&u) zx!(7WoRjm-b#m@=e?Is8-mzL5%0&3I_y7QaNL58a2LM2WqrSs%u~Em^7`qbG3C~T% z*b@LCApiG41LWpE2LSLt*vrdnY1z4gTs`ev-I!G6<(b?(Ty5-~tN{R@r2<{BQ5up; zdJSp)%s_78q#?^G6u`n-gF8%OTuPD(u!tZbdp8&vgKt1VNt&;sKM*#HuTl`RQOwb5 zD;pQ{F<#&F?J?s@#m_)L#L>~+{9VUx{_g#R@8q)(QZn|Gol*yYm`+7Q z3DA;t0K>d`!xVtw=YV?MAD{36=>UL}Z-5*Npo$1^c%dqd1z4y|TcHLll)k9M1tg#W zayXPKMgurn}cG&D=y>AFBF%id_So?m9TPyJ zF^O0*+uokTa2rCa_v&`6GyyCb0PNOofP%|-#UJsf{BGiX-`>AtC@j$$mZX1yPe5?Q zW?9ntW;0&;N$`*BdVJ6o>et6*zY~Ca?z^1Yp0e-bIhqH z=ok$>p4e#G8}KgZoaZwwK?;DxR!G1X2>_&Z-z2@`LIXgvzH9;j9edABzok>F|H1_T z6pBM%*URD%_EOaJ5a;*Ocl1!BTVN}^BYfE-Ng{{674ibV2!o!pu#wE947LOsdOk7}@z@^Sf#ALBh5lRjD z!n7Ylq0KTl?C}M?QqCa-sKR>2<3S;oVEXPhd3l&gAnrb{LzzE4v{4)5H@ermwr`BI zaleW^VIZMrz>v&RM;L7rgH%X!X$4Ge&kF3)5A|^LWQ+Y`|lDegV&&-xAph}?XsIsiW z^F{ZI^fZZmzB>Csvh&F57H(rm4O3Q1OY*a1&D6V*{;d`Y@xho4b-dD-I$zSs-V0mH zY-4^c5|GO&uF{597XHSqiV-jRsOntot;MGsT}dwFmCFXrqmm!{!c#Uom1}QnkF?|4 z2SM=Q;S7pdQ(4oFdpP^M`{5U0LZT?5@F5jT4jM-qf0~NtEi`;N>g8B7SvkXcZ{`K) za%{7oWxMJdy}o)KK$$X1mLZ;DkP(!zTcxM(sV_6@TScH(t^ch0KZC$>CH)^-o0WLK zsj6oy>Gj(yMd~JWz&c4tBeW`D3WX}md9_r|)T^XBtc*Om9IvZ=92u_@SbhoTYxYFIxJTg-ny!8}1U;m?D? zBg4}$=TK`?8&oU0#QSiV@}=`d*(LQ~#2f;~DEdYSS0tIniT|zD$#}BWo@2IsE9@lV&o|OB zJ4niaT^UTZ>{ToKakTBGun)DgO^xdd%Nn6o>lH^y3rl-})VNa4C!Ce z=tX`-(Ou=e_=Xit+veG^E*`C6cg_pf%7F325(P~?{#?@Q6M4G@?kME03YT=Q>QI9fDqxVX}YwtRP-N9od{N0D2sH=gIqlunWAu(BqdIxS) zi9zsd>I}0Qx0-Kt*Y!%RI~#@?X0rj8zRpWatM6Mzj}BB0z8tvJAdS1fzwdOAot=t0 zA*!W2P1vS0bAG=HD)Do;OoTQ;N1+(P7Q#m+@LR^>fj&i|2-9El1?vvf_eYI8|;J>N0S2EGR(hptB z32wQ>Jy7xGnilW&s^KYfE|x0kMC^SoE1>_6Ub(B~DG0&8Y2`H}oMc#7T)-i9db1Ul zwpsD1qOd?iM(TIYiZ4?AKF1NL4eYd)pDdK21|6%nm?1~bS9gDjF-uCr5(}o_r5Ht9REPHty6WjqVpt2yWsh zyX$-_π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 literal 0 HcmV?d00001 diff --git a/BotSharp.WebHost/wwwroot/images/BotSharp.psd b/BotSharp.WebHost/wwwroot/images/BotSharp.psd new file mode 100644 index 0000000000000000000000000000000000000000..db98df7bf8e863fe03c11a3c7a9ae9fab6fb6368 GIT binary patch literal 128892 zcmeFa31E{&^FO{xOG}|ZxNms4L7{!x(u*@tuF4fD2na|@njZEFY09Y(1Vu%qUL1lF z1wr6Nst5=uMCCpMNIB#Pm)sDbTrKVM|I9u~+Hz=pUw_~C_@|IOyED79v$M0av-`~R zB%-S(hAEi*=Z(vL#uO)5S>`2!M#o2VjqdAB7{)5qQ@qH$>Ne|HPstemGmdM9qcq2EB=gk)W0T;tB2%5@mmZd|G%Rd0$F#-*mDWwaaDv2ko%`Y3%n zqzN3@Sl~rW$sHSaA%rlbuSSSUH|mAZfRHviF(^m~3kwKp8yXfC)LIA@gMtG^{10mr z)V5t{Si9hG!THy?Q#qtM7~|sG4d~Xx*&K2m8z-7fhIWC0W56xaEjT=)#?muV0QVs5g z(lP>g9|Lshse$8S4S_)cVxXHcDt3TO+C>@lv8Ht6!1VN#PIAvRiRq^FjKp+<5ET<9 zv>cq27MDIYqg98%M~fG=UqngYE!L#(1o=d?5yK&zfuh(hIJ8|z+csioJ5ek~L@xOV zjlLL*xL8x{V^qT1g+{gu3Mo#dMA=8_q{k)2k1rLKqLNM;9Rf+n#e~jBl;rgY{Lco% z;1cAMhs2G3d|=$Dc2Vgm>Bhe4ar#an9Ri;OF4plPbaYgd#+V+Tl%nsHF`#ExA-a21 zSWskGSexL0pyFhTm3tzcf%NJ|jKTsM8nMKA95LDdL;A)h{+x-zg?B)@UfsY7wf4)2EUkzMn#ZqaGz84|z(` z|GWP5ANa3z<_Y!xO+D%QuXW_{>VKgh@;H@LyyEN-sgnBow@v0aoqHA=GL0$Re#hwo z^(p#PeVQo)b2zA^agEcpi%&PE#+o|C8Vo5(x>&N`fn(C*oL1Sb^&J9>iaHhZZ{r#! zyKi4N<4;@>Qd0w;w31|)x{tvk<6N|!STlnrcc5!-cOL^e6s=q|v3cw5qSG==v1vMe zbhl0b1SBQJwd>ZlYq#!QyG4byjR@}^5fl^|B?fg3@7BF-xA4gDkf3gSndsZMc-5jQ z>m=JPU6)Cscan_**>JIYNMuyEuEC))*{*HHu2E5u-6Es9bn6k+Bg#d#Sk=eK_BSTM zuZT@4R))C#E99R*;<09WC1qgM9beMmaI+etA6*hklBAXAubNdpg6(2;q<5Wkw9M<{ zIs}%07O_=iO63Acj}O|POZTy=Pp3aNQJ?llZh}mTmwGypjP!WZ*jS^!O9J%Z&%76z zV#z9xlKy+w0l7uz0A$3D`Pan%=X2&?5&t9p)xSslr0H_Yy2RMD1btkmK$pV00Hqr- zc^pg5B-iABWad5D)XGpe@Yp*9x;GDx%}e*J`8yMjcJc3|?WW~v#4U=_Bs}6Ojg;JF zJmPYTqBIGQxJn}>cNvek+@dH=!XvKINXcEsBQCcnN|W%2t29z_m+^?pEsD}4JmM;i zl-y-J;&O|kGzpKmN+TtA8IQQ!q9{$mBd*d&$z8@HF1IL3lkkYEG*WVx@rcVUiqa%J z;wp`l++{rCa*Lug36Ho+BPDkkkGR~TC{4m6uF^=!UB)9WwcNvek+@dH=!XvKINXcEsBQCcnN|X3Qag{52 z99N%)XK=^jVO##RZae-Y?_qqa@R6SiE^jaJVC{sW;Lyg9Ez{83>Tvm|Ou5L8iyY=uMf1 z{-a*j0a+%oQDXRvjg!-;GAn0rc_XG*gcz15#)--G5zE;)Ex`2V|s}I9xL>MLob>yxbVQ4i7@%NnJeE z?9>BIf+oYI2b8A5xDwl}k3L=|^GLG;@woDnnvKz=$Z(BOryfca_@7E=Og9Y1Ge{cJ z$)vOdm-s3YVgPvRnr3N*B{-}2yD-E;F?aIE7rRKF{+f@i{-Yc)lE!q(3K(3hq+lIA^up`3Ah!ZJzhz-}sVg zx1hOznI+FAq?Eku9S-fq0^{R>Nx`=dhbWwo&*y&Ph6DqnU@zj^Rfc+_U^LU55Ki+x z@{Ac=T+6%{eS2LbbWy%|>R-WeSrBP@ae;#8=miEY-ed`j9O9)=I3-TJQwf@cHF=$~ z9OASbN;Qb#0?(N#2`O&M zSXyQZ*;wkF58gPC7MJmeCDECJfa7e^^mFStfRD@(*0pFZ;k6Kq4RB8t&YDjK9+1^% zypYm|CcC0UJ7qWy;41j|@=SEMVr}^*7}GNiB|tvu{2@-49q%4P)a9o#L8C%!rYXIr zK22|=Cn5o0^c<_Ra5=d!K?oBqFF*gU`|pJ(ic2hCT=*p+eKQhDE^$7wDW-w32_;HZ z)ag@F=qc#vj9vr#_HmiivMz9m!hVVA#tB_gk`i1iUM0Eny1iZuKU2B^&OwI0xD73r0%Q9a)PEE= z&X2*%W7rcPEzW0KOKOObom6&q@U%QnD{(OFuYa#TNonay%*Rx$pY+azAwypjeD^~A z{V?mG=&`yCL*JMlCH&L zIVO`7->VPOZ;VOOk45@dq?@K>rY0dxmbF@{J{FVFn`GA1q}L@PEh6o295?_gv3Cc? z%K9f1OOGm+HbDbXmPMr-#`7@|TIyN}c-={a&`UoyMQ<{-(cmpEvBo&OVHSc z6Yn$CVpSe{X$1$%Uw?=!R_>3IG`2GS_Vawq6g74i!HQ}Y!P38gZN@6*l~n{AHJ7oq zuQOKbSP`tL1@^2}@aXTT`j|1R;RoQbS5BPl^3aMXZ-f-ciIhSJWJunc^kN~{{I%^I*KtR=jbU>45WGd1hZ zo@4#lKsJ=U#B?l?r7|NM%U)qq*c)sH%VHn1PuK#sh%IGbvv1j2_5=HgZDqTdjU8gY zF*`fYt}q9?%ktq>_$n$Wsw!$L8Y-G8o>c@ZA{3nz-4%Tl0~A9QT1A2)O_8a1MKM(| zL-B#)6UFC>rHXG9>l8mJb}05Mjw((oE-7v)@|0dme`PggePwfHpfW<)McG?9P&q=G zpd787pq!?BPdP{Vh4LTDHOilqyOf8NcI6f29WUlp-m8XJBd<1I5nfSV{k>lFiuW>l zP4ar%YnIm+USE5y_uA%l(97<1)$4(`k9SpX!Mlxjd+%P}gS>U#qrE42zvKOh_gCI) zyf=Fv^giwF@GdM)X+{zi+Is$@dN4xxWAK-Q;_~ z_q^}@vgOM*EE`<5N7)z4rj>oI?5wiO%5E%spzMXR`F<+DW`6Db`uoNCjrW`Bx5#h3 z-#)+de);7pmupe3W4VFlUM@GK+?;Y>m)lbAc)8o<%a?ClKC=At<&(;r%g-sFU4DD{ z)8!xdSMh(wKgxf&f2RL?{!9F={zv_9SEx{-c?ETa7b}=5yjNjqglvuTry0T`Ij)X+ou0l~z^SSLv$CPt{x%rHWNeQq5DXQyo^_ zsa&;kQ04xWQ!Bqyd0FKhl`mHDthv^ zdcK-ZwHDQ)tG!%pMzs~y_EvLLuTs5j^%ts-t3I##kJarpylOPB5nUst#>^Vu*2t-m zSF?W2E;aQv->Ug_%>y;>)v8-dT}xlTIcVwQjY#?d$65zFqg*y2t7%>pfF%K)s3e7S`Kc?@s*&^?TMg)Sp}bm-<&5 z)M%h?@N$EX8feVQ-(dUi!Hp*|@ zqVb@{uQguT_(YR(O(L4aH~FZ^&rKXn8#e9R^p&Q|n;vWC*DRu0Vzb%Jwl%xgyhZcD z&8IhC+x%jSS}memOlYyZ#qpLET6S(Zy5$!we{JQ{Dxy_#t4~|mo>4v%`b^?8^PbuF ztn%5gXOo`&^x6Hb%e0Pco!0t`)`#2px9QSmOq=CxP6yNo=o9c-z}kT8flUKn417Ou zTVSCWDyE2w#NUFd1U(n@TG0BSTfxr+>w@P6{~A&uq({i)knclowtcp(zU^mikAzkY z?Hf8h^ykomu<$Tr*w(|j;I!)iFhYsdt{l&u91@?e~5h0F07rY-M8&- zv~SZsx&5;C7dy1*pzpA#!`Y6FJH~eWyraF7&`I0L(#hVrQRmpsUvxgBZlaD;FIHdZ z(yGhLUH;MKdRMWlvFqxt_oCWGy&7fh=GCodx3|0P?Ovt(pzfb^KiQ*kkAxn}dpLTA z_MF($+N(^j-o4)MbvU|yv@UvSwBxz(=U#nob8r9NF}*+OeWuSdeT;q9_f__NuJ4C^ zkN0cVFRkC&{;Yp={}210(6rEu)@*p*=XuTZ^Pc~GK+u3!25gI|8Z$CxSb_;m+HKf^3snZD~*gDxk_6`J6O9+`!KeD>=&_jMn#XBKgywt z(#_UgiBrdY6n9DAQU8JdLVU;g58^K-bWHd#;ZkDf#94_~lcJJ7NxJ!Rua_6Rd@s3w z@{(jJWpK*M)Uv7C)OBf9(vs6Qr#DC+m%iWdtl0Z zi&+bO7LHl?`=S>XZTm9f%cYC!ES|BrU`g5%`&R?L+PpM;>C$EOmd#wQT%Ni7(m#g( z!?vQ^itoQ}^Y!N|Ypk4+&9XDIFMp%`CgZ+^XUZYquevM;o z;#&LnL%-j@?zwe8uW!G8^@e~AOMYnd!@M7>|2T7FxsB5{N}DEZx??q1ul|(q)7hU# z{`}i7Lw@;n^YfecZt1;c`_>*?f7#Y$+otUuxBsxC-HvrTBX+Lc6}D^5?$F(<_k`|Q zy*F&{ntkE>zPCl%*6;7If8&A92Yx!(?cmm5qkr9XsNbReIfHVJ93FnyekAV5#iJ=l zZyp>twx?Uz}=nYNb8Q{^RLxr+1%;IrH0D-PtSWGR{3bKkfGl zzt6hR@WRrI!54qH)Z>!v^03S2uNbc6Uwz|R`C1F6ljg}&+W4^&z|HDH#07Q;p*9wc=jZoJ&9*e;@OjU_9UJ?iDysp|EE2PbdCA* z7kiJ4>WiJmbykt*SezM-kwW^7O=JFL%a-*k>+k31U%7m_@|CMs^7pS)y;jw#)vH#m zRoS2aIWKbN(QieC^5rX3te~n`QB|#C#fsJFt70{|O6AfJkgTk7S!|0eUW&#{Sy|y# zSs|UkoyBs}W<_UkSq4X*_yfcA=fxCC?=n8VW&O&PS3HWu{d6xEQpFVB3NNL%vW%}! z*)m@KAwX94@@`Zms7#mVW2-hEJtf$u+WVh>)3r&{>H~fn71GxD+WsitW*@{jPT$mJ zgx2`t+o{dFeK;_#`_BtaVKom7I-|d}YT7RcGtb`c(c+^;uYdRP=3md{ez|(fq4RfM zh#&LDti@}#=KOv)yyxJAvD0TSS-b7{zYsPgS6lT(&akKDr4q6nk zARS}=UcAl9tTVeasP~Ha&c0usJC`$RYw)u{;)Tj1(xyIKyL|blc~{B^>iO(*}BBC+kQKVC8QPQucJGa&)f2R{4lnCa_&I(cB|FGFse7#6c_m#$`n z?#=b9YW*+&2F&BHk>ht=OQ; zy1zJPR>Z0X5xX64P5LNq(%^N2R^7h2ep1M{#u2OEwJDa*KbxDpV$=M4&p!Lk!*|yc>v_!x zi1r_MwqSf_=M()U7SSm?vv<9d@4xfx(#7Ff^}0Qj!S75nne9{ePI*NU|R zPA%#^#O^y||}ABeeCx`me2DuG(6WbsNwip;l%)g_y?iM0(9}VPwk?ki?&kP?!|fwq=A>OVoe4b={P~!u z&lKKDuh=bn@3q@hVfnn=ZN2i2@4Q$yaox2#$6)=MlZZ^o*=`^t{m;b$GK zn^U_x!4Zj}rO-|?P@9Gp8^Itr|D(vmN zPl&xEu@$v{y1sewhSv=ZqS#w`o%`jiIQ5TpKJUHtQJ3jM_G@n6DZAoSZoTuvE~j<= z@<7KJiM`xr;qOyZe{pM0C% z8hWbH`T@~R7wRWVwmXBizB*=m;N@z%sb7ZHeC6uc!XAsi-ZTDiPWi(9Ip3Z-x-xfL zK}xwzm*=c}C9LM0UH2OI|21#;zIV=@KL7pXy}c?edNpml=;wH8?!nQ8yAIy`X8ZI( zF?CKqv~-kM?(BI3UQRu<-aaDcrGvVj%`C6oT{HQE^*0{eoGP)=UrP*K`|yR0jb;RN zDSP&*q}A5cKZdf)fiVoPK%WsiO#2ZDSDH~H$5nVOw# zw=GIr6@RkH=)9l@%eJXkeoa5Clk@tq zS6{docG@@o{Mxkc@BTI-VU~D#ti*mEDzPpvXGH2|D7-K0eyW_)^St3f>#Dy;&e`7M zix$`W6u#5_rs2nOXE%O1G4H)WD+@CYN^IGr3lcl<^3}mLGgjoSz4Q9fGOr(*TldW= zd(zvV+$pi}U$?Eg-8rK$G~W2xR|%Utjo)1Bz9YS6`hr~j`Bl9i{1DT4@}Ya3(C%w@ z-+JcAiQZlTn_?Q=9dfdds%+tg`Zp5p=8PPcxBso_G0T4WX6^aP?7Qhf3wC~Us%OUJ z{Vf|!ZF<4lc-#*gN8SiCW<-qs<@iTue|e$hshamDkKeg#>~9;_{krqb#`BV4&Nk0{ z@zm{+KhF4e_>Ds^%@`w2*6j9#gC4kJEN~>2(S0N>P*3< zN^_@XZ42@{zda)1vxLA(*Ec_WfBb@#wd)22eS`iExl-xpHP_Jlb*Z`Y)4$E#{bJc; zzYnzCeE3B;`qDR}^Ux;kuQUko{~#wX^M`R0-aD00==IH*mKSnw9ch$*d}yWnBO9L_ zc6iV2$j)P@`%nJqfy6GfYWl&Tx|gGyeh?$=zw_)0eQ2i(bM&c!qi-c1A3Qtq`Zrs* z&7HU-W9Gc~&iv?gC7{c~FZ2<$GT*IUDerXk4TV$Z|L`FBm4NDg`_@&KSWSubG)#*8 z;MS;Z`QL;{tYQEB*Q@xpYkvHcYW=CN?w<<@Z2E4!-v=Hn(4>=ubl*bx3xLfPjG+nbN_|Gv+- zFo~5*4>~Ym&xwFj1J*BFz2uT_Ti>7F^55?DYeK_aE5?4>xpUpGMy+j8`@puuF8lWw z@&+9_wP)hsxnF;HxkuD*bKifru)>`gx}SC%5(=6hnb~<)k0E0Xg(N|v>J9zuWYs;?|^jW=U^19Wk;WsK=OU=-AK3n7MGgrriU&}vn$m`Qy zt52Veu@uhyA^gOp3BzhsOgXUS=h&_TKK85Mq|%j+gP+|M6**^zahh&(Y~?K-796VA zXZfXugN)bxmj_&)f4hR-tXS!fdp#f90mQeGW!I(6IVl!5???16 z-+A)U)^|Ea1m0cu&H6D|W^xKIf48o|%tJ#D-b_s$a%0DjH^PS0Dx3T)3wmSQ8=KPi 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 literal 0 HcmV?d00001 diff --git a/BotSharp.WebHost/wwwroot/swagger.css b/BotSharp.WebHost/wwwroot/swagger.css new file mode 100644 index 00000000..877e3e72 --- /dev/null +++ b/BotSharp.WebHost/wwwroot/swagger.css @@ -0,0 +1,3 @@ +.topbar-wrapper a span { + visibility: hidden; +}