add BotSharp.NLP library, finish RegexTokenizer.

This commit is contained in:
haiping008@gmail.com 2018-08-15 17:37:23 -05:00
parent cd72868f38
commit 443e60c9b1
44 changed files with 369 additions and 120 deletions

View file

@ -1,4 +1,5 @@
using BotSharp.Core.Abstractions;
using BotSharp.NLP.Tokenize;
using EntityFrameworkCore.BootKit;
using Newtonsoft.Json;
using System;
@ -20,8 +21,8 @@ namespace BotSharp.Core.Accounts
private void ImportAccount(Database dc)
{
var dataPath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "DbInitializer", "Accounts");
string json = File.ReadAllText(Path.Join(dataPath, "users.json"));
var dataPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "DbInitializer", "Accounts");
string json = File.ReadAllText(Path.Combine(dataPath, "users.json"));
var users = JsonConvert.DeserializeObject<List<User>>(json);
users.ForEach(user =>

View file

@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Haiping Chen</Authors>
<Company />
<Product>BotSharp Chatbot Platform</Product>
<Description>Open source chatbot platform which is written in C# runs on .Net Core and is enterprise oriented. Integrated with multiple bot engines besides BotSharp bot engine. Modulized pipeline design make NLP tasks plugin easily. Abstract platform and NLP task, migrate existed chatbot from a platform into another platform perfectly through dump and restore.</Description>
<Product>BotSharp AI Bot Platform Builder</Product>
<Description>Open source AI Bot platform builder which is written in C# runs on .Net Core and is enterprise oriented. Integrated with multiple bot engines besides BotSharp bot engine. Modulized pipeline design make NLP tasks plugin easily. Abstract platform and NLP task, migrate existed chatbot from a platform into another platform perfectly through dump and restore.</Description>
<RepositoryType>MIT</RepositoryType>
<RepositoryUrl>https://github.com/Oceania2018/BotSharp</RepositoryUrl>
<PackageTags>NLU, Chatbot, Bot, AI Bot, Artificial Intelligence, RPA</PackageTags>
@ -30,13 +31,21 @@
<DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;MODEL_PER_CONTEXTS</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DefineConstants>TRACE;MODEL_PER_CONTEXTS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetToolkit" Version="1.5.4" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="1.8.0" />
<PackageReference Include="DotNetToolkit" Version="1.6.0" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="1.9.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="RestSharp" Version="106.3.1" />
@ -44,6 +53,7 @@
<ItemGroup>
<ProjectReference Include="..\BotSharp.MachineLearning\BotSharp.MachineLearning.csproj" />
<ProjectReference Include="..\BotSharp.NLP\BotSharp.NLP.csproj" />
</ItemGroup>
<ItemGroup>

View file

@ -32,7 +32,7 @@ namespace BotSharp.Core.Engines
{
dc = new DefaultDataContextLoader().GetDefaultDc();
string dataPath = AppDomain.CurrentDomain.GetData("DataPath").ToString();
DbInitializerPath = Path.Join(dataPath, $"DbInitializer");
DbInitializerPath = Path.Combine(dataPath, $"DbInitializer");
}
public AIResponse TextRequest(AIRequest request)
@ -91,7 +91,7 @@ namespace BotSharp.Core.Engines
/// <returns></returns>
public bool RestoreAgent<TAgentImporter>(AgentImportHeader agentHeader) where TAgentImporter : IAgentImporter, new()
{
string dataDir = Path.Join(DbInitializerPath, "Agents");
string dataDir = Path.Combine(DbInitializerPath, "Agents");
int row = dc.DbTran(() => {
LoadAgentFromFile<TAgentImporter>(dataDir, agentHeader);

View file

@ -20,9 +20,9 @@ namespace BotSharp.Core.Engines
public async Task<NlpDoc> Predict(Agent agent, AIRequest request)
{
// load model
var dir = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "ModelFiles", agent.Id);
var dir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "ModelFiles", agent.Id);
Console.WriteLine($"Load model from {dir}");
var metaJson = File.ReadAllText(Path.Join(dir, "metadata.json"));
var metaJson = File.ReadAllText(Path.Combine(dir, "metadata.json"));
var meta = JsonConvert.DeserializeObject<ModelMetaData>(metaJson);
// Get NLP Provider
@ -49,8 +49,8 @@ namespace BotSharp.Core.Engines
var settings = new PipeSettings
{
ProjectDir = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", agent.Id),
AlgorithmDir = Path.Join(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms")
ProjectDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", agent.Id),
AlgorithmDir = Path.Combine(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms")
};

View file

@ -66,11 +66,11 @@ namespace BotSharp.Core.Engines
var settings = new PipeSettings
{
ProjectDir = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", agent.Id),
AlgorithmDir = Path.Join(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms")
ProjectDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", agent.Id),
AlgorithmDir = Path.Combine(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms")
};
settings.ModelDir = Path.Join(settings.ProjectDir, "model" + DateTime.UtcNow.ToString("MMddyyyyHHmm"));
settings.ModelDir = Path.Combine(settings.ProjectDir, "model" + DateTime.UtcNow.ToString("MMddyyyyHHmm"));
if (!Directory.Exists(settings.ProjectDir))
{
@ -126,7 +126,7 @@ namespace BotSharp.Core.Engines
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
File.WriteAllText(Path.Join(settings.ModelDir, "metadata.json"), metaJson);
File.WriteAllText(Path.Combine(settings.ModelDir, "metadata.json"), metaJson);
Console.WriteLine(metaJson);

View file

@ -21,17 +21,17 @@ namespace BotSharp.Core.Engines.Classifiers
public async Task<bool> Predict(Agent agent, NlpDoc doc, PipeModel meta)
{
string modelFileName = Path.Join(Settings.ModelDir, meta.Model);
string predictFileName = Path.Join(Settings.TempDir, "fasttext.txt");
string modelFileName = Path.Combine(Settings.ModelDir, meta.Model);
string predictFileName = Path.Combine(Settings.TempDir, "fasttext.txt");
File.WriteAllText(predictFileName, doc.Sentences[0].Text);
var output = CmdHelper.Run(Path.Join(Settings.AlgorithmDir, "fasttext"), $"predict-prob {modelFileName}.bin {predictFileName}");
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "fasttext"), $"predict-prob {modelFileName}.bin {predictFileName}");
File.Delete(predictFileName);
doc.Sentences[0].Intent = new TextClassificationResult
{
Label = output.Split(' ')[0].Split("__label__")[1],
Label = output.Split(' ')[0].Split(new string[] { "__label__" }, StringSplitOptions.None)[1],
Confidence = decimal.Parse(output.Split(' ')[1])
};
@ -42,8 +42,8 @@ namespace BotSharp.Core.Engines.Classifiers
{
meta.Model = "classification-fasttext.model";
string parsedTrainingDataFileName = Path.Join(Settings.TempDir, $"classification-fasttext.parsed.txt");
string modelFileName = Path.Join(Settings.ModelDir, meta.Model);
string parsedTrainingDataFileName = Path.Combine(Settings.TempDir, $"classification-fasttext.parsed.txt");
string modelFileName = Path.Combine(Settings.ModelDir, meta.Model);
// assemble corpus
StringBuilder corpus = new StringBuilder();
@ -51,7 +51,7 @@ namespace BotSharp.Core.Engines.Classifiers
File.WriteAllText(parsedTrainingDataFileName, corpus.ToString());
var output = CmdHelper.Run(Path.Join(Settings.AlgorithmDir, "fasttext"), $"supervised -input {parsedTrainingDataFileName} -output {modelFileName}", false);
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "fasttext"), $"supervised -input {parsedTrainingDataFileName} -output {modelFileName}", false);
Console.WriteLine($"Saved model to {modelFileName}");
meta.Meta = new JObject();

View file

@ -1,4 +1,5 @@
using System;
using BotSharp.NLP;
using System;
using System.Collections.Generic;
using System.Text;

View file

@ -30,7 +30,7 @@ namespace BotSharp.Core.Engines
public Agent LoadAgent(AgentImportHeader agentHeader)
{
// load agent profile
string data = File.ReadAllText(Path.Join(AgentDir, "Dialogflow", $"{agentHeader.Name}{Path.DirectorySeparatorChar}agent.json"));
string data = File.ReadAllText(Path.Combine(AgentDir, "Dialogflow", $"{agentHeader.Name}{Path.DirectorySeparatorChar}agent.json"));
var agent = JsonConvert.DeserializeObject<DialogflowAgent>(data);
agent.Name = agentHeader.Name;
agent.Id = agentHeader.Id;
@ -58,14 +58,14 @@ namespace BotSharp.Core.Engines
public void LoadCustomEntities(Agent agent)
{
agent.Entities = new List<EntityType>();
string entityDir = Path.Join(AgentDir, "Dialogflow", $"{agent.Name}{Path.DirectorySeparatorChar}entities");
string entityDir = Path.Combine(AgentDir, "Dialogflow", $"{agent.Name}{Path.DirectorySeparatorChar}entities");
if (!Directory.Exists(entityDir)) return;
Directory.EnumerateFiles(entityDir)
.ToList()
.ForEach(fileName =>
{
string entityName = fileName.Split($"{Path.DirectorySeparatorChar}").Last();
string entityName = fileName.Split(Path.DirectorySeparatorChar).Last();
if (!entityName.Contains("_"))
{
string entityJson = File.ReadAllText($"{fileName}");
@ -93,7 +93,7 @@ namespace BotSharp.Core.Engines
public void LoadIntents(Agent agent)
{
agent.Intents = new List<Intent>();
string intentDir = Path.Join(AgentDir, "Dialogflow", $"{agent.Name}{Path.DirectorySeparatorChar}intents");
string intentDir = Path.Combine(AgentDir, "Dialogflow", $"{agent.Name}{Path.DirectorySeparatorChar}intents");
if (!Directory.Exists(intentDir)) return;
Directory.EnumerateFiles(intentDir)

View file

@ -1,6 +1,7 @@
using BotSharp.Core.Abstractions;
using BotSharp.Core.Agents;
using BotSharp.MachineLearning.NLP;
using BotSharp.NLP.Tokenize;
using DotNetToolkit;
using EntityFrameworkCore.BootKit;
using Microsoft.Extensions.Configuration;
@ -45,9 +46,9 @@ namespace BotSharp.Core.Engines.NERs
List<TrainingIntentExpression<TrainingIntentExpressionPart>> userSays = corpus.UserSays;
List<List<TrainingData>> list = new List<List<TrainingData>>();
string rawTrainingDataFileName = Path.Join(Settings.TempDir, "ner-crf.corpus.txt");
string parsedTrainingDataFileName = Path.Join(Settings.TempDir, "ner-crf.parsed.txt");
string modelFileName = Path.Join(Settings.ModelDir, meta.Model);
string rawTrainingDataFileName = Path.Combine(Settings.TempDir, "ner-crf.corpus.txt");
string parsedTrainingDataFileName = Path.Combine(Settings.TempDir, "ner-crf.parsed.txt");
string modelFileName = Path.Combine(Settings.ModelDir, meta.Model);
using (FileStream fs = new FileStream(rawTrainingDataFileName, FileMode.Create))
{
@ -74,11 +75,11 @@ namespace BotSharp.Core.Engines.NERs
var biFeatures = Configuration.GetValue<String>($"CRFsuiteEntityRecognizer:biFeatures");
new MachineLearning.CRFsuite.Ner()
.NerStart(rawTrainingDataFileName, parsedTrainingDataFileName, fields, uniFeatures.Split(" "), biFeatures.Split(" "));
.NerStart(rawTrainingDataFileName, parsedTrainingDataFileName, fields, uniFeatures.Split(' '), biFeatures.Split(' '));
var algorithmDir = Path.Join(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms");
var algorithmDir = Path.Combine(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms");
CmdHelper.Run(Path.Join(algorithmDir, "crfsuite"), $"learn -m {modelFileName} {parsedTrainingDataFileName}", false); // --split=3 -x
CmdHelper.Run(Path.Combine(algorithmDir, "crfsuite"), $"learn -m {modelFileName} {parsedTrainingDataFileName}", false); // --split=3 -x
Console.WriteLine($"Saved model to {modelFileName}");
meta.Meta = new JObject();
meta.Meta["fields"] = fields;
@ -88,7 +89,7 @@ namespace BotSharp.Core.Engines.NERs
return true;
}
public List<TrainingData> Merge(List<NlpToken> tokens, List<TrainingIntentExpressionPart> entities)
public List<TrainingData> Merge(List<Token> tokens, List<TrainingIntentExpressionPart> entities)
{
List<TrainingData> trainingTuple = new List<TrainingData>();
HashSet<String> entityWordBag = new HashSet<String>();
@ -103,7 +104,7 @@ namespace BotSharp.Core.Engines.NERs
entities.ForEach(entity => {
if (!entityFinded)
{
string[] words = entity.Value.Split(" ");
string[] words = entity.Value.Split(' ');
for (int j = 0; j < words.Length; j++)
{
if (tokens[i + j].Text == words[j])
@ -150,11 +151,11 @@ namespace BotSharp.Core.Engines.NERs
var uniFeatures = meta.Meta["uniFeatures"].ToString();
var biFeatures = meta.Meta["biFeatures"].ToString();
string field = meta.Meta["fields"].ToString();
string[] fields = field.Split(" ");
string[] fields = field.Split(' ');
string rawPredictingDataFileName = Path.Join(Settings.TempDir, "ner-crf.corpus.predict.txt");
string parsedPredictingDataFileName = Path.Join(Settings.TempDir, "ner-crf.parsed.predict.txt");
string modelFileName = Path.Join(Settings.ModelDir, meta.Model);
string rawPredictingDataFileName = Path.Combine(Settings.TempDir, "ner-crf.corpus.predict.txt");
string parsedPredictingDataFileName = Path.Combine(Settings.TempDir, "ner-crf.parsed.predict.txt");
string modelFileName = Path.Combine(Settings.ModelDir, meta.Model);
using (FileStream fs = new FileStream(rawPredictingDataFileName, FileMode.Create))
{
@ -163,7 +164,7 @@ namespace BotSharp.Core.Engines.NERs
List<string> curLine = new List<string>();
foreach (NlpDocSentence sentence in doc.Sentences)
{
foreach (NlpToken token in sentence.Tokens)
foreach (Token token in sentence.Tokens)
{
for (int i = 0 ; i < fields.Length; i++)
{
@ -191,18 +192,18 @@ namespace BotSharp.Core.Engines.NERs
}
new MachineLearning.CRFsuite.Ner()
.NerStart(rawPredictingDataFileName, parsedPredictingDataFileName, field, uniFeatures.Split(" "), biFeatures.Split(" "));
.NerStart(rawPredictingDataFileName, parsedPredictingDataFileName, field, uniFeatures.Split(' '), biFeatures.Split(' '));
var output = CmdHelper.Run(Path.Join(Settings.AlgorithmDir, "crfsuite"), $"tag -i -m {modelFileName} {parsedPredictingDataFileName}", false);
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "crfsuite"), $"tag -i -m {modelFileName} {parsedPredictingDataFileName}", false);
var entities = new List<NlpEntity>();
string[] entityProbabilityPairs = output.Split(Environment.NewLine).Where(x => !String.IsNullOrEmpty(x)).ToArray();
string[] entityProbabilityPairs = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Where(x => !String.IsNullOrEmpty(x)).ToArray();
for (int i = 0; i < entityProbabilityPairs.Length; i++)
{
string entityProbabilityPair = entityProbabilityPairs[i];
string entity = entityProbabilityPair.Split(":")[0];
decimal probability = decimal.Parse(entityProbabilityPair.Split(":")[1]);
string entity = entityProbabilityPair.Split(':')[0];
decimal probability = decimal.Parse(entityProbabilityPair.Split(':')[1]);
entities.Add(new NlpEntity
{
Entity = entity,

View file

@ -1,4 +1,5 @@
using BotSharp.MachineLearning.NLP;
using BotSharp.NLP.Tokenize;
using System;
using System.Collections.Generic;
using System.Text;
@ -13,7 +14,7 @@ namespace BotSharp.Core.Engines
public class NlpDocSentence
{
public string Text { get; set; }
public List<NlpToken> Tokens { get; set; }
public List<Token> Tokens { get; set; }
public List<NlpEntity> Entities { get; set; }
public TextClassificationResult Intent { get; set; }
}

View file

@ -2,6 +2,7 @@ using BotSharp.Core.Abstractions;
using BotSharp.Core.Agents;
using BotSharp.Core.Models;
using BotSharp.MachineLearning.NLP;
using BotSharp.NLP.Tokenize;
using EntityFrameworkCore.BootKit;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
@ -24,7 +25,7 @@ namespace BotSharp.Core.Engines.SpaCy
{
var client = new RestClient(Configuration.GetSection("NltkProvider:Url").Value);
var request = new RestRequest("nltktokenizesentences", Method.POST);
List<List<NlpToken>> tokens = new List<List<NlpToken>>();
List<List<Token>> tokens = new List<List<Token>>();
Boolean res = true;
var dc = new DefaultDataContextLoader().GetDefaultDc();
var corpus = agent.Corpus;
@ -74,7 +75,7 @@ namespace BotSharp.Core.Engines.SpaCy
{
var client = new RestClient(Configuration.GetSection("NltkProvider:Url").Value);
var request = new RestRequest("nltktokenizesentences", Method.POST);
List<List<NlpToken>> tokens = new List<List<NlpToken>>();
List<List<Token>> tokens = new List<List<Token>>();
Boolean res = true;
var corpus = agent.Corpus;
@ -92,7 +93,7 @@ namespace BotSharp.Core.Engines.SpaCy
private class Result
{
public List<List<NlpToken>> TokensList { get; set; }
public List<List<Token>> TokensList { get; set; }
}
private class Documents

View file

@ -14,7 +14,7 @@ namespace BotSharp.Core.Engines
{
get
{
return Path.Join(ProjectDir, "Temp");
return Path.Combine(ProjectDir, "Temp");
}
}
}

View file

@ -87,7 +87,7 @@ namespace BotSharp.Core.Engines.Rasa
public void LoadIntents(Agent agent)
{
string data = File.ReadAllText(Path.Join(AgentDir, "corpus.json"));
string data = File.ReadAllText(Path.Combine(AgentDir, "corpus.json"));
var rasa = JsonConvert.DeserializeObject<RasaAgent>(data);
agent.Intents = rasa.UserSays.Select(x => x.Intent).Distinct().Select(x => new Intent { Name = x }).ToList();

View file

@ -198,7 +198,7 @@ namespace BotSharp.Core.Engines
rest.AddQueryParameter("model", ctx);
string trainingConfig = agent.Language == "zh" ? "config_jieba_mitie_sklearn.yml" : "config_mitie_sklearn.yml";
var contentRootPatch = AppDomain.CurrentDomain.GetData("ContentRootPath").ToString();
string body = File.ReadAllText(Path.Join(contentRootPatch, "Settings", trainingConfig));
string body = File.ReadAllText(Path.Combine(contentRootPatch, "Settings", trainingConfig));
body = $"{body}\r\ndata: {json}";
rest.AddParameter("application/x-yml", body, ParameterType.RequestBody);
@ -208,7 +208,7 @@ namespace BotSharp.Core.Engines
{
var result = JObject.Parse(response.Content);
string modelName = result["info"].Value<String>().Split(": ")[1];
string modelName = result["info"].Value<String>().Split(new string[] { ": " }, StringSplitOptions.None)[1];
}
else
{

View file

@ -101,7 +101,7 @@ namespace BotSharp.Core.Engines
intentResponse.Parameters.ForEach(p => {
string query = request.Query.First();
var entity = response.Entities.FirstOrDefault(x => x.Entity == p.Name || x.Entity.Split(":").Contains(p.Name));
var entity = response.Entities.FirstOrDefault(x => x.Entity == p.Name || x.Entity.Split(':').Contains(p.Name));
if (entity != null)
{
p.Value = query.Substring(entity.Start, entity.End - entity.Start);
@ -168,7 +168,7 @@ namespace BotSharp.Core.Engines
if (msg.Speech != "[]")
{
msg.Speech = msg.Speech.StartsWith("[") ?
ArrayHelper.GetRandom(msg.Speech.Substring(2, msg.Speech.Length - 4).Split("\",\"").ToList()) :
ArrayHelper.GetRandom(msg.Speech.Substring(2, msg.Speech.Length - 4).Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList()) :
msg.Speech;
msg.Speech = ReplaceParameters4Response(intentResponse.Parameters, msg.Speech);
@ -181,7 +181,7 @@ namespace BotSharp.Core.Engines
{
var reg = new Regex(@"\$\w+");
reg.Matches(text).ToList().ForEach(token => {
reg.Matches(text).Cast<Match>().ToList().ForEach(token => {
var parameter = parameters.FirstOrDefault(x => x.Name == token.Value.Substring(1));
if(parameter != null)
{

View file

@ -31,7 +31,7 @@ namespace BotSharp.Core.Engines
public Agent LoadAgent(AgentImportHeader agentHeader)
{
// load agent profile
string data = File.ReadAllText(Path.Join(AgentDir, "Sebis", $"{agentHeader.Name}{Path.DirectorySeparatorChar}agent.json"));
string data = File.ReadAllText(Path.Combine(AgentDir, "Sebis", $"{agentHeader.Name}{Path.DirectorySeparatorChar}agent.json"));
var agent = JsonConvert.DeserializeObject<SebisAgent>(data);
agent.Name = agentHeader.Name;
agent.Id = agentHeader.Id;
@ -54,7 +54,7 @@ namespace BotSharp.Core.Engines
public void LoadIntents(Agent agent)
{
string data = File.ReadAllText(Path.Join(AgentDir, "Sebis", $"{agent.Name}{Path.DirectorySeparatorChar}corpus.json"));
string data = File.ReadAllText(Path.Combine(AgentDir, "Sebis", $"{agent.Name}{Path.DirectorySeparatorChar}corpus.json"));
var sentences = JsonConvert.DeserializeObject<SebisAgent>(data).Sentences;
agent.Intents = sentences.Select(x => x.Name).Distinct().Select(x => new Intent{Name = x}).ToList();

View file

@ -2,6 +2,7 @@
using BotSharp.Core.Agents;
using BotSharp.Core.Models;
using BotSharp.MachineLearning.NLP;
using BotSharp.NLP.Tokenize;
using EntityFrameworkCore.BootKit;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
@ -24,7 +25,7 @@ namespace BotSharp.Core.Engines.SpaCy
{
var client = new RestClient(Configuration.GetSection("SpaCyProvider:Url").Value);
var request = new RestRequest("tokenizer", Method.POST);
List<List<NlpToken>> tokens = new List<List<NlpToken>>();
List<List<Token>> tokens = new List<List<Token>>();
Boolean res = true;
var corpus = agent.Corpus;
@ -57,7 +58,7 @@ namespace BotSharp.Core.Engines.SpaCy
{
var client = new RestClient(Configuration.GetSection("SpaCyProvider:Url").Value);
var request = new RestRequest("tokenizer", Method.GET);
List<List<NlpToken>> tokens = new List<List<NlpToken>>();
List<List<Token>> tokens = new List<List<Token>>();
Boolean res = true;
var corpus = agent.Corpus;
@ -75,7 +76,7 @@ namespace BotSharp.Core.Engines.SpaCy
private class Result
{
public List<List<NlpToken>> TokensList { get; set; }
public List<List<Token>> TokensList { get; set; }
}
private class Documents

View file

@ -41,7 +41,7 @@ namespace BotSharp.Core.Intents
{
return Contexts == null || Contexts.Count == 0
? Guid.Empty.ToString("N")
: $"{String.Join(',', Contexts.OrderBy(x => x.Name).Select(x => x.Name))}".GetMd5Hash();
: $"{String.Join(",", Contexts.OrderBy(x => x.Name).Select(x => x.Name))}".GetMd5Hash();
}
}

View file

@ -1,21 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<Folder Include="Fasttext\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DevExpress.Xpo" Version="18.1.4" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Data.Sqlite">
<HintPath>..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.data.sqlite.core\2.1.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -63,7 +63,7 @@ namespace BotSharp.MachineLearning.CRFsuite
/// <param name="names">each attribute name in fields</param>
/// <param name="sep">seperate by</param>
public List<List<Dictionary<string, Object>>> Readiter (string fiPath, List<string> names, string sep = " ")
public List<List<Dictionary<string, Object>>> Readiter (string fiPath, List<string> names, char sep = ' ')
{
List<List<Dictionary<string, Object>>> Xs = new List<List<Dictionary<string, Object>>>();
List<Dictionary<string, Object>> X = new List<Dictionary<string, Object>>();
@ -143,8 +143,8 @@ namespace BotSharp.MachineLearning.CRFsuite
{
using (StreamWriter sw = new StreamWriter(fs))
{
List<string> F = fields.Split(" ").ToList();
List<List<Dictionary<string, Object>>> Xs = Readiter(rawFile, F, " ");
List<string> F = fields.Split(' ').ToList();
List<List<Dictionary<string, Object>>> Xs = Readiter(rawFile, F);
foreach (List<Dictionary<string, Object>> X in Xs)
{

View file

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BotSharp.NLP\BotSharp.NLP.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,36 @@
using BotSharp.NLP.Tokenize;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace BotSharp.NLP.UnitTest
{
[TestClass]
public class RegexpTokenizerTest
{
[TestMethod]
public void Tokenize()
{
var tokenizer = new TokenizerFactory<RegexTokenizer>();
var tokens = tokenizer.Tokenize("Chop into pieces, isn't it?",
new TokenizationOptions
{
Pattern = RegexTokenizer.WHITE_SPACE
});
Assert.IsTrue(tokens[0].Offset == 0);
Assert.IsTrue(tokens[0].Text == "Chop");
Assert.IsTrue(tokens[1].Offset == 5);
Assert.IsTrue(tokens[1].Text == "into");
Assert.IsTrue(tokens[2].Offset == 10);
Assert.IsTrue(tokens[2].Text == "pieces,");
Assert.IsTrue(tokens[3].Offset == 18);
Assert.IsTrue(tokens[3].Text == "isn't");
Assert.IsTrue(tokens[3].Offset == 24);
Assert.IsTrue(tokens[3].Text == "it?");
}
}
}

View file

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
</Project>

View file

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Models
namespace BotSharp.NLP
{
public class SupportedLanguage
{

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.NLP.Tokenize
{
/// <summary>
/// A tokenizer is a component used for dividing text intotokens.
/// A tokenizer is language specific and takes into account the peculiarities of the language, e.g. dont in English is tokenized as two tokens.
/// </summary>
public interface ITokenizer
{
/// <summary>
/// Language
/// </summary>
SupportedLanguage Lang { get; set; }
/// <summary>
/// Tokenize
/// </summary>
/// <param name="text">input</param>
/// <param name="options">Options such as: regex expression</param>
/// <returns></returns>
Token[] Tokenize(string text, TokenizationOptions options);
}
}

View file

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace BotSharp.NLP.Tokenize
{
public class RegexTokenizer : ITokenizer
{
public SupportedLanguage Lang { get; set; }
/// <summary>
/// Tokenize a text into a sequence of alphabetic and non-alphabetic characters
/// </summary>
public const string WORD_PUNC = @"\w+|[^\w\s]+";
/// <summary>
/// Tokenize a string, treating any sequence of blank lines as a delimiter.
/// Blank lines are defined as lines containing no characters, except for space or tab characters.
/// options.IsGap = true
/// </summary>
public const string BLANK_LINE = @"\s*\n\s*\n\s*";
/// <summary>
/// Tokenize a string on whitespace (space, tab, newline).
/// In general, users should use the string ``split()`` method instead.
/// options.IsGap = true
/// </summary>
public const string WHITE_SPACE = @"\s+";
private Regex _regex;
public Token[] Tokenize(string text, TokenizationOptions options)
{
_regex = new Regex(options.Pattern);
var matches = _regex.Matches(text).Cast<Match>().ToArray();
options.IsGap = new string[] { WHITE_SPACE, BLANK_LINE }.Contains(options.Pattern);
if (options.IsGap)
{
int pos = 0;
int span = 0;
var tokens = matches.Select(x =>
{
var token = new Token
{
Text = (span == matches.Length - 1) ? text.Substring(pos) : text.Substring(pos, x.Index - pos),
Offset = pos
};
pos = x.Index + 1;
if (span == matches.Length - 1)
{
}
span++;
return token;
}).ToArray();
return tokens;
}
else
{
return matches.Select(x => new Token
{
Text = x.Value,
Offset = x.Index
}).ToArray();
}
}
}
}

View file

@ -2,9 +2,9 @@
using System.Collections.Generic;
using System.Text;
namespace BotSharp.MachineLearning.NLP
namespace BotSharp.NLP.Tokenize
{
public class NlpToken
public class Token
{
public string Text { get; set; }
public int Offset { get; set; }
@ -15,7 +15,7 @@ namespace BotSharp.MachineLearning.NLP
{
get
{
return Offset + Text.Length;
return Offset + Text.Length - 1;
}
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.NLP.Tokenize
{
public class TokenizationOptions
{
/// <summary>
/// Regex pattern
/// </summary>
public string Pattern { get; set; }
/// <summary>
/// True if this tokenizer's pattern should be used to find separators between tokens;
/// False if this tokenizer's pattern should be used to find the tokens themselves.
/// </summary>
public bool IsGap { get; set; }
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.NLP.Tokenize
{
/// <summary>
/// BotSharp Tokenizer Factory
/// Tokenizers divide strings into lists of substrings.
/// The particular tokenizer requires implement interface
/// models to be installed.BotSharp.NLP also provides a simpler, regular-expression based tokenizer, which splits text on whitespace and punctuation.
/// </summary>
public class TokenizerFactory<ITokenize> where ITokenize : ITokenizer, new()
{
private ITokenize _tokenizer;
public TokenizerFactory()
{
_tokenizer = new ITokenize();
}
public Token[] Tokenize(string text, TokenizationOptions options)
{
return _tokenizer.Tokenize(text, options);
}
}
}

View file

@ -48,7 +48,7 @@ namespace BotSharp.RestApi
[HttpGet("{agentId}")]
public ActionResult Restore([FromRoute] String agentId)
{
var botsHeaderFilePath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), $"DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json");
var botsHeaderFilePath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), $"DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json");
var agents = JsonConvert.DeserializeObject<List<AgentImportHeader>>(System.IO.File.ReadAllText(botsHeaderFilePath));
var rasa = new BotSharpAi();

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Haiping Chen</Authors>
<Company>Personal</Company>
@ -15,6 +15,7 @@
<PackageLicenseUrl>https://github.com/Oceania2018/BotSharp/blob/master/LICENSE</PackageLicenseUrl>
<PackageTags>NLU, Chatbot, Bot, AI Bot</PackageTags>
<PackageReleaseNotes>Restful API for BotSharp.Core</PackageReleaseNotes>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -22,10 +23,19 @@
<DefineConstants>TRACE;DEBUG;MODE_RASA</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DocumentationFile>bin\Debug\netcoreapp2.1\BotSharp.RestApi.xml</DocumentationFile>
<DefineConstants>TRACE;DEBUG;MODE_RASA</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;MODE_DIALOGFLOW;RELEASE;NETCOREAPP;NETCOREAPP2_1;RELEASE;NETCOREAPP;NETCOREAPP2_1</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DefineConstants>TRACE;MODE_DIALOGFLOW;RELEASE;NETCOREAPP;NETCOREAPP2_1;RELEASE;NETCOREAPP;NETCOREAPP2_1</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.1" />
</ItemGroup>

View file

@ -2,6 +2,7 @@
using BotSharp.Core.Engines;
using BotSharp.Core.Engines.Dialogflow;
using BotSharp.Core.Models;
using BotSharp.NLP;
using BotSharp.RestApi.Integrations.FacebookMessenger;
using DotNetToolkit;
using EntityFrameworkCore.BootKit;

View file

@ -1,5 +1,6 @@
using BotSharp.Core.Engines;
using BotSharp.Core.Models;
using BotSharp.NLP;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;

View file

@ -38,16 +38,16 @@ namespace BotSharp.RestApi.Rasa
}
// save corpus to agent dir
var projectPath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects");
var dataPath = Path.Join(projectPath, project);
var agentPath = Path.Join(dataPath, "Temp");
var projectPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects");
var dataPath = Path.Combine(projectPath, project);
var agentPath = Path.Combine(dataPath, "Temp");
if (!Directory.Exists(agentPath))
{
Directory.CreateDirectory(agentPath);
}
var fileName = Path.Join(agentPath, "corpus.json");
var fileName = Path.Combine(agentPath, "corpus.json");
System.IO.File.WriteAllText(fileName, JsonConvert.SerializeObject(request.Corpus, new JsonSerializerSettings
{

View file

@ -47,7 +47,7 @@ namespace BotSharp.UnitTest
public void RestoreAgentFromDialogflowToRasaTest()
{
string dataPath = AppDomain.CurrentDomain.GetData("DataPath").ToString();
var botsHeaderFilePath = Path.Join(dataPath, "DbInitializer", $"Agents{Path.DirectorySeparatorChar}agents.json");
var botsHeaderFilePath = Path.Combine(dataPath, "DbInitializer", $"Agents{Path.DirectorySeparatorChar}agents.json");
var agents = JsonConvert.DeserializeObject<List<AgentImportHeader>>(File.ReadAllText(botsHeaderFilePath));
agents.ForEach(agentHeader => {

View file

@ -1,9 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>

View file

@ -1,6 +1,7 @@
using BotSharp.Core.Engines;
using BotSharp.Core.Engines.Dialogflow;
using BotSharp.Core.Models;
using BotSharp.NLP;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;

View file

@ -26,7 +26,7 @@ namespace BotSharp.UnitTest
configurationBuilder.AddJsonFile(setting, optional: false, reloadOnChange: true);
});
AppDomain.CurrentDomain.SetData("DataPath", Path.Join(contentRoot, "App_Data"));
AppDomain.CurrentDomain.SetData("DataPath", Path.Combine(contentRoot, "App_Data"));
AppDomain.CurrentDomain.SetData("Configuration", configurationBuilder.Build());
AppDomain.CurrentDomain.SetData("ContentRootPath", contentRoot);
AppDomain.CurrentDomain.SetData("Assemblies", new String[] { "BotSharp.Core" });

View file

@ -3,12 +3,17 @@
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>Portable;win10-x64;centos.7-x64</RuntimeIdentifiers>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;MODE_RASA</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DefineConstants>TRACE;DEBUG;MODE_RASA</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="App_Data\ModelFiles\**" />
<Compile Remove="App_Data\NewFolder\**" />

View file

@ -1,12 +1,9 @@
using BotSharp.Core.Abstractions;
using DotNetToolkit;
using EntityFrameworkCore.BootKit;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BotSharp.WebHost
{
@ -18,7 +15,8 @@ namespace BotSharp.WebHost
{
var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies");
var appsLoaders1 = TypeHelper.GetInstanceWithInterface<IInitializationLoader>(assemblies);
appsLoaders1.ForEach(loader => {
appsLoaders1.ForEach(loader =>
{
loader.Initialize(Config, Env);
});
}

View file

@ -1,12 +1,8 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace BotSharp.WebHost
{
@ -19,11 +15,13 @@ namespace BotSharp.WebHost
public static IWebHost BuildWebHost(string[] args) =>
Microsoft.AspNetCore.WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) => {
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
var settings = Directory.GetFiles($"{env.ContentRootPath}{Path.DirectorySeparatorChar}Settings", "*.json");
settings.ToList().ForEach(setting => {
settings.ToList().ForEach(setting =>
{
config.AddJsonFile(setting, optional: false, reloadOnChange: true);
});
})

View file

@ -1,23 +1,19 @@
using System;
using System.IO;
using System.Linq;
using BotSharp.Core.Agents;
using BotSharp.Core.Engines;
using DotNetToolkit;
using DotNetToolkit.JwtHelper;
using EntityFrameworkCore.BootKit;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Newtonsoft.Json.Serialization;
using Swashbuckle.AspNetCore.Swagger;
using BotSharp.Core.Engines.BotSharp;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using DotNetToolkit.JwtHelper;
using BotSharp.Core.Agents;
using System.IO;
using System.Linq;
namespace BotSharp.WebHost
{
@ -124,7 +120,7 @@ namespace BotSharp.WebHost
app.UseMvc();
AppDomain.CurrentDomain.SetData("DataPath", Path.Join(env.ContentRootPath, "App_Data"));
AppDomain.CurrentDomain.SetData("DataPath", Path.Combine(env.ContentRootPath, "App_Data"));
AppDomain.CurrentDomain.SetData("Configuration", Configuration);
AppDomain.CurrentDomain.SetData("ContentRootPath", env.ContentRootPath);
AppDomain.CurrentDomain.SetData("Assemblies", Configuration.GetValue<String>("Assemblies").Split(','));

View file

@ -13,6 +13,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.WebHost", "BotShar
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.MachineLearning", "BotSharp.MachineLearning\BotSharp.MachineLearning.csproj", "{E664115A-AE86-49E9-8AE4-D4589A568CD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.NLP", "BotSharp.NLP\BotSharp.NLP.csproj", "{D60A6A0A-4428-4460-868E-18CB5C7DA20F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.NLP.UnitTest", "BotSharp.NLP.UnitTest\BotSharp.NLP.UnitTest.csproj", "{2A8C199C-FD8E-4CB7-A83B-08F50F809AE8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -39,6 +43,14 @@ Global
{E664115A-AE86-49E9-8AE4-D4589A568CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E664115A-AE86-49E9-8AE4-D4589A568CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E664115A-AE86-49E9-8AE4-D4589A568CD7}.Release|Any CPU.Build.0 = Release|Any CPU
{D60A6A0A-4428-4460-868E-18CB5C7DA20F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D60A6A0A-4428-4460-868E-18CB5C7DA20F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D60A6A0A-4428-4460-868E-18CB5C7DA20F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D60A6A0A-4428-4460-868E-18CB5C7DA20F}.Release|Any CPU.Build.0 = Release|Any CPU
{2A8C199C-FD8E-4CB7-A83B-08F50F809AE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A8C199C-FD8E-4CB7-A83B-08F50F809AE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A8C199C-FD8E-4CB7-A83B-08F50F809AE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A8C199C-FD8E-4CB7-A83B-08F50F809AE8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -1,6 +1,6 @@
# <img src="https://raw.githubusercontent.com/Oceania2018/BotSharp/master/BotSharp.WebHost/wwwroot/images/BotSharp.png" height="30">
### The Open Source AI Chatbot Platform Builder for Enterprise
### The Open Source AI Bot Platform Builder for Enterprise
#### Open up as much learning power as possible for your enterprise 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 enterprise information systems. Out-of-the-box machine learning algorithms allow ordinary programmers to develop artificial intelligence applications faster and easier.
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/C++ interfaces directly which skips the python interfaces. That will facilitate the feature of the typed language C#, and be more easier when refactoring code in system scope.