Replace Articulate API, in progress.

This commit is contained in:
Oceania2018 2018-09-27 19:49:43 -05:00
parent e591a4965b
commit d96febbc22
40 changed files with 6273 additions and 17 deletions

View file

@ -5,7 +5,7 @@
<IsPackable>false</IsPackable>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA;ARTICULATE</Configurations>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>

View file

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Configurations>Debug;Release;RASA;DIALOGFLOW</Configurations>
<Configurations>Debug;Release;RASA;DIALOGFLOW;ARTICULATE</Configurations>
<Platforms>AnyCPU;x64</Platforms>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageIconUrl>https://raw.githubusercontent.com/Oceania2018/BotSharp/master/BotSharp.WebHost/wwwroot/images/BotSharp.png</PackageIconUrl>
@ -24,4 +24,8 @@
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>TRACE;ARTICULATE</DefineConstants>
</PropertyGroup>
</Project>

View file

@ -7,7 +7,7 @@
<Platforms>AnyCPU;x64</Platforms>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<ItemGroup>

View file

@ -6,7 +6,7 @@
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
<Platforms>AnyCPU;x64</Platforms>
<Configurations>Debug;Release;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<PropertyGroup>
@ -50,6 +50,11 @@ If you feel that this project is helpful to you, please Star on the project, we
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>DEBUG;TRACE;ARTICULATE</DefineConstants>
<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Colorful.Console" Version="1.2.9" />
<PackageReference Include="DotNetToolkit" Version="1.6.0" />

View file

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class AgentModel
{
public int Id { get; set; }
public string Status { get; set; }
public string Timezone { get; set; }
public string Language { get; set; }
public string AgentName { get; set; }
public bool UseWebhook { get; set; }
public string Description { get; set; }
public bool UsePostFormat { get; set; }
public bool ExtraTrainingData { get; set; }
public List<String> FallbackResponses { get; set; }
public bool EnableModelsPerDomain { get; set; }
public decimal DomainClassifierThreshold { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class DomainModel
{
public int Id { get; set; }
public string Agent { get; set; }
public string DomainName { get; set; }
public bool Enabled { get; set; }
public bool ExtraTrainingData { get; set; }
public decimal IntentThreshold { get; set; }
public string Status { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class EntityModel
{
public int Id { get; set; }
public string Regex { get; set; }
public string Agent { get; set; }
public string EntityName { get; set; }
public string Type { get; set; }
public string UiColor { get; set; }
public List<EntitySynonymModel> Examples { get; set; }
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class EntitySynonymModel
{
public string Value { get; set; }
public List<String> Synonyms { get; set; }
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class IntentExampleModel
{
public string userSays { get; set; }
public List<ArticulateTrainingIntentExpressionPart> Entities { get; set; }
}
public class ArticulateTrainingIntentExpressionPart : TrainingIntentExpressionPart
{
public int EntityId { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class IntentModel
{
public int Id { get; set; }
public string IntentName { get; set; }
public string Agent { get; set; }
public string Domain { get; set; }
public bool UsePostFormat { get; set; }
public bool UseWebhook { get; set; }
public List<IntentExampleModel> Examples { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class IntentScenarioModel
{
public int Id { get; set; }
public string Domain { get; set; }
public string Agent { get; set; }
public string Intent { get; set; }
public string ScenarioName { get; set; }
public List<String> IntentResponses { get; set; }
public List<SlotModel> Slots { get; set; }
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class LanguageModel
{
public string Text { get; set; }
public string Value { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class PipelineModel
{
public string Name { get; set; }
}
}

View file

@ -0,0 +1,38 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class SettingsModel
{
public string DucklingURL { get; set; }
public string UiLanguage { get; set; }
public string DefaultAgentLanguage { get; set; }
public string DefaultTimezone { get; set; }
public List<String> Timezones { get; set; }
public List<PipelineModel> DomainClassifierPipeline { get; set; }
public List<PipelineModel> IntentClassifierPipeline { get; set; }
public List<String> DucklingDimension { get; set; }
public List<PipelineModel> EntityClassifierPipeline { get; set; }
public List<String> DefaultAgentFallbackResponses { get; set; }
public string RasaURL { get; set; }
public List<String> SpacyPretrainedEntities { get; set; }
public List<LanguageModel> AgentLanguages { get; set; }
public List<LanguageModel> UiLanguages { get; set; }
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Engines.Articulate
{
public class SlotModel
{
public string Entity { get; set; }
public bool IsList { get; set; }
public bool IsRequired { get; set; }
public string SlotName { get; set; }
public List<String> TextPrompts { get; set; }
}
}

View file

@ -7,7 +7,7 @@
<Platforms>AnyCPU;x64</Platforms>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<ItemGroup>

View file

@ -23,7 +23,7 @@ Naive Bayes Classifier</Description>
<PackageReleaseNotes>Added Penn Treebank tokenize standard.</PackageReleaseNotes>
<PackageIconUrl>https://raw.githubusercontent.com/Oceania2018/BotSharp/master/BotSharp.WebHost/wwwroot/images/BotSharp.png</PackageIconUrl>
<PackageTags>BotSharp, NLP, NLU, POS, NER, LSTM, CRF, SVM, Tagger, NaiveBayes</PackageTags>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -40,6 +40,10 @@ Naive Bayes Classifier</Description>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>TRACE;ARTICULATE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>

View file

@ -0,0 +1,74 @@
using BotSharp.Core.Engines.Articulate;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace BotSharp.RestApi.Articulate
{
#if ARTICULATE
[Route("[controller]")]
public class AgentController : ControllerBase
{
[HttpGet]
public List<AgentModel> GetAgent()
{
var agents = new List<AgentModel>();
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
var agentPaths = Directory.GetFiles(dataDir).Where(x => Regex.IsMatch(x, @"agent-\d+.json")).ToList();
for (int i = 0; i< agentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(agentPaths[i]);
var agent = JsonConvert.DeserializeObject<AgentModel>(json);
agents.Add(agent);
}
return agents;
}
[HttpGet("{agentId}")]
public AgentModel GetAgent([FromRoute] int agentId)
{
string dataPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate", $"agent-{agentId}.json");
string json = System.IO.File.ReadAllText(dataPath);
var agent = JsonConvert.DeserializeObject<AgentModel>(json);
return agent;
}
[HttpGet("name/{agentName}")]
public AgentModel GetAgent([FromRoute] string agentName)
{
AgentModel agent = null;
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
var agentPaths = Directory.GetFiles(dataDir).Where(x => Regex.IsMatch(x, @"agent-\d+\.json")).ToList();
for (int i = 0; i < agentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(agentPaths[i]);
var agentTmp = JsonConvert.DeserializeObject<AgentModel>(json);
if(agentTmp.AgentName == agentName)
{
agent = agentTmp;
}
}
return agent;
}
}
#endif
}

View file

@ -0,0 +1,57 @@
using BotSharp.Core.Engines.Articulate;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace BotSharp.RestApi.Articulate
{
#if ARTICULATE
[Route("[controller]")]
public class DomainController : ControllerBase
{
[HttpGet("{domainId}")]
public DomainModel GetDomain([FromRoute] int domainId)
{
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
var dataPath = Directory.GetFiles(dataDir).FirstOrDefault(x => Regex.IsMatch(x, $"-domain-{domainId}.json"));
string json = System.IO.File.ReadAllText(dataPath);
var domain = JsonConvert.DeserializeObject<DomainModel>(json);
return domain;
}
[HttpPost]
public void PostModel([FromBody] DomainModel domain)
{
}
[HttpGet("/agent/{agentId}/domain")]
public DomainPageViewModel GetAgentDomains([FromRoute] int agentId, [FromQuery] int start, [FromQuery] int limit)
{
var domains = new List<DomainModel>();
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
var agentPaths = Directory.GetFiles(dataDir).Where(x => x.Contains($"agent-{agentId}-domain-")).ToList();
for (int i = 0; i < agentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(agentPaths[i]);
var domain = JsonConvert.DeserializeObject<DomainModel>(json);
domains.Add(domain);
}
return new DomainPageViewModel { Domains = domains, Total = domains.Count };
}
}
#endif
}

View file

@ -0,0 +1,14 @@
using BotSharp.Core.Engines.Articulate;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.RestApi.Articulate
{
public class DomainPageViewModel
{
public List<DomainModel> Domains { get; set; }
public int Total { get; set; }
}
}

View file

@ -0,0 +1,51 @@
using BotSharp.Core.Engines.Articulate;
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.Articulate
{
#if ARTICULATE
[Route("[controller]")]
public class EntityController : ControllerBase
{
[HttpGet("{entityId}")]
public EntityModel GetEntity([FromRoute] int entityId)
{
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
string dataPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.EndsWith($"-entity-{entityId}.json"));
string json = System.IO.File.ReadAllText(dataPath);
var entity = JsonConvert.DeserializeObject<EntityModel>(json);
return entity;
}
[HttpGet("/agent/{agentId}/entity")]
public EntityPageViewModel GetAgentEntities([FromRoute] int agentId, [FromQuery] int start, [FromQuery] int limit)
{
var entities = new List<EntityModel>();
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
var agentPaths = Directory.GetFiles(dataDir).Where(x => x.Contains($"agent-{agentId}-entity-")).ToList();
for (int i = 0; i < agentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(agentPaths[i]);
var entity = JsonConvert.DeserializeObject<EntityModel>(json);
entities.Add(entity);
}
return new EntityPageViewModel { Entities = entities, Total = entities.Count };
}
}
#endif
}

View file

@ -0,0 +1,14 @@
using BotSharp.Core.Engines.Articulate;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.RestApi.Articulate
{
public class EntityPageViewModel
{
public List<EntityModel> Entities { get; set; }
public int Total { get; set; }
}
}

View file

@ -0,0 +1,141 @@
using BotSharp.Core.Engines.Articulate;
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.Articulate
{
#if ARTICULATE
[Route("[controller]")]
public class IntentController : ControllerBase
{
[HttpGet("{intentId}")]
public IntentModel GetIntent([FromRoute] int intentId)
{
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
string dataPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.EndsWith($"-intent-{intentId}.json"));
string json = System.IO.File.ReadAllText(dataPath);
var intent = JsonConvert.DeserializeObject<IntentModel>(json);
return intent;
}
[HttpGet("{intentId}/scenario")]
public IntentScenarioModel GetIntentScenario([FromRoute] int intentId)
{
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
string dataPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.Contains($"-intent-{intentId}-scenario-"));
string json = System.IO.File.ReadAllText(dataPath);
var scenario = JsonConvert.DeserializeObject<IntentScenarioModel>(json);
return scenario;
}
[HttpGet("{intentId}/webhook")]
public void GetIntentWebhook([FromRoute] int intentId)
{
}
[HttpGet("{intentId}/postFormat")]
public void GetIntentPostFormat([FromRoute] int intentId)
{
}
[HttpGet("/agent/{agentId}/intent")]
public IntentPageViewModel GetAgentIntents([FromRoute] int agentId, [FromQuery] int start, [FromQuery] int limit)
{
var intents = new List<IntentModel>();
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
var agentPaths = Directory.GetFiles(dataDir).Where(x => x.Contains($"agent-{agentId}-intent-")).ToList();
for (int i = 0; i < agentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(agentPaths[i]);
var intent = JsonConvert.DeserializeObject<IntentModel>(json);
intents.Add(intent);
}
return new IntentPageViewModel { Intents = intents, Total = intents.Count };
}
[HttpGet("/entity/{entityId}/intent")]
public List<IntentModel> GetReferencedIntentsByEntity([FromRoute] int entityId, [FromQuery] int start, [FromQuery] int limit)
{
var intents = new List<IntentModel>();
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
string entityPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.Contains($"-entity-{entityId}.json"));
var entity = JsonConvert.DeserializeObject<EntityModel>(System.IO.File.ReadAllText(entityPath));
string agentId = entityPath.Split(Path.DirectorySeparatorChar).Last().Split('-')[1];
string agentPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.Contains($"agent-{agentId}.json"));
var agent = JsonConvert.DeserializeObject<AgentModel>(System.IO.File.ReadAllText(agentPath));
var intentPaths = Directory.GetFiles(dataDir).Where(x => x.Contains($"agent-{agent.Id}-intent-")).ToList();
for (int i = 0; i < intentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(intentPaths[i]);
var intent = JsonConvert.DeserializeObject<IntentModel>(json);
if (intent.Examples.Exists(x => x.Entities.Exists(e => e.EntityId == entityId)))
{
intents.Add(intent);
}
}
return intents;
}
[HttpGet("/domain/{domainId}/intent")]
public IntentPageViewModel GetReferencedIntentsByDomain([FromRoute] int domainId, [FromQuery] int start, [FromQuery] int limit)
{
var intents = new List<IntentModel>();
string dataDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate");
string domainPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.Contains($"-domain-{domainId}.json"));
var domain = JsonConvert.DeserializeObject<DomainModel>(System.IO.File.ReadAllText(domainPath));
string agentId = domainPath.Split(Path.DirectorySeparatorChar).Last().Split('-')[1];
string agentPath = Directory.GetFiles(dataDir).FirstOrDefault(x => x.Contains($"agent-{agentId}.json"));
var agent = JsonConvert.DeserializeObject<AgentModel>(System.IO.File.ReadAllText(agentPath));
var intentPaths = Directory.GetFiles(dataDir).Where(x => x.Contains($"agent-{agentId}-intent-")).ToList();
for (int i = 0; i < intentPaths.Count; i++)
{
string json = System.IO.File.ReadAllText(intentPaths[i]);
var intent = JsonConvert.DeserializeObject<IntentModel>(json);
if (intent.Domain == domain.DomainName)
{
intents.Add(intent);
}
}
return new IntentPageViewModel { Intents = intents, Total = intents.Count };
}
}
#endif
}

View file

@ -0,0 +1,14 @@
using BotSharp.Core.Engines.Articulate;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.RestApi.Articulate
{
public class IntentPageViewModel
{
public List<IntentModel> Intents { get; set; }
public int Total { get; set; }
}
}

View file

@ -0,0 +1,28 @@
using BotSharp.Core.Engines.Articulate;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace BotSharp.RestApi.Articulate
{
#if ARTICULATE
[Route("[controller]")]
public class SettingsController : ControllerBase
{
[HttpGet]
public SettingsModel GetSettings()
{
string dataPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Articulate", "settings.json");
string json = System.IO.File.ReadAllText(dataPath);
var settings = JsonConvert.DeserializeObject<SettingsModel>(json);
return settings;
}
}
#endif
}

View file

@ -16,7 +16,7 @@
<PackageTags>NLU, Chatbot, Bot, AI Bot</PackageTags>
<PackageReleaseNotes>Restful API for BotSharp.Core</PackageReleaseNotes>
<Platforms>AnyCPU;x64</Platforms>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -65,6 +65,12 @@
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>TRACE;ARTICULATE</DefineConstants>
<DocumentationFile>bin\ARTICULATE\BotSharp.RestApi.xml</DocumentationFile>
<OutputPath>bin\ARTICULATE</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Authentication\**" />
<EmbeddedResource Remove="Authentication\**" />

View file

@ -8,5 +8,6 @@ namespace BotSharp.RestApi
[Route("v1/[controller]/[action]")]
public class IntentController : ControllerBase
{
}
}

View file

@ -2,11 +2,15 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Configurations>Debug;Release;RASA;DIALOGFLOW</Configurations>
<Configurations>Debug;Release;RASA;DIALOGFLOW;ARTICULATE</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>bin\RASA</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>TRACE;ARTICULATE</DefineConstants>
</PropertyGroup>
</Project>

View file

@ -5,7 +5,7 @@
<IsPackable>false</IsPackable>
<Configurations>Debug;Release;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<ItemGroup>

View file

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Configurations>Debug;Release;RASA;DIALOGFLOW</Configurations>
<Configurations>Debug;Release;RASA;DIALOGFLOW;ARTICULATE</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@ -14,6 +14,10 @@
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>TRACE;ARTICULATE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NAudio" Version="1.8.4" />
</ItemGroup>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>Portable;win10-x64;centos.7-x64</RuntimeIdentifiers>
<Platforms>AnyCPU;x64</Platforms>
<Configurations>Debug;Release;DIALOGFLOW;RASA</Configurations>
<Configurations>Debug;Release;DIALOGFLOW;RASA;ARTICULATE</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -21,6 +21,11 @@
<DefineConstants>DEBUG;TRACE;DIALOGFLOW;NETCOREAPP;NETCOREAPP2_1</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ARTICULATE|AnyCPU'">
<DefineConstants>DEBUG;TRACE;ARTICULATE</DefineConstants>
<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Remove="App_Data\AgentArchive\**" />
<Compile Remove="App_Data\Corpus\**" />

View file

@ -34,7 +34,13 @@ namespace BotSharp.WebHost
config.AddJsonFile(setting, optional: false, reloadOnChange: true);
});
})
#if ARTICULATE
.UseUrls("http://0.0.0.0:7500")
#elif RASA
.UseUrls("http://0.0.0.0:5000")
#else
.UseUrls("http://0.0.0.0:3112")
#endif
.UseStartup<Startup>()
.Build();
}

View file

@ -1,11 +1,11 @@
{
"Swagger": {
"Contact": {
"Email": "haiping008@gmail.com",
"Email": "botsharp2018@gmail.com",
"Name": "BotSharp AI",
"Url": "https://github.com/Oceania2018"
},
"Description": "BotSharp is a chatbot platform written in C# (.net core), and it's developed for enterprise usage.",
"Description": "BotSharp is a chatbot platform builder running in .NET Core",
"Endpoint": "/swagger/v1/swagger.json",
"License": {
"Name": "Apache License 2.0",

View file

@ -83,6 +83,8 @@ namespace BotSharp.WebHost
app.UseDeveloperExceptionPage();
}
app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
app.UseDefaultFiles();
app.UseStaticFiles();
@ -95,6 +97,8 @@ namespace BotSharp.WebHost
info.Title += " (DIALOGFLOW)";
#elif RASA
info.Title += " (RASA)";
#elif ARTICULATE
info.Title += " (ARTICULATE)";
#endif
c.SupportedSubmitMethods(SubmitMethod.Get, SubmitMethod.Post, SubmitMethod.Put, SubmitMethod.Patch, SubmitMethod.Delete);
@ -105,8 +109,6 @@ namespace BotSharp.WebHost
c.InjectStylesheet(Configuration.GetValue<String>("Swagger:Stylesheet"));
});
app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
app.Use(async (context, next) =>
{
string token = context.Request.Headers["Authorization"];

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Core.UnitTest", "B
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
ARTICULATE|Any CPU = ARTICULATE|Any CPU
ARTICULATE|x64 = ARTICULATE|x64
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
DIALOGFLOW|Any CPU = DIALOGFLOW|Any CPU
@ -43,6 +45,10 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{95780673-2A1A-4953-962F-C46CBFDD07FF}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{95780673-2A1A-4953-962F-C46CBFDD07FF}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{95780673-2A1A-4953-962F-C46CBFDD07FF}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{95780673-2A1A-4953-962F-C46CBFDD07FF}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{95780673-2A1A-4953-962F-C46CBFDD07FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95780673-2A1A-4953-962F-C46CBFDD07FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95780673-2A1A-4953-962F-C46CBFDD07FF}.Debug|x64.ActiveCfg = Debug|x64
@ -59,6 +65,10 @@ Global
{95780673-2A1A-4953-962F-C46CBFDD07FF}.Release|Any CPU.Build.0 = Release|Any CPU
{95780673-2A1A-4953-962F-C46CBFDD07FF}.Release|x64.ActiveCfg = Release|x64
{95780673-2A1A-4953-962F-C46CBFDD07FF}.Release|x64.Build.0 = Release|x64
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.Debug|x64.ActiveCfg = Debug|x64
@ -75,6 +85,10 @@ Global
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.Release|Any CPU.Build.0 = Release|Any CPU
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.Release|x64.ActiveCfg = Release|x64
{80DDAA05-69BC-49DD-96A4-37345E7A2E20}.Release|x64.Build.0 = Release|x64
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.Debug|x64.ActiveCfg = Debug|x64
@ -91,6 +105,10 @@ Global
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.Release|Any CPU.Build.0 = Release|Any CPU
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.Release|x64.ActiveCfg = Release|x64
{03DCA427-327A-4FC9-9A2F-57D17F16708C}.Release|x64.Build.0 = Release|x64
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.Debug|x64.ActiveCfg = Debug|x64
@ -107,6 +125,10 @@ Global
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.Release|Any CPU.Build.0 = Release|Any CPU
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.Release|x64.ActiveCfg = Release|x64
{BE1A033F-AC14-4654-95C3-4B33AF8F6BBF}.Release|x64.Build.0 = Release|x64
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.Debug|x64.ActiveCfg = Debug|x64
@ -123,6 +145,10 @@ Global
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.Release|Any CPU.Build.0 = Release|Any CPU
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.Release|x64.ActiveCfg = Release|x64
{C2FDC855-BD88-4041-B0FF-3AA8A1C11A22}.Release|x64.Build.0 = Release|x64
{184F8B93-68C2-4849-9625-4023C4360990}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.ARTICULATE|x64.ActiveCfg = ARTICULATE|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.ARTICULATE|x64.Build.0 = ARTICULATE|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.Debug|Any CPU.Build.0 = Debug|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -139,6 +165,10 @@ Global
{184F8B93-68C2-4849-9625-4023C4360990}.Release|Any CPU.Build.0 = Release|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.Release|x64.ActiveCfg = Release|Any CPU
{184F8B93-68C2-4849-9625-4023C4360990}.Release|x64.Build.0 = Release|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.ARTICULATE|x64.ActiveCfg = ARTICULATE|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.ARTICULATE|x64.Build.0 = ARTICULATE|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -155,6 +185,10 @@ Global
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.Release|Any CPU.Build.0 = Release|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.Release|x64.ActiveCfg = Release|Any CPU
{75B02A7C-EDB3-4082-9C1F-471773E760C3}.Release|x64.Build.0 = Release|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.ARTICULATE|x64.ActiveCfg = ARTICULATE|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.ARTICULATE|x64.Build.0 = ARTICULATE|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -171,6 +205,10 @@ Global
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.Release|Any CPU.Build.0 = Release|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.Release|x64.ActiveCfg = Release|Any CPU
{3F0CAAD4-564B-43FF-90BF-26AC47C9D677}.Release|x64.Build.0 = Release|Any CPU
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.Debug|x64.ActiveCfg = Debug|x64
@ -187,6 +225,10 @@ Global
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.Release|Any CPU.Build.0 = Release|Any CPU
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.Release|x64.ActiveCfg = Release|x64
{3C702980-826B-4F7D-8D5A-C9F1C811AAE2}.Release|x64.Build.0 = Release|x64
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.Debug|x64.ActiveCfg = Debug|x64
@ -203,6 +245,10 @@ Global
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.Release|Any CPU.Build.0 = Release|Any CPU
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.Release|x64.ActiveCfg = Release|x64
{8A1F6277-FFCB-4CCD-B798-876D8BE525A9}.Release|x64.Build.0 = Release|x64
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.ARTICULATE|Any CPU.ActiveCfg = ARTICULATE|Any CPU
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.ARTICULATE|Any CPU.Build.0 = ARTICULATE|Any CPU
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.ARTICULATE|x64.ActiveCfg = ARTICULATE|x64
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.ARTICULATE|x64.Build.0 = ARTICULATE|x64
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30F80E7D-951A-4E8F-9C3C-2C866528EABD}.Debug|x64.ActiveCfg = Debug|x64

View file

@ -1,6 +1,6 @@
.. raw:: html
<img src="https://github.com/Oceania2018/BotSharp/blob/master/BotSharp.WebHost/wwwroot/images/BotSharp.png" width="100px">
<img src="https://raw.githubusercontent.com/Oceania2018/BotSharp/master/BotSharp.WebHost/wwwroot/images/BotSharp.png" width="100px">
The Open Source AI Bot Platform Builder
======================================================
@ -77,7 +77,7 @@ Scan to join group in Wechat
.. raw:: html
<img src="https://github.com/Oceania2018/BotSharp/blob/master/docs/static/logos/WechatQRCode.png" width="150px">
<img src="https://raw.githubusercontent.com/Oceania2018/BotSharp/master/docs/static/logos/WechatQRCode.png" width="150px">
.. _Docker: https://www.docker.com
.. _Rasa UI: https://github.com/paschmann/rasa-ui

88
README_zh.rst Normal file
View file

@ -0,0 +1,88 @@
.. raw:: html
<img src="https://raw.githubusercontent.com/Oceania2018/BotSharp/master/BotSharp.WebHost/wwwroot/images/BotSharp.png" width="100px">
开源人工智能聊天机器人平台构建框架
===============================
.. image:: https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg
:target: `gitter`_
:alt: gitter
:align: left
.. image:: https://img.shields.io/hexpm/l/plug.svg
:target: `license`_
:alt: Hex.pm
:align: left
.. image:: https://img.shields.io/nuget/dt/EntityFrameworkCore.BootKit.svg
:target: `botsharpnuget`_
:alt: NuGet
本项目用于学习和交流人工智能聊天机器人平台构建的相关技术,本人对于任何用于生产环境而产生的风险和损失不负责任
**************************************************************************************************
*"Conversation as a platform (CaaP) is the future, so it's perfect that we're already offering the whole toolkits to our .NET developers using the BotSharp AI BOT Platform Builder to build a CaaP. It opens up as much learning power as possible for your own robots and precisely control every step of the AI processing pipeline."*
**BotSharp** is an open source machine learning framework for AI Bot platform builder. This project involves natural language understanding, computer vision and audio processing technologies, and aims to promote the development and application of intelligent robot assistants in information systems. Out-of-the-box machine learning algorithms allow ordinary programmers to develop artificial intelligence applications faster and easier.
.. raw:: html
<img src="https://raw.githubusercontent.com/Oceania2018/BotSharp/master/docs/static/logos/BotSharpEngine.jpg" width="100%">
It's witten in C# running on .Net Core that is full cross-platform framework. C# is a enterprise grade programming language which is widely used to code business logic in information management related system. More friendly to corporate developers. BotSharp adopts machine learning algrithm in C# directly. That will facilitate the feature of the typed language C#, and be more easier when refactoring code in system scope.
Why we do this? because we all know python is not friendly programming language for enterprise developers, it's not only because it's low performance but also it's a type weak language, it will be a disater if you use python to build your bussiness system.
BotSharp is in accordance with components princple strictly, decouples every part that needed in the platform builder. So you can choose different UI/UX, or pick up a different NLP Tagger, or select a more advanced algrithm to do NER task. They are all modulized based an unfied interfaces.
Some Features
-------------
* Integrated debugging is easier without relying on any other machine learning algorithm libraries.
* Built-in multi-Agents management, easy to build Bot as a Service platform.
* Context In/ Out with lifespan to make conversion flow be controllable.
* Use the natural language processing pipeline mechanism to work with extensions easily, and build your own unique robot processing flows.
* Rewrote NLP algorithm from ground without historical issues.
* Support export/ import agent from other bot platforms directly.
* Support different UI providers like `Rasa UI`_ and `Articulate UI`_.
* Support for multiple data request and response formats such as Rasa NLU and Dialogflow.
* Integrate with popular social platforms like Facebook Messenger, Slack and Telegram.
* Multi-core parallel computing optimization, High-Performance C# on GPUs in Hybridizer.
Quick Started
-------------
You can use docker compose to run BotSharp quickly, make sure you've got `Docker`_ installed.
::
PS D:\> git clone https://github.com/Oceania2018/BotSharp
PS D:\> cd BotSharp
PS D:\BotSharp\> docker-compose -f dockerfiles/docker-compose-articulateui.yml up
Point your web browser at http://localhost:3000 and enjoy BotSharp with Articulate-UI.
Documents
---------
Read the docs: https://botsharp.readthedocs.io
Feel free to message me on
.. image:: https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg
:target: `gitter`_
If you feel that this project is helpful to you, please Star on the project, we will be very grateful.
Scan to join group in Wechat
.. raw:: html
<img src="https://raw.githubusercontent.com/Oceania2018/BotSharp/master/docs/static/logos/WechatQRCode.png" width="150px">
.. _Docker: https://www.docker.com
.. _Rasa UI: https://github.com/paschmann/rasa-ui
.. _Articulate UI: https://spg.ai/projects/articulate
.. _gitter: https://gitter.im/botsharpcore/Lobby
.. _license: https://raw.githubusercontent.com/Oceania2018/BotSharp/master/LICENSE
.. _botsharpnuget: https://www.nuget.org/packages/BotSharp.Core