diff --git a/.editorconfig b/.editorconfig
index e56cfa722..668528ada 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,8 +4,79 @@
indent_style = space
charset = utf-8
# prevent linux/windows problem
-end_of_line = lf
+end_of_line = lf
+csharp_using_directive_placement = outside_namespace:silent
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_prefer_braces = true:silent
+csharp_style_namespace_declarations = block_scoped:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+csharp_indent_labels = one_less_than_current
# Xml files
[*.{xml,csproj}]
indent_size = 2
+
+[*.{cs,vb}]
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index b8162b2f6..91cb7a0a5 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
-custom: ['https://bit.ly/2op1mu5'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+custom: ['https://www.paypal.com/pool/9avinmEbbb?sr=wccr'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..ed4cf5653
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,44 @@
+name: build
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+ - windows-latest
+ - macos-latest
+ runs-on: ${{matrix.os}}
+ steps:
+ - uses: actions/checkout@v1
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: '8.0.x'
+ - name: Set env
+ run: |
+ echo "DOTNET_CLI_TELEMETRY_OPTOUT=1" >> $GITHUB_ENV
+ echo "DOTNET_hostBuilder:reloadConfigOnChange=false" >> $GITHUB_ENV
+ - name: Install required workloads
+ run: |
+ dotnet workload install aspire --source https://aka.ms/dotnet8/nuget/index.json --source https://api.nuget.org/v3/index.json
+ - name: Clean
+ run: |
+ dotnet clean ./BotSharp.sln --configuration Release
+ dotnet nuget locals all --clear
+ - name: Build
+ run: dotnet build ./BotSharp.sln -c Release
+ - name: Test
+ run: |
+ cd ./tests/UnitTest
+ dotnet test --logger "console;verbosity=detailed"
+ cd ../BotSharp.Plugin.SemanticKernel.UnitTests
+ dotnet test --logger "console;verbosity=detailed"
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index c27958857..126bcaff9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -283,12 +283,15 @@ __pycache__/
*.btm.cs
*.odx.cs
*.xsd.cs
-/BotSharp.WebHost/App_Data/BotSharp.db
-/BotSharp.UI
-/BotSharp.WebHost/App_Data/Projects
-/BotSharp.WebHost/PublishOutput
-/Data
+
/docs/_build
-*.RestApi.xml
-/BotSharp.WebHost/App_Data/AgentStorage
-/BotSharp.WebHost/App_Data/SessionStorage
+*.bin
+src/WebStarter/Properties/PublishProfiles
+src/WebStarter/Properties/ServiceDependencies
+XMLs
+logs
+wwwroot
+appsettings.Production.json
+*.csproj.user
+env/
+FodyWeavers.*
\ No newline at end of file
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 000000000..8024c2d66
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,35 @@
+# Read the Docs configuration file for Sphinx projects
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version and other tools you might need
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+ # You can also specify other tool versions:
+ # nodejs: "20"
+ # rust: "1.70"
+ # golang: "1.20"
+
+# Build documentation in the "docs/" directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+ # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
+ # builder: "dirhtml"
+ # Fail on all warnings to avoid broken references
+ # fail_on_warning: true
+
+# Optionally build your docs in additional formats such as PDF and ePub
+# formats:
+# - pdf
+# - epub
+
+# Optional but recommended, declare the Python requirements required
+# to build your documentation
+# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
+python:
+ install:
+ - requirements: docs/requirements.txt
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..7894fed44
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "aspire.enableSettingsFileCreationPromptOnStartup": false
+}
\ No newline at end of file
diff --git a/BotSharp.Channel.FacebookMessenger/BotSharp.Channel.FacebookMessenger.csproj b/BotSharp.Channel.FacebookMessenger/BotSharp.Channel.FacebookMessenger.csproj
deleted file mode 100644
index 4c70e8616..000000000
--- a/BotSharp.Channel.FacebookMessenger/BotSharp.Channel.FacebookMessenger.csproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- $(DefaultTargetFramework)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BotSharp.Channel.FacebookMessenger/Controllers/FacebookMessengerController.cs b/BotSharp.Channel.FacebookMessenger/Controllers/FacebookMessengerController.cs
deleted file mode 100644
index 458a84bac..000000000
--- a/BotSharp.Channel.FacebookMessenger/Controllers/FacebookMessengerController.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using BotSharp.Channel.FacebookMessenger.Models;
-using BotSharp.Platform.Models;
-using EntityFrameworkCore.BootKit;
-using Microsoft.AspNetCore.Mvc;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Serialization;
-using RestSharp;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Channel.FacebookMessenger.Controllers
-{
- [Route("v1/[controller]")]
- public class FacebookMessengerController : ControllerBase
- {
- [HttpGet("{agentId}")]
- public ActionResult Verify([FromRoute] string agentId)
- {
- var mode = Request.Query.ContainsKey("hub.mode") ? Request.Query["hub.mode"].ToString() : String.Empty;
- var token = Request.Query.ContainsKey("hub.verify_token") ? Request.Query["hub.verify_token"].ToString() : String.Empty;
- var challenge = Request.Query.ContainsKey("hub.challenge") ? Request.Query["hub.challenge"].ToString() : String.Empty;
-
- if (mode == "subscribe")
- {
- var dc = new DefaultDataContextLoader().GetDefaultDc();
- var config = dc.Table().FirstOrDefault(x => x.AgentId == agentId && x.Platform == "Facebook Messenger");
-
- return config.VerifyToken == token ? Ok(challenge) : Ok(agentId);
- }
-
- return BadRequest();
- }
-
- [HttpPost("{agentId}")]
- public async Task CallbackAsync([FromRoute] string agentId)
- {
- WebhookEvent body;
- IWebhookMessageBody response = null;
-
- using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
- {
- var json = await reader.ReadToEndAsync();
- body = JsonConvert.DeserializeObject(json);
- }
-
- body.Entry.ForEach(entry =>
- {
- entry.Messaging.ForEach(msg =>
- {
- // received text message
- if (msg.Message.ContainsKey("text"))
- {
- OnTextMessaged(agentId, new WebhookMessage
- {
- Sender = msg.Sender,
- Recipient = msg.Recipient,
- Timestamp = msg.Timestamp,
- Message = msg.Message.ToObject()
- });
- }
- });
-
- });
-
- return Ok();
- }
-
- private void OnTextMessaged(string agentId, WebhookMessage message)
- {
- Console.WriteLine($"OnTextMessaged: {message.Message.Text}");
-
- /*var ai = new ApiAi();
- var agent = ai.LoadAgent(agentId);
- ai.AiConfig = new AIConfiguration(agent.ClientAccessToken, SupportedLanguage.English) { AgentId = agentId };
- ai.AiConfig.SessionId = message.Sender.Id;
- var aiResponse = ai.TextRequest(new AIRequest { Query = new String[] { message.Message.Text } });
-
- var dc = new DefaultDataContextLoader().GetDefaultDc();
- var config = dc.Table().FirstOrDefault(x => x.AgentId == agentId && x.Platform == "Facebook Messenger");
-
- SendTextMessage(config.AccessToken, new WebhookMessage
- {
- Recipient = message.Sender.ToObject(),
- Message = new WebhookTextMessage
- {
- Text = String.IsNullOrEmpty(aiResponse.Result.Fulfillment.Speech) ? aiResponse.Result.Action : aiResponse.Result.Fulfillment.Speech
- }
- });*/
- }
-
- private void SendTextMessage(string accessToken, WebhookMessage body)
- {
- var client = new RestClient("https://graph.facebook.com");
-
- var rest = new RestRequest("v2.6/me/messages", Method.POST);
- string json = JsonConvert.SerializeObject(body,
- new JsonSerializerSettings
- {
- ContractResolver = new CamelCasePropertyNamesContractResolver(),
- NullValueHandling = NullValueHandling.Ignore
- });
-
- rest.AddParameter("application/json", json, ParameterType.RequestBody);
- rest.AddQueryParameter("access_token", accessToken);
-
- var response = client.Execute(rest);
- }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/IWebhookMessageBody.cs b/BotSharp.Channel.FacebookMessenger/IWebhookMessageBody.cs
deleted file mode 100644
index 19d72ace6..000000000
--- a/BotSharp.Channel.FacebookMessenger/IWebhookMessageBody.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger
-{
- public interface IWebhookMessageBody
- {
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookEvent.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookEvent.cs
deleted file mode 100644
index d4ba1d72a..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookEvent.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookEvent
- {
- public string Object { get; set; }
- public List Entry { get; set; }
- }
-
-
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookEventEntry.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookEventEntry.cs
deleted file mode 100644
index 4889fb972..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookEventEntry.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookEventEntry
- {
- public string Id { get; set; }
- public long Time { get; set; }
- public List Messaging { get; set; }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessage.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookMessage.cs
deleted file mode 100644
index e06642f7f..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessage.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookMessage
- {
- public WebhookMessageSender Sender { get; set; }
-
- public WebhookMessageRecipient Recipient { get; set; }
-
- public long Timestamp { get; set; }
-
- public JObject Message { get; set; }
- }
-
- public class WebhookMessage where TWebhookMessage : IWebhookMessageBody
- {
- public WebhookMessageSender Sender { get; set; }
-
- public WebhookMessageRecipient Recipient { get; set; }
-
- public long Timestamp { get; set; }
-
- public TWebhookMessage Message { get; set; }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageQuickReply.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageQuickReply.cs
deleted file mode 100644
index b67f9a238..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageQuickReply.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookMessageQuickReply
- {
- public String Payload { get; set; }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageRecipient.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageRecipient.cs
deleted file mode 100644
index cba0f51ae..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageRecipient.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookMessageRecipient
- {
- ///
- /// PAGE_ID
- ///
- public String Id { get; set; }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageSender.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageSender.cs
deleted file mode 100644
index 888aadfa1..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookMessageSender.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookMessageSender
- {
- ///
- /// PSID
- ///
- public String Id { get; set; }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/Models/WebhookTextMessage.cs b/BotSharp.Channel.FacebookMessenger/Models/WebhookTextMessage.cs
deleted file mode 100644
index 16d0fa73f..000000000
--- a/BotSharp.Channel.FacebookMessenger/Models/WebhookTextMessage.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Channel.FacebookMessenger.Models
-{
- public class WebhookTextMessage : IWebhookMessageBody
- {
- public string Mid { get; set; }
- public String Text { get; set; }
- [JsonProperty("quick_reply")]
- public WebhookMessageQuickReply QuickReply { get; set; }
- }
-}
diff --git a/BotSharp.Channel.FacebookMessenger/ModuleInjector.cs b/BotSharp.Channel.FacebookMessenger/ModuleInjector.cs
deleted file mode 100644
index 4a5f52184..000000000
--- a/BotSharp.Channel.FacebookMessenger/ModuleInjector.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using BotSharp.Core.Modules;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using System;
-
-namespace BotSharp.Channel.FacebookMessenger
-{
- public class ModuleInjector : IModule
- {
- public void ConfigureServices(IServiceCollection services, IConfiguration config)
- {
-
- }
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env/*, IOptions senparcSetting, IOptions senparcWeixinSetting*/)
- {
-
- }
- }
-}
diff --git a/BotSharp.Channel.Weixin/BotSharp.Channel.Weixin.csproj b/BotSharp.Channel.Weixin/BotSharp.Channel.Weixin.csproj
deleted file mode 100644
index c5cf908a1..000000000
--- a/BotSharp.Channel.Weixin/BotSharp.Channel.Weixin.csproj
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- $(DefaultTargetFramework)
- true
-
-
-
- Haiping Chen
- https://github.com/Oceania2018/botsharp-channel-weixin
- git
- https://github.com/Oceania2018/botsharp-channel-weixin
- Apache 2.0
- botsharp, wechat, wexin, chatbot
- 0.1.1
-
-
-
- DEBUG;TRACE
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BotSharp.Channel.Weixin/Controllers/WeixinAsyncController.cs b/BotSharp.Channel.Weixin/Controllers/WeixinAsyncController.cs
deleted file mode 100644
index fa7ffa11f..000000000
--- a/BotSharp.Channel.Weixin/Controllers/WeixinAsyncController.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using BotSharp.Channel.Weixin.Models;
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Dialogflow.Models;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
-using Senparc.CO2NET.AspNet.HttpUtility;
-using Senparc.CO2NET.HttpUtility;
-using Senparc.Weixin.MP;
-using Senparc.Weixin.MP.Entities.Request;
-using Senparc.Weixin.MP.MvcExtension;
-using System;
-using System.IO;
-using System.Threading.Tasks;
-
-namespace BotSharp.Channel.Weixin.Controllers
-{
- ///
- /// 此Controller为异步Controller(Action),使用异步线程处理并发请求。
- /// 为了方便演示,此Controller中没有加入多余的日志记录等示例,保持了最简单的Controller写法。日志等其他操作可以参考WeixinController.cs。
- /// 提示:异步Controller并不是在任何情况下都能提升效率(响应时间),当请求量非常小的时候反而会增加一定的开销。
- ///
- [Route("weixin")]
- public class WeixinAsyncController : ControllerBase
- {
- readonly Func _getRandomFileName = () => DateTime.Now.ToString("yyyyMMdd-HHmmss") + "_Async_" + Guid.NewGuid().ToString("n").Substring(0, 6);
-
- readonly IConfiguration config;
- private IPlatformBuilder builder;
-
- public WeixinAsyncController(IPlatformBuilder platform, IConfiguration configuration)
- {
- config = configuration;
- builder = platform;
- }
-
- [HttpGet]
- public Task Get(string signature, string timestamp, string nonce, string echostr)
- {
- var token = config.GetValue("weixinChannel:token");
- return Task.Factory.StartNew(() =>
- {
- if (CheckSignature.Check(signature, timestamp, nonce, token))
- {
- return echostr; //返回随机字符串则表示验证通过
- }
- else
- {
- return "failed:" + signature + "," + Senparc.Weixin.MP.CheckSignature.GetSignature(timestamp, nonce, token) + "。" +
- "如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。";
- }
- }).ContinueWith(task => Content(task.Result));
- }
-
- public CustomMessageHandler MessageHandler = null;//开放出MessageHandler是为了做单元测试,实际使用过程中不需要
-
- ///
- /// 最简化的处理流程
- ///
- [HttpPost]
- public async Task Post(PostModel postModel)
- {
- var token = config.GetValue("weixinChannel:token");
-
- if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, token))
- {
- return new WeixinResult("参数错误!");
- }
-
- postModel.Token = token;
- postModel.EncodingAESKey = config.GetValue("weixinChannel:encodingAESKey");
- postModel.AppId = config.GetValue("weixinChannel:appId");
-
- var messageHandler = new CustomMessageHandler(builder, config, Request.GetRequestMemoryStream(), postModel, 10);
-
- messageHandler.DefaultMessageHandlerAsyncEvent = Senparc.NeuChar.MessageHandlers.DefaultMessageHandlerAsyncEvent.SelfSynicMethod;//没有重写的异步方法将默认尝试调用同步方法中的代码(为了偷懒)
-
- #region 设置消息去重
-
- /* 如果需要添加消息去重功能,只需打开OmitRepeatedMessage功能,SDK会自动处理。
- * 收到重复消息通常是因为微信服务器没有及时收到响应,会持续发送2-5条不等的相同内容的RequestMessage*/
- messageHandler.OmitRepeatedMessage = true;//默认已经开启,此处仅作为演示,也可以设置为false在本次请求中停用此功能
-
- #endregion
-
- #region 记录 Request 日志
-
- var logPath = Server.GetMapPath(string.Format("~/App_Data/MP/{0}/", DateTime.Now.ToString("yyyy-MM-dd")));
- if (!Directory.Exists(logPath))
- {
- Directory.CreateDirectory(logPath);
- }
-
- //测试时可开启此记录,帮助跟踪数据,使用前请确保App_Data文件夹存在,且有读写权限。
- messageHandler.RequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_{1}_{2}.txt", _getRandomFileName(),
- messageHandler.RequestMessage.FromUserName,
- messageHandler.RequestMessage.MsgType)));
- if (messageHandler.UsingEncryptMessage)
- {
- messageHandler.EcryptRequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_Ecrypt_{1}_{2}.txt", _getRandomFileName(),
- messageHandler.RequestMessage.FromUserName,
- messageHandler.RequestMessage.MsgType)));
- }
-
- #endregion
-
- await messageHandler.ExecuteAsync(new System.Threading.CancellationToken()); //执行微信处理过程
-
- #region 记录 Response 日志
-
- //测试时可开启,帮助跟踪数据
-
- //if (messageHandler.ResponseDocument == null)
- //{
- // throw new Exception(messageHandler.RequestDocument.ToString());
- //}
- if (messageHandler.ResponseDocument != null)
- {
- messageHandler.ResponseDocument.Save(Path.Combine(logPath, string.Format("{0}_Response_{1}_{2}.txt", _getRandomFileName(),
- messageHandler.ResponseMessage.ToUserName,
- messageHandler.ResponseMessage.MsgType)));
- }
-
- if (messageHandler.UsingEncryptMessage && messageHandler.FinalResponseDocument != null)
- {
- //记录加密后的响应信息
- messageHandler.FinalResponseDocument.Save(Path.Combine(logPath, string.Format("{0}_Response_Final_{1}_{2}.txt", _getRandomFileName(),
- messageHandler.ResponseMessage.ToUserName,
- messageHandler.ResponseMessage.MsgType)));
- }
-
- #endregion
-
- MessageHandler = messageHandler;//开放出MessageHandler是为了做单元测试,实际使用过程中不需要
-
- return new FixWeixinBugWeixinResult(messageHandler);
- }
- }
-}
diff --git a/BotSharp.Channel.Weixin/LocationService.cs b/BotSharp.Channel.Weixin/LocationService.cs
deleted file mode 100644
index ea21ab261..000000000
--- a/BotSharp.Channel.Weixin/LocationService.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*----------------------------------------------------------------
- Copyright (C) 2018 Senparc
-
- 文件名:LocationService.cs
- 文件功能描述:地理位置信息处理
-
-
- 创建标识:Senparc - 20150312
-----------------------------------------------------------------*/
-
-using System.Collections.Generic;
-using Senparc.Weixin.MP.Entities;
-using Senparc.CO2NET.Helpers.BaiduMap;
-using Senparc.CO2NET.Helpers.GoogleMap;
-using Senparc.Weixin.MP.Helpers;
-using Senparc.CO2NET.Helpers;
-using Senparc.NeuChar.Entities;
-
-namespace BotSharp.Channel.Weixin
-{
- public class LocationService
- {
- public ResponseMessageNews GetResponseMessage(RequestMessageLocation requestMessage)
- {
- var responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage);
-
- #region 百度地图
-
- {
- var markersList = new List();
- markersList.Add(new BaiduMarkers()
- {
- Longitude = requestMessage.Location_X,
- Latitude = requestMessage.Location_Y,
- Color = "red",
- Label = "S",
- Size = BaiduMarkerSize.m
- });
-
- var mapUrl = BaiduMapHelper.GetBaiduStaticMap(requestMessage.Location_X, requestMessage.Location_Y, 1, 6, markersList);
- responseMessage.Articles.Add(new Article()
- {
- Description = string.Format("【来自百度地图】您刚才发送了地理位置信息。Location_X:{0},Location_Y:{1},Scale:{2},标签:{3}",
- requestMessage.Location_X, requestMessage.Location_Y,
- requestMessage.Scale, requestMessage.Label),
- PicUrl = mapUrl,
- Title = "定位地点周边地图",
- Url = mapUrl
- });
- }
-
- #endregion
-
- #region GoogleMap
-
- {
- var markersList = new List();
- markersList.Add(new GoogleMapMarkers()
- {
- X = requestMessage.Location_X,
- Y = requestMessage.Location_Y,
- Color = "red",
- Label = "S",
- Size = GoogleMapMarkerSize.Default,
- });
- var mapSize = "480x600";
- var mapUrl = GoogleMapHelper.GetGoogleStaticMap(19 /*requestMessage.Scale*//*微信和GoogleMap的Scale不一致,这里建议使用固定值*/,
- markersList, mapSize);
- responseMessage.Articles.Add(new Article()
- {
- Description = string.Format("【来自GoogleMap】您刚才发送了地理位置信息。Location_X:{0},Location_Y:{1},Scale:{2},标签:{3}",
- requestMessage.Location_X, requestMessage.Location_Y,
- requestMessage.Scale, requestMessage.Label),
- PicUrl = mapUrl,
- Title = "定位地点周边地图",
- Url = mapUrl
- });
- }
-
- #endregion
-
-
- responseMessage.Articles.Add(new Article()
- {
- Title = "微信公众平台SDK 官网链接",
- Description = "Senparc.Weixin.MK SDK地址",
- PicUrl = "http://sdk.weixin.senparc.com/images/logo.jpg",
- Url = "http://sdk.weixin.senparc.com"
- });
-
- return responseMessage;
- }
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Channel.Weixin/Models/CustomMessageContext.cs b/BotSharp.Channel.Weixin/Models/CustomMessageContext.cs
deleted file mode 100644
index e5436b67a..000000000
--- a/BotSharp.Channel.Weixin/Models/CustomMessageContext.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-/*----------------------------------------------------------------
- Copyright (C) 2018 Senparc
-
- 文件名:CustomMessageContext.cs
- 文件功能描述:微信消息上下文
-
-
- 创建标识:Senparc - 20150312
-----------------------------------------------------------------*/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Linq;
-using Senparc.NeuChar;
-using Senparc.NeuChar.Context;
-using Senparc.NeuChar.Entities;
-using Senparc.Weixin.MP.MessageContexts;
-
-namespace BotSharp.Channel.Weixin.Models
-{
- public class CustomMessageContext : DefaultMpMessageContext
- {
- public CustomMessageContext()
- {
- base.MessageContextRemoved += CustomMessageContext_MessageContextRemoved;
- }
-
-
-
-
- ///
- /// 当上下文过期,被移除时触发的时间
- ///
- ///
- ///
- void CustomMessageContext_MessageContextRemoved(object sender, Senparc.NeuChar.Context.WeixinContextRemovedEventArgs e)
- {
- /* 注意,这个事件不是实时触发的(当然你也可以专门写一个线程监控)
- * 为了提高效率,根据WeixinContext中的算法,这里的过期消息会在过期后下一条请求执行之前被清除
- */
-
- var messageContext = e.MessageContext as CustomMessageContext;
- if (messageContext == null)
- {
- return;//如果是正常的调用,messageContext不会为null
- }
-
- //TODO:这里根据需要执行消息过期时候的逻辑,下面的代码仅供参考
-
- //Log.InfoFormat("{0}的消息上下文已过期",e.OpenId);
- //api.SendMessage(e.OpenId, "由于长时间未搭理客服,您的客服状态已退出!");
- }
- }
-}
diff --git a/BotSharp.Channel.Weixin/Models/CustomMessageHandler.cs b/BotSharp.Channel.Weixin/Models/CustomMessageHandler.cs
deleted file mode 100644
index 6b5486ba9..000000000
--- a/BotSharp.Channel.Weixin/Models/CustomMessageHandler.cs
+++ /dev/null
@@ -1,375 +0,0 @@
-/*----------------------------------------------------------------
- Copyright (C) 2018 Senparc
-
- 文件名:CustomMessageHandler.cs
- 文件功能描述:微信公众号自定义MessageHandler
-
-
- 创建标识:Senparc - 20150312
-
- 修改标识:Senparc - 20171027
- 修改描述:v14.8.3 添加OnUnknownTypeRequest()方法Demo
-
-----------------------------------------------------------------*/
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-
-using Senparc.Weixin.MP.Entities;
-using Senparc.Weixin.MP.Entities.Request;
-using Senparc.Weixin.MP.MessageHandlers;
-using Senparc.Weixin.MP.AdvancedAPIs;
-using System.Threading.Tasks;
-using Senparc.NeuChar.Entities.Request;
-using Senparc.NeuChar.Helpers;
-using Senparc.NeuChar.Entities;
-using Senparc.Weixin;
-using Senparc.Weixin.MP;
-using BotSharp.Platform.Models.AiRequest;
-using BotSharp.Platform.Abstractions;
-using Microsoft.Extensions.Configuration;
-using BotSharp.Platform.Dialogflow.Models;
-
-#if NET45
-using System.Web;
-using System.Configuration;
-using System.Web.Configuration;
-using Senparc.Weixin.MP.Sample.CommonService.Utilities;
-#else
-using Microsoft.AspNetCore.Http;
-#endif
-
-namespace BotSharp.Channel.Weixin.Models
-{
- ///
- /// 自定义MessageHandler
- /// 把MessageHandler作为基类,重写对应请求的处理方法
- ///
- public partial class CustomMessageHandler : MessageHandler
- {
- /*
- * 重要提示:v1.5起,MessageHandler提供了一个DefaultResponseMessage的抽象方法,
- * DefaultResponseMessage必须在子类中重写,用于返回没有处理过的消息类型(也可以用于默认消息,如帮助信息等);
- * 其中所有原OnXX的抽象方法已经都改为虚方法,可以不必每个都重写。若不重写,默认返回DefaultResponseMessage方法中的结果。
- */
-
-
-#if !DEBUG || NETSTANDARD1_6 || NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1
- string agentUrl = "http://localhost:12222/App/Weixin/4";
- string agentToken = "27C455F496044A87";
- string wiweihiKey = "CNadjJuWzyX5bz5Gn+/XoyqiqMa5DjXQ";
-#else
- //下面的Url和Token可以用其他平台的消息,或者到www.weiweihi.com注册微信用户,将自动在“微信营销工具”下得到
- private string agentUrl = Config.SenparcWeixinSetting.AgentUrl;//这里使用了www.weiweihi.com微信自动托管平台
- private string agentToken = Config.SenparcWeixinSetting.AgentToken;//Token
- private string wiweihiKey = Config.SenparcWeixinSetting.SenparcWechatAgentKey;//WeiweihiKey专门用于对接www.Weiweihi.com平台,获取方式见:http://www.weiweihi.com/ApiDocuments/Item/25#51
-#endif
-
-#if NET45
- private string appId = Config.SenparcWeixinSetting.WeixinAppId;
- private string appSecret = Config.SenparcWeixinSetting.WeixinAppSecret;
-#else
- private string appId = "appId";
- private string appSecret = "appSecret";
-#endif
-
- ///
- /// 模板消息集合(Key:checkCode,Value:OpenId)
- ///
- public static Dictionary TemplateMessageCollection = new Dictionary();
-
- private IPlatformBuilder nluPlatform = null;
- private readonly IConfiguration config;
-
- public CustomMessageHandler(IPlatformBuilder nluPlatform, IConfiguration configuration, Stream inputStream, PostModel postModel, int maxRecordCount = 0)
- : base(inputStream, postModel, maxRecordCount)
- {
- this.nluPlatform = nluPlatform;
- this.config = configuration;
-
- //这里设置仅用于测试,实际开发可以在外部更全局的地方设置,
- //比如MessageHandler.GlobalGlobalMessageContext.ExpireMinutes = 3。
- GlobalMessageContext.ExpireMinutes = 3;
-
- if (!string.IsNullOrEmpty(postModel.AppId))
- {
- appId = postModel.AppId;//通过第三方开放平台发送过来的请求
- }
-
- //在指定条件下,不使用消息去重
- base.OmitRepeatedMessageFunc = requestMessage =>
- {
- var textRequestMessage = requestMessage as RequestMessageText;
- if (textRequestMessage != null && textRequestMessage.Content == "容错")
- {
- return false;
- }
- return true;
- };
- }
-
- public override async Task OnExecutingAsync(CancellationToken cancellationToken)
- {
- var CurrentMessageContext = await GetCurrentMessageContext();
- //测试MessageContext.StorageData
- if (CurrentMessageContext.StorageData == null)
- {
- CurrentMessageContext.StorageData = 0;
- }
- await base.OnExecutingAsync(cancellationToken);
- }
-
- public override async Task OnExecutedAsync(CancellationToken cancellationToken)
- {
- var CurrentMessageContext = await GetCurrentMessageContext();
- CurrentMessageContext.StorageData = ((int)CurrentMessageContext.StorageData) + 1;
- await base.OnExecutedAsync(cancellationToken);
- }
-
- ///
- /// 处理文字请求
- ///
- ///
- public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
- {
- var defaultResponseMessage = base.CreateResponseMessage();
-
- var requestHandler =
- requestMessage.StartHandler()
- .Keyword("BotSharp",() =>
- {
- var result = new StringBuilder();
- result.AppendFormat("{0}", "你好!欢迎使用BotSharp NLU服务,BotSharp通过强大的自然语言理解技术让你更轻松的处理智能回复。");
- defaultResponseMessage.Content = result.ToString();
- return defaultResponseMessage;
- })
- .Keyword("再见", () =>
- {
- var result = new StringBuilder();
- result.AppendFormat("{0}", "谢谢使用,再见!");
- defaultResponseMessage.Content = result.ToString();
- return defaultResponseMessage;
- })
- .Default(() =>
- {
- var result = new StringBuilder();
-
- // send text to BotSharp platform emulator
- var aIResponse = nluPlatform.TextRequest(new AiRequest
- {
- Text = requestMessage.Content,
- AgentId = config.GetValue("weixinChannel:agentId"),
- SessionId = requestMessage.FromUserName
- });
-
- result.AppendFormat("{0}", aIResponse.Result.Fulfillment.Speech);
-
- defaultResponseMessage.Content = result.ToString();
- return defaultResponseMessage;
- });
-
- return requestHandler.GetResponseMessage() as IResponseMessageBase;
- }
-
- ///
- /// 处理位置请求
- ///
- ///
- ///
- public override IResponseMessageBase OnLocationRequest(RequestMessageLocation requestMessage)
- {
- var locationService = new LocationService();
- var responseMessage = locationService.GetResponseMessage(requestMessage as RequestMessageLocation);
- return responseMessage;
- }
-
- public override IResponseMessageBase OnShortVideoRequest(RequestMessageShortVideo requestMessage)
- {
- var responseMessage = this.CreateResponseMessage();
- responseMessage.Content = "您刚才发送的是小视频";
- return responseMessage;
- }
-
- ///
- /// 处理图片请求
- ///
- ///
- ///
- public override IResponseMessageBase OnImageRequest(RequestMessageImage requestMessage)
- {
- //一隔一返回News或Image格式
- if (base.GlobalMessageContext.GetMessageContext(requestMessage).RequestMessages.Count() % 2 == 0)
- {
- var responseMessage = CreateResponseMessage();
-
- responseMessage.Articles.Add(new Article()
- {
- Title = "您刚才发送了图片信息",
- Description = "您发送的图片将会显示在边上",
- PicUrl = requestMessage.PicUrl,
- Url = "http://sdk.weixin.senparc.com"
- });
- responseMessage.Articles.Add(new Article()
- {
- Title = "第二条",
- Description = "第二条带连接的内容",
- PicUrl = requestMessage.PicUrl,
- Url = "http://sdk.weixin.senparc.com"
- });
-
- return responseMessage;
- }
- else
- {
- var responseMessage = CreateResponseMessage();
- responseMessage.Image.MediaId = requestMessage.MediaId;
- return responseMessage;
- }
- }
-
- ///
- /// 处理语音请求
- ///
- ///
- ///
- public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
- {
- var responseMessage = CreateResponseMessage();
- //上传缩略图
- //var accessToken = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
- var uploadResult = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.image,
- Server.GetMapPath("~/Images/Logo.jpg"));
-
- //设置音乐信息
- responseMessage.Music.Title = "天籁之音";
- responseMessage.Music.Description = "播放您上传的语音";
- responseMessage.Music.MusicUrl = "http://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
- responseMessage.Music.HQMusicUrl = "http://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
- responseMessage.Music.ThumbMediaId = uploadResult.media_id;
-
- //推送一条客服消息
- try
- {
- CustomApi.SendText(appId, WeixinOpenId, "本次上传的音频MediaId:" + requestMessage.MediaId);
-
- }
- catch
- {
- }
-
- return responseMessage;
- }
- ///
- /// 处理视频请求
- ///
- ///
- ///
- public override IResponseMessageBase OnVideoRequest(RequestMessageVideo requestMessage)
- {
- var responseMessage = CreateResponseMessage();
- responseMessage.Content = "您发送了一条视频信息,ID:" + requestMessage.MediaId;
-
- #region 上传素材并推送到客户端
-
- Task.Factory.StartNew(async () =>
- {
- //上传素材
- var dir = Server.GetMapPath("~/App_Data/TempVideo/");
- var file = await MediaApi.GetAsync(appId, requestMessage.MediaId, dir);
- var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, UploadMediaFileType.video, file, 50000);
- await CustomApi.SendVideoAsync(appId, base.WeixinOpenId, uploadResult.media_id, "这是您刚才发送的视频", "这是一条视频消息");
- }).ContinueWith(async task =>
- {
- if (task.Exception != null)
- {
- WeixinTrace.Log("OnVideoRequest()储存Video过程发生错误:", task.Exception.Message);
-
- var msg = string.Format("上传素材出错:{0}\r\n{1}",
- task.Exception.Message,
- task.Exception.InnerException != null
- ? task.Exception.InnerException.Message
- : null);
- await CustomApi.SendTextAsync(appId, base.WeixinOpenId, msg);
- }
- });
-
- #endregion
-
- return responseMessage;
- }
-
-
- ///
- /// 处理链接消息请求
- ///
- ///
- ///
- public override IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage)
- {
- var responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage);
- responseMessage.Content = string.Format(@"您发送了一条连接信息:
-Title:{0}
-Description:{1}
-Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url);
- return responseMessage;
- }
-
- public override IResponseMessageBase OnFileRequest(RequestMessageFile requestMessage)
- {
- var responseMessage = requestMessage.CreateResponseMessage();
- responseMessage.Content = string.Format(@"您发送了一个文件:
-文件名:{0}
-说明:{1}
-大小:{2}
-MD5:{3}", requestMessage.Title, requestMessage.Description, requestMessage.FileTotalLen, requestMessage.FileMd5);
- return responseMessage;
- }
-
- ///
- /// 处理事件请求(这个方法一般不用重写,这里仅作为示例出现。除非需要在判断具体Event类型以外对Event信息进行统一操作
- ///
- ///
- ///
- public override IResponseMessageBase OnEventRequest(IRequestMessageEventBase requestMessage)
- {
- var eventResponseMessage = base.OnEventRequest(requestMessage);//对于Event下属分类的重写方法,见:CustomerMessageHandler_Events.cs
- //TODO: 对Event信息进行统一操作
- return eventResponseMessage;
- }
-
- public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
- {
- /* 所有没有被处理的消息会默认返回这里的结果,
- * 因此,如果想把整个微信请求委托出去(例如需要使用分布式或从其他服务器获取请求),
- * 只需要在这里统一发出委托请求,如:
- * var responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString());
- * return responseMessage;
- */
-
- var responseMessage = this.CreateResponseMessage();
- responseMessage.Content = "这条消息来自DefaultResponseMessage。";
- return responseMessage;
- }
-
-
- public override IResponseMessageBase OnUnknownTypeRequest(RequestMessageUnknownType requestMessage)
- {
- /*
- * 此方法用于应急处理SDK没有提供的消息类型,
- * 原始XML可以通过requestMessage.RequestDocument(或this.RequestDocument)获取到。
- * 如果不重写此方法,遇到未知的请求类型将会抛出异常(v14.8.3 之前的版本就是这么做的)
- */
- var msgType = Senparc.NeuChar.Helpers.MsgTypeHelper.GetRequestMsgTypeString(requestMessage.RequestDocument);
- var responseMessage = this.CreateResponseMessage();
- responseMessage.Content = "未知消息类型:" + msgType;
-
- WeixinTrace.SendCustomLog("未知请求消息类型", requestMessage.RequestDocument.ToString());//记录到日志中
-
- return responseMessage;
- }
- }
-}
diff --git a/BotSharp.Channel.Weixin/ModuleInjector.cs b/BotSharp.Channel.Weixin/ModuleInjector.cs
deleted file mode 100644
index a26f41ba3..000000000
--- a/BotSharp.Channel.Weixin/ModuleInjector.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using BotSharp.Core.Modules;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Senparc.CO2NET.RegisterServices;
-using Senparc.Weixin.RegisterServices;
-
-namespace BotSharp.Channel.Weixin
-{
- public class ModuleInjector : IModule
- {
- public void ConfigureServices(IServiceCollection services, IConfiguration config)
- {
- // Senparc.CO2NET, Senparc.Weixin
- services.AddSenparcGlobalServices(config)
- .AddSenparcWeixinServices(config);
- }
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env/*, IOptions senparcSetting, IOptions senparcWeixinSetting*/)
- {
-
- //https://github.com/Senparc/Senparc.CO2NET/blob/master/Sample/Senparc.CO2NET.Sample.netcore/Startup.cs
- /* IRegisterService register = RegisterService.Start(env, senparcSetting.Value)
- .UseSenparcGlobal();*/
- }
- }
-}
diff --git a/BotSharp.Channel.Weixin/README.md b/BotSharp.Channel.Weixin/README.md
deleted file mode 100644
index dcc516840..000000000
--- a/BotSharp.Channel.Weixin/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# botsharp-channel-weixin
-A channel module of BotSharp for Tencent Weixin
-
-### How to install through NuGet
-
-```
-PM> Install-Package BotSharp.Channel.Weixin
-```
-
-### How to run locally
-```
-git clone https://github.com/dotnetcore/BotSharp
-```
-
-Check app.json to use DialogflowAi
-```
-{
- "version": "0.1.0",
- "assemblies": "BotSharp.Core",
-
- "platformModuleName": "DialogflowAi"
-}
-```
-
-Update channels.weixin.json to set the corresponding KEY
-```
-{
- "weixinChannel": {
- "token": "botsharp",
- "encodingAESKey": "",
- "appId": "",
- "agentId": "60bee6f9-ba58-4fe8-8b95-94af69d6fd41"
- }
-}
-```
-
-F5 run BotSharp.WebHost
-
-Access http://localhost:3112
-
-Import demo (Spotify.zip) agent located at App_Data
-
-Train agent (id: 60bee6f9-ba58-4fe8-8b95-94af69d6fd41)
-
-Or refer [BotSharp docs](https://botsharp.readthedocs.io) to design your new chatbot.
-
-Setup Wechat webhood from https://mp.weixin.qq.com/.
diff --git a/BotSharp.Channel.Weixin/Server.cs b/BotSharp.Channel.Weixin/Server.cs
deleted file mode 100644
index df286e4a0..000000000
--- a/BotSharp.Channel.Weixin/Server.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-#if NET45
-using System.Web;
-#else
-using Microsoft.AspNetCore.Http;
-#endif
-
-namespace BotSharp.Channel.Weixin
-{
- public static class Server
- {
- private static string _appDomainAppPath;
- public static string AppDomainAppPath
- {
- get
- {
- if (_appDomainAppPath == null)
- {
-#if NET45
- _appDomainAppPath = HttpRuntime.AppDomainAppPath;
-#else
- _appDomainAppPath = AppContext.BaseDirectory; //dll所在目录:;
-#endif
- }
- return _appDomainAppPath;
- }
- set
- {
- _appDomainAppPath = value;
-#if NETSTANDARD1_6 || NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1
- if (!_appDomainAppPath.EndsWith("/"))
- {
- _appDomainAppPath += "/";
- }
-#endif
- }
- }
-
- private static string _webRootPath;
- ///
- /// wwwroot文件夹目录(专供ASP.NET Core MVC使用)
- ///
- public static string WebRootPath
- {
- get
- {
- if (_webRootPath == null)
- {
-#if NET45
- _webRootPath = AppDomainAppPath;
-#else
- _webRootPath = AppDomainAppPath + "wwwroot/";//asp.net core的wwwroot文件目录结构不一样
-#endif
- }
- return _webRootPath;
- }
- set { _webRootPath = value; }
- }
-
- public static string GetMapPath(string virtualPath)
- {
- if (virtualPath == null)
- {
- return "";
- }
- else if (virtualPath.StartsWith("~/"))
- {
- return virtualPath.Replace("~/", AppDomainAppPath);
- }
- else
- {
- return Path.Combine(AppDomainAppPath, virtualPath);
- }
- }
-
- public static HttpContext HttpContext
- {
- get
- {
-#if NET45
- HttpContext context = HttpContext.Current;
- if (context == null)
- {
- HttpRequest request = new HttpRequest("Default.aspx", "http://sdk.weixin.senparc.com/default.aspx", null);
- StringWriter sw = new StringWriter();
- HttpResponse response = new HttpResponse(sw);
- context = new HttpContext(request, response);
- }
-#else
- HttpContext context = new DefaultHttpContext();
-#endif
- return context;
- }
- }
- }
-}
diff --git a/BotSharp.Core.UnitTest/AgentTest.cs b/BotSharp.Core.UnitTest/AgentTest.cs
deleted file mode 100644
index 6e7a3b0a0..000000000
--- a/BotSharp.Core.UnitTest/AgentTest.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using BotSharp.Core.Engines;
-using EntityFrameworkCore.BootKit;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Core.UnitTest
-{
- [TestClass]
- public class AgentTest : TestEssential
- {
- /*[TestMethod]
- public void CreateAgentTest()
- {
- var agent = new Agent
- {
- Id = BOT_ID,
- Language = "en"
- };
- var rasa = new RasaAi();
- //int row = dc.DbTran(() => rasa.agent.SaveAgent(dc));
- }
-
- [TestMethod]
- public void UpdateAgentTest()
- {
- var agent = new Agent
- {
- Id = BOT_ID,
- Language = "en"
- };
- var rasa = new RasaAi();
- //int row = dc.DbTran(() => rasa.agent.SaveAgent(dc));
- }
-
- [TestMethod]
- public void RestoreAgentFromDialogflowToRasaTest()
- {
- string dataPath = AppDomain.CurrentDomain.GetData("DataPath").ToString();
- var botsHeaderFilePath = Path.Combine(dataPath, "DbInitializer", $"Agents{Path.DirectorySeparatorChar}agents.json");
- var agents = JsonConvert.DeserializeObject>(File.ReadAllText(botsHeaderFilePath));
-
- agents.ForEach(agentHeader => {
- var bot = new BotSharpAi();
- bot.LoadAgentFromFile(dataPath);
- bot.SaveAgentToDb();
- });
- }
-
- [TestMethod]
- public void TrainAgentTest()
- {
- var rasa = new RasaAi();
- rasa.LoadAgent(BOT_ID);
- rasa.Train();
- }*/
- }
-}
diff --git a/BotSharp.Core.UnitTest/BotSharp.Core.UnitTest.csproj b/BotSharp.Core.UnitTest/BotSharp.Core.UnitTest.csproj
deleted file mode 100644
index 5db15bbf5..000000000
--- a/BotSharp.Core.UnitTest/BotSharp.Core.UnitTest.csproj
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
- $(DefaultTargetFramework)
-
- false
-
- AnyCPU;x64
-
- Debug;Release;RASA NLU;DIALOGFLOW;RASA;ARTICULATE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BotSharp.Core.UnitTest/BotTrainerTest.cs b/BotSharp.Core.UnitTest/BotTrainerTest.cs
deleted file mode 100644
index 2ad2e8fd8..000000000
--- a/BotSharp.Core.UnitTest/BotTrainerTest.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using BotSharp.Core.Engines;
-using BotSharp.Platform.Models;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.UnitTest
-{
- [TestClass]
- public class BotTrainerTest : TestEssential
- {
- [TestMethod]
- public async void TrainingTest()
- {
- }
- }
-}
diff --git a/BotSharp.Core.UnitTest/ConversationTest.cs b/BotSharp.Core.UnitTest/ConversationTest.cs
deleted file mode 100644
index bb9f8f9be..000000000
--- a/BotSharp.Core.UnitTest/ConversationTest.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Core.UnitTest
-{
- [TestClass]
- public class ConversationTest : TestEssential
- {
- [TestMethod]
- public void TextRequest()
- {
- /*var ai = new ApiAi();
- var agent = ai.LoadAgent(BOT_ID);
- ai.AiConfig = new AIConfiguration(agent.ClientAccessToken, SupportedLanguage.English) { AgentId = BOT_ID };
- ai.AiConfig.SessionId = Guid.NewGuid().ToString();
-
- // Round 1
- var response = ai.TextRequest(new AIRequest { Query = new String[] { "Can you play country music?" } });
- Assert.AreEqual(response.Result.Metadata.IntentName, "music.play");
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "music-player-control").Lifespan, 3);
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "play-music").Lifespan, 5);
- Assert.AreEqual(response.Result.Parameters.First(x => x.Key == "genre").Value, "country");
-
- // Round 2
- response = ai.TextRequest(new AIRequest { Query = new String[] { "pause it" } });
- Assert.AreEqual(response.Result.Metadata.IntentName, "music_player_control.pause");
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "music-player-control").Lifespan, 3);
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "play-music").Lifespan, 4);
-
- // Round 3
- response = ai.TextRequest(new AIRequest { Query = new String[] { "continue" } });
- Assert.AreEqual(response.Result.Metadata.IntentName, "music_player_control.resume");
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "music-player-control").Lifespan, 3);
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "play-music").Lifespan, 3);
-
- // Round 4
- response = ai.TextRequest(new AIRequest { Query = new String[] { "play Hard Times by David Newman" } });
- Assert.AreEqual(response.Result.Metadata.IntentName, "music.play");
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "music-player-control").Lifespan, 3);
- Assert.AreEqual(response.Result.Contexts.First(x => x.Name == "play-music").Lifespan, 5);
- Assert.AreEqual(response.Result.Parameters.First(x => x.Key == "song").Value, "Hard Times");
- Assert.AreEqual(response.Result.Parameters.First(x => x.Key == "artist").Value, "David Newman");*/
- }
- }
-}
diff --git a/BotSharp.Core.UnitTest/EntityEntryTest.cs b/BotSharp.Core.UnitTest/EntityEntryTest.cs
deleted file mode 100644
index 87058cc8a..000000000
--- a/BotSharp.Core.UnitTest/EntityEntryTest.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.UnitTest
-{
- [TestClass]
- public class EntityEntryTest : TestEssential
- {
- [TestMethod]
- public void CreateEntityEntryTest()
- {
-
- }
-
- [TestMethod]
- public void UpdateEntityEntryeTest()
- {
-
- }
-
- [TestMethod]
- public void DeleteEntityEntryTest()
- {
-
- }
- }
-}
diff --git a/BotSharp.Core.UnitTest/EntityTypeTest.cs b/BotSharp.Core.UnitTest/EntityTypeTest.cs
deleted file mode 100644
index 3628c8613..000000000
--- a/BotSharp.Core.UnitTest/EntityTypeTest.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.UnitTest
-{
- [TestClass]
- public class EntityTypeTest : TestEssential
- {
- [TestMethod]
- public void CreateEntityTypeTest()
- {
-
- }
-
- [TestMethod]
- public void UpdateEntityTypeTest()
- {
-
- }
-
- [TestMethod]
- public void DeleteEntityTypeTest()
- {
-
- }
- }
-}
diff --git a/BotSharp.Core.UnitTest/Performance/Spotify.cs b/BotSharp.Core.UnitTest/Performance/Spotify.cs
deleted file mode 100644
index 601429716..000000000
--- a/BotSharp.Core.UnitTest/Performance/Spotify.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using BotSharp.Core.Engines;
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Core.UnitTest.Performance
-{
- [TestClass]
- public class Spotify : TestEssential
- {
- //private List> Samples;
- private IBotEngine _platform;
-
- [TestMethod]
- public void IntentAccuracy()
- {
- int correct = 0;
- List> errors = new List>();
-
- // var agent = LoadAgent();
-
- /*for (int i = 0; i < Samples.Count; i++)
- {
- var aIResponse = _platform.TextRequest(Samples[i].Item1);
- if (aIResponse.Result.Metadata.IntentName == Samples[i].Item2)
- {
- correct++;
- }
- else
- {
- errors.Add(new Tuple(Samples[i].Item2, Samples[i].Item1.Query[0]));
- }
- }*/
-
- //double accuracy = correct / (Samples.Count + 0.0);
- }
-
- private AgentBase LoadAgent()
- {
- //_platform = new BotSharpAi();
-
- // Load agent
- var projectPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", "Spotify");
- string model = Directory.GetDirectories(projectPath).Where(x => x.Contains("model_")).Last().Split(Path.DirectorySeparatorChar).Last();
- var modelPath = Path.Combine(projectPath, model);
- /*var agent = _platform.LoadAgentFromFile(modelPath);
-
- // Init samples
- Samples = new List>();
- agent.Corpus.UserSays.ForEach(intent =>
- {
- Samples.Add(new Tuple(new AIRequest
- {
- AgentDir = projectPath,
- Model = model,
- Query = new String[]
- {
- intent.Text
- }
- }, intent.Intent));
- });
-
- Samples.Shuffle();*/
-
- //var samples = String.Join("\r\n", Samples.Select(x => $"__label__{x.Item2} {x.Item1.Query[0]}").ToList());
-
- return null;
- }
- }
-}
diff --git a/BotSharp.Core.UnitTest/TestEssential.cs b/BotSharp.Core.UnitTest/TestEssential.cs
deleted file mode 100644
index fae973f33..000000000
--- a/BotSharp.Core.UnitTest/TestEssential.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using BotSharp.Core.Engines;
-using EntityFrameworkCore.BootKit;
-using Microsoft.Data.Sqlite;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.IO;
-using System.Linq;
-
-namespace BotSharp.Core.UnitTest
-{
- public abstract class TestEssential
- {
- public static String BOT_ID = "6a9fd374-c43d-447a-97f2-f37540d0c725";
-
- protected Database dc { get; set; }
- protected string contentRoot;
-
- public TestEssential()
- {
- contentRoot = $"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}BotSharp.WebHost{Path.DirectorySeparatorChar}";
- contentRoot = Path.GetFullPath(contentRoot);
- ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
- var settings = Directory.GetFiles(Path.Combine(contentRoot, "Settings"), "*.json");
- settings.ToList().ForEach(setting =>
- {
- configurationBuilder.AddJsonFile(setting, optional: false, reloadOnChange: true);
- });
-
- 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" });
-
- dc = new DefaultDataContextLoader().GetDefaultDc();
- }
- }
-
-
-}
diff --git a/BotSharp.Core/Abstractions/IAgentImporter.cs b/BotSharp.Core/Abstractions/IAgentImporter.cs
deleted file mode 100644
index 906fa7608..000000000
--- a/BotSharp.Core/Abstractions/IAgentImporter.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using BotSharp.Platform.Models;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- public interface IAgentImporter
- {
- ///
- /// data dir
- ///
- string AgentDir { get; set; }
-
- ///
- /// Load agent summary
- ///
- ///
- Task LoadAgent(AgentImportHeader agentHeader);
-
- ///
- /// Load user customized entity type which defined in dictionary
- ///
- ///
- Task LoadCustomEntities(TAgent agent);
-
- ///
- /// Load user customized intents
- ///
- ///
- Task LoadIntents(TAgent agent);
-
- ///
- /// Add entities that labeled in intent.UserSays into user customized entity dictionary
- ///
- ///
- Task LoadBuildinEntities(TAgent agent);
- }
-}
diff --git a/BotSharp.Core/Abstractions/IAgentStorage.cs b/BotSharp.Core/Abstractions/IAgentStorage.cs
deleted file mode 100644
index 3b9cacb89..000000000
--- a/BotSharp.Core/Abstractions/IAgentStorage.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using BotSharp.Platform.Models;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- ///
- /// Agent could be persisted in any kind of storage.
- /// Example: local file storage, cloud storage, relational database, key-value database or memory
- ///
- public interface IAgentStorage
- {
- ///
- /// Save agent instance
- ///
- ///
- ///
- Task Persist(TAgent agent);
-
- ///
- /// Get agent by id
- ///
- ///
- ///
- Task FetchById(string agentId);
-
- ///
- /// Get agent by name
- ///
- ///
- ///
- Task FetchByName(string agentName);
-
- ///
- /// Query agents
- ///
- ///
- Task> Query();
-
- ///
- /// Delete agents
- ///
- ///
- Task PurgeAllAgents();
- }
-}
diff --git a/BotSharp.Core/Abstractions/IAgentStorageFactory.cs b/BotSharp.Core/Abstractions/IAgentStorageFactory.cs
deleted file mode 100644
index d4f176eb2..000000000
--- a/BotSharp.Core/Abstractions/IAgentStorageFactory.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using BotSharp.Platform.Models;
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- public interface IAgentStorageFactory where TAgent : AgentBase
- {
- IAgentStorage Get();
- }
-}
diff --git a/BotSharp.Core/Abstractions/IBotEngine.cs b/BotSharp.Core/Abstractions/IBotEngine.cs
deleted file mode 100644
index a99b4ac4f..000000000
--- a/BotSharp.Core/Abstractions/IBotEngine.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.AiRequest;
-using BotSharp.Platform.Models.AiResponse;
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- ///
- /// BotEngine is the NLU of bot platform
- ///
- public interface IBotEngine
- {
- Task TextRequest(AiRequest request);
-
- Task Train(BotTrainOptions options);
- }
-}
diff --git a/BotSharp.Core/Abstractions/IContextStorage.cs b/BotSharp.Core/Abstractions/IContextStorage.cs
deleted file mode 100644
index 50d9fa141..000000000
--- a/BotSharp.Core/Abstractions/IContextStorage.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- public interface IContextStorage
- {
- Task Persist(string sessionId, T[] context);
- Task Fetch(string sessionId);
- }
-}
diff --git a/BotSharp.Core/Abstractions/IContextStorageFactory.cs b/BotSharp.Core/Abstractions/IContextStorageFactory.cs
deleted file mode 100644
index 1cf10cc47..000000000
--- a/BotSharp.Core/Abstractions/IContextStorageFactory.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- public interface IContextStorageFactory
- {
- IContextStorage Get();
- }
-}
diff --git a/BotSharp.Core/Abstractions/IHookDbInitializer.cs b/BotSharp.Core/Abstractions/IHookDbInitializer.cs
deleted file mode 100644
index f0e86df66..000000000
--- a/BotSharp.Core/Abstractions/IHookDbInitializer.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using EntityFrameworkCore.BootKit;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Abstractions
-{
- ///
- /// Initialize data for modules
- ///
- public interface IHookDbInitializer
- {
- ///
- /// value smaller is higher priority
- ///
- int Priority { get; }
- void Load(Database dc);
- }
-}
diff --git a/BotSharp.Core/Abstractions/IInitializationLoader.cs b/BotSharp.Core/Abstractions/IInitializationLoader.cs
deleted file mode 100644
index e3d1638e8..000000000
--- a/BotSharp.Core/Abstractions/IInitializationLoader.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Hosting;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Abstractions
-{
- public interface IInitializationLoader
- {
- int Priority { get; }
- void Initialize(IConfiguration config, IWebHostEnvironment env);
- }
-}
diff --git a/BotSharp.Core/Abstractions/INlpPipeline.cs b/BotSharp.Core/Abstractions/INlpPipeline.cs
deleted file mode 100644
index 1b39ae61a..000000000
--- a/BotSharp.Core/Abstractions/INlpPipeline.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using BotSharp.Core.Engines;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Abstractions
-{
- ///
- /// NLP process pipeline interface
- ///
- public interface INlpPipeline
- {
- IConfiguration Configuration { get; set; }
-
- ///
- /// Common settings for Pipeline
- ///
- PipeSettings Settings { get; set; }
- }
-}
diff --git a/BotSharp.Core/Abstractions/INlpPredict.cs b/BotSharp.Core/Abstractions/INlpPredict.cs
deleted file mode 100644
index 9d7d76c89..000000000
--- a/BotSharp.Core/Abstractions/INlpPredict.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using BotSharp.Core.Engines;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Abstractions
-{
- public interface INlpPredict : INlpPipeline
- {
- Task Predict(AgentBase agent, NlpDoc doc, PipeModel meta);
- }
-}
diff --git a/BotSharp.Core/Abstractions/INlpProvider.cs b/BotSharp.Core/Abstractions/INlpProvider.cs
deleted file mode 100644
index 64ea55017..000000000
--- a/BotSharp.Core/Abstractions/INlpProvider.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using BotSharp.Core.Engines;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Abstractions
-{
- public interface INlpProvider : INlpPipeline
- {
- Task Load(AgentBase agent, PipeModel meta);
- }
-}
diff --git a/BotSharp.Core/Abstractions/INlpTrain.cs b/BotSharp.Core/Abstractions/INlpTrain.cs
deleted file mode 100644
index 40204732b..000000000
--- a/BotSharp.Core/Abstractions/INlpTrain.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using BotSharp.Core.Engines;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Abstractions
-{
- public interface INlpTrain : INlpPipeline
- {
- ///
- /// Process
- ///
- ///
- /// Intermediate result
- /// Meta data which is packed to model
- ///
- Task Train(AgentBase agent, NlpDoc doc, PipeModel meta);
- }
-}
diff --git a/BotSharp.Core/Abstractions/IPlatformBuilder.cs b/BotSharp.Core/Abstractions/IPlatformBuilder.cs
deleted file mode 100644
index 991fc239c..000000000
--- a/BotSharp.Core/Abstractions/IPlatformBuilder.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.AiRequest;
-using BotSharp.Platform.Models.AiResponse;
-using BotSharp.Platform.Models.MachineLearning;
-using System.Threading.Tasks;
-
-namespace BotSharp.Platform.Abstractions
-{
- ///
- /// Platform abstraction
- /// Implement this interface to build a Chatbot platform
- ///
- public interface IPlatformBuilder
- {
- TAgent Agent { get; set; }
-
- ///
- /// Agent storage
- ///
- IAgentStorage Storage { get; set; }
-
- ///
- /// Parse options for the incoming text or voice request from the sender.
- ///
- // DialogRequestOptions RequestOptions { get; set; }
-
- ///
- /// Convert platform specific data to standard training corpus format
- ///
- ///
- ///
- Task ExtractorCorpus(TAgent agent);
-
- ///
- /// Load agent from files.
- /// There must contain a meta.json
- ///
- ///
- ///
- Task LoadAgentFromFile(string dataDir) where TImporter : IAgentImporter, new();
-
- ///
- ///
- ///
- ///
- ///
- ///
- Task SaveAgent(TAgent agent);
-
- Task Train(TAgent agent, TrainingCorpus corpus, BotTrainOptions options);
-
- Task TextRequest(AiRequest request);
-
- Task AssembleResult(AiRequest request, AiResponse response);
-
- Task FallbackResponse(AiRequest request);
- }
-}
diff --git a/BotSharp.Core/Abstractions/IPlatformSettings.cs b/BotSharp.Core/Abstractions/IPlatformSettings.cs
deleted file mode 100644
index 71059dc5a..000000000
--- a/BotSharp.Core/Abstractions/IPlatformSettings.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Platform.Abstractions
-{
- public interface IPlatformSettings
- {
- string BotEngine { get; set; }
-
- string AgentStorage { get; set; }
-
- string ContextStorage { get; set; }
- }
-}
diff --git a/BotSharp.Core/Accounts/AccountController.cs b/BotSharp.Core/Accounts/AccountController.cs
deleted file mode 100644
index ab53c7b3d..000000000
--- a/BotSharp.Core/Accounts/AccountController.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using DotNetToolkit.JwtHelper;
-using DotNetToolkit;
-using EntityFrameworkCore.BootKit;
-using Microsoft.Extensions.Configuration;
-using System.Linq;
-
-namespace BotSharp.Core.Accounts
-{
- ///
- /// The /account endpoint is used to create, retrieve, update, and delete account.
- ///
- public class AccountController : CoreController
- {
- private IConfiguration config;
-
- public AccountController(IConfiguration config)
- {
- this.config = config;
- }
-
- [HttpGet("/account")]
- public VmUser GetUser()
- {
- /*var user = dc.Table().Find(CurrentUserId);
- return user.ToObject();*/
- return new VmUser
- {
- Email = "botsharp@ai.com",
- FirstName = "Bot",
- LastName = "Sharp"
- };
- }
-
- ///
- /// Get a valid token after login
- ///
- /// User Email
- /// Password
- ///
- [AllowAnonymous]
- [HttpPost("/token")]
- [ProducesResponseType(typeof(string), 200)]
- public IActionResult Token([FromBody] VmUserLogin userModel)
- {
- if (string.IsNullOrEmpty(userModel.UserName) || string.IsNullOrEmpty(userModel.Password))
- {
- return new BadRequestObjectResult("Username and password should not be empty.");
- }
- return Ok(JwtToken.GenerateToken(config, "botsharp"));
- // validate from local
- var user = (from usr in dc.Table()
- join auth in dc.Table() on usr.Id equals auth.UserId
- where usr.UserName == userModel.UserName
- select auth).FirstOrDefault();
-
- if (user != null)
- {
- if (!user.IsActivated)
- {
- return BadRequest("Account hasn't been activated, please check your email to activate it.");
- }
- else
- {
- // validate password
- string hash = PasswordHelper.Hash(userModel.Password, user.Salt);
- if (user.Password == hash)
- {
- return Ok(JwtToken.GenerateToken(config, "botsharp"));
- }
- else
- {
- return BadRequest("Authorization Failed.");
- }
- }
- }
- else
- {
- return BadRequest("Account doesn't exist");
- }
- }
- }
-}
diff --git a/BotSharp.Core/Accounts/AccountCore.cs b/BotSharp.Core/Accounts/AccountCore.cs
deleted file mode 100644
index 8c048c6b3..000000000
--- a/BotSharp.Core/Accounts/AccountCore.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using DotNetToolkit;
-using EntityFrameworkCore.BootKit;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Core.Accounts
-{
- public class AccountCore
- {
- private Database _dc;
- private IConfiguration _config;
-
- public AccountCore(Database dc = null)
- {
- if (dc == null)
- {
- dc = new DefaultDataContextLoader().GetDefaultDc();
- }
- else
- {
- _dc = dc;
- }
-
- _config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration");
- }
-
- public void CreateUser(User user)
- {
- user.Authenticaiton.IsActivated = false;
- user.Authenticaiton.Salt = PasswordHelper.GetSalt();
- user.Authenticaiton.Password = PasswordHelper.Hash(user.Authenticaiton.Password, user.Authenticaiton.Salt);
- user.Authenticaiton.ActivationCode = Guid.NewGuid().ToString("N");
-
- _dc.Transaction(() =>
- {
- _dc.Table().Add(user);
- });
-
-
- $"Created user {user.Email}, user id: {user.Id}".Log(LogLevel.INFO);
- }
-
- public void Activate(string activationCode)
- {
- var activation = _dc.Table().FirstOrDefault(x => x.ActivationCode == activationCode && !x.IsActivated);
- if (activation == null)
- {
- }
- else
- {
- _dc.Transaction(() =>
- {
- activation = _dc.Table().FirstOrDefault(x => x.ActivationCode == activationCode);
- activation.ActivationCode = String.Empty;
- activation.IsActivated = true;
- activation.UpdatedTime = DateTime.UtcNow;
- });
- }
- }
- }
-}
diff --git a/BotSharp.Core/Accounts/AccountDbInitializer.cs b/BotSharp.Core/Accounts/AccountDbInitializer.cs
deleted file mode 100644
index dd066622e..000000000
--- a/BotSharp.Core/Accounts/AccountDbInitializer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using BotSharp.Core.Abstractions;
-using CherubNLP.Tokenize;
-using EntityFrameworkCore.BootKit;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Core.Accounts
-{
- public class AccountDbInitializer : IHookDbInitializer
- {
- public int Priority => 100;
-
- public void Load(Database dc)
- {
- ImportAccount(dc);
- }
-
- private void ImportAccount(Database dc)
- {
- var dataPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "DbInitializer", "Accounts");
- string json = File.ReadAllText(Path.Combine(dataPath, "users.json"));
-
- var users = JsonConvert.DeserializeObject>(json);
- users.ForEach(user =>
- {
- if (!dc.Table().Any(x => x.UserName == user.UserName))
- {
- var core = new AccountCore(dc);
- core.CreateUser(user);
- core.Activate(user.Authenticaiton.ActivationCode);
- }
- });
-
- }
- }
-}
diff --git a/BotSharp.Core/Accounts/User.cs b/BotSharp.Core/Accounts/User.cs
deleted file mode 100644
index aa9e3c4b9..000000000
--- a/BotSharp.Core/Accounts/User.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using EntityFrameworkCore.BootKit;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using System.Text;
-
-namespace BotSharp.Core.Accounts
-{
- ///
- /// User profile
- ///
- [Table("User")]
- public class User : DbRecord, IDbRecord
- {
- [Required]
- [StringLength(64)]
- public string UserName { get; set; }
-
- [Required]
- [StringLength(64)]
- [DataType(DataType.EmailAddress)]
- public string Email { get; set; }
-
- [StringLength(32)]
- public string FirstName { get; set; }
-
- [StringLength(32)]
- public string LastName { get; set; }
-
- [MaxLength(256)]
- public string Description { get; set; }
-
- [Required]
- [DataType(DataType.DateTime)]
- public DateTime SignupDate { get; set; }
-
- [DataType(DataType.Date)]
- public DateTime? Birthday { get; set; }
-
- [MaxLength(36)]
- public string Nationality { get; set; }
-
- [NotMapped]
- public string FullName
- {
- get
- {
- return FirstName + (string.IsNullOrEmpty(LastName) ? "" : " " + LastName);
- }
- }
-
- public UserAuth Authenticaiton { get; set; }
-
- public User()
- {
- SignupDate = DateTime.UtcNow;
- }
- }
-}
diff --git a/BotSharp.Core/Accounts/UserAuth.cs b/BotSharp.Core/Accounts/UserAuth.cs
deleted file mode 100644
index 022bc78d7..000000000
--- a/BotSharp.Core/Accounts/UserAuth.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using EntityFrameworkCore.BootKit;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using System.Text;
-
-namespace BotSharp.Core.Accounts
-{
- ///
- /// User authentication
- ///
- [Table("UserAuth")]
- public class UserAuth : DbRecord, IDbRecord
- {
- [StringLength(36)]
- public string UserId { get; set; }
-
- [Required]
- [StringLength(256)]
- [DataType(DataType.Password)]
- public string Password { get; set; }
-
- [Required]
- [StringLength(64)]
- public string Salt { get; set; }
-
- [StringLength(32)]
- public string ActivationCode { get; set; }
-
- public bool IsActivated { get; set; }
-
- [ForeignKey("UserId")]
- public User User { get; set; }
- }
-}
diff --git a/BotSharp.Core/Accounts/VmUser.cs b/BotSharp.Core/Accounts/VmUser.cs
deleted file mode 100644
index 5e2626d9e..000000000
--- a/BotSharp.Core/Accounts/VmUser.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Accounts
-{
- public class VmUser
- {
- public String FullName
- {
- get
- {
- return $"{FirstName} {LastName}";
- }
- }
- public String FirstName { get; set; }
- public String LastName { get; set; }
- public String Email { get; set; }
- public String Avatar { get; set; }
- }
-}
diff --git a/BotSharp.Core/Accounts/VmUserLogin.cs b/BotSharp.Core/Accounts/VmUserLogin.cs
deleted file mode 100644
index d4817001b..000000000
--- a/BotSharp.Core/Accounts/VmUserLogin.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Accounts
-{
- public class VmUserLogin
- {
- public string UserName { get; set; }
-
- public string Password { get; set; }
- }
-}
diff --git a/BotSharp.Core/AgentStorage/AgentStorageFactory.cs b/BotSharp.Core/AgentStorage/AgentStorageFactory.cs
deleted file mode 100644
index dea8f5986..000000000
--- a/BotSharp.Core/AgentStorage/AgentStorageFactory.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.AgentStorage
-{
- public class AgentStorageFactory : IAgentStorageFactory where TAgent : AgentBase
- {
- private readonly Func> func;
- private readonly IPlatformSettings platformSetting;
-
- public AgentStorageFactory(IPlatformSettings setting, Func> serviceAccessor)
- {
- this.func = serviceAccessor;
- this.platformSetting = setting;
- }
-
- public IAgentStorage Get()
- {
- IAgentStorage storage = null;
- string storageName = this.platformSetting.AgentStorage;
- storage = func(storageName);
- return storage as IAgentStorage;
- }
- }
-}
diff --git a/BotSharp.Core/AgentStorage/AgentStorageInFile.cs b/BotSharp.Core/AgentStorage/AgentStorageInFile.cs
deleted file mode 100644
index cf6f1e002..000000000
--- a/BotSharp.Core/AgentStorage/AgentStorageInFile.cs
+++ /dev/null
@@ -1,118 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using CSRedis;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Serialization;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.AgentStorage
-{
- public class AgentStorageInFile : IAgentStorage
- where TAgent : AgentBase
- {
- private static string storageDir;
-
- public AgentStorageInFile()
- {
- IConfiguration config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration");
- var db = config.GetSection("Database:Default").Value;
- storageDir = config.GetSection($"Database:ConnectionStrings:{db}").Value;
- string contentDir = AppDomain.CurrentDomain.GetData("DataPath").ToString();
- storageDir = storageDir.Replace("|DataDirectory|", contentDir + Path.DirectorySeparatorChar + "AgentStorage" + Path.DirectorySeparatorChar);
-
- if (!Directory.Exists(storageDir))
- {
- Directory.CreateDirectory(storageDir);
- }
- }
-
- public async Task FetchById(string agentId)
- {
- string dataPath = Path.Combine(storageDir, agentId + ".json");
- if (File.Exists(dataPath))
- {
- string json = File.ReadAllText(dataPath);
- return JsonConvert.DeserializeObject(json);
- }
- else
- {
- return default(TAgent);
- }
- }
-
- public async Task FetchByName(string agentName)
- {
- var files = Directory.GetFiles(storageDir);
- for (int i = 0; i < files.Length; i++)
- {
- var file = files[i];
- string json = File.ReadAllText(file);
- var agent = JsonConvert.DeserializeObject(json);
- if (agent.Name.ToLower() == agentName.ToLower())
- {
- return agent;
- }
- }
-
- return default(TAgent);
- }
-
- public async Task Persist(TAgent agent)
- {
- if (String.IsNullOrEmpty(agent.Id))
- {
- agent.Id = Guid.NewGuid().ToString();
- }
-
- var json = JsonConvert.SerializeObject(agent, new JsonSerializerSettings
- {
- NullValueHandling = NullValueHandling.Ignore,
- Formatting = Formatting.Indented,
- ContractResolver = new CamelCasePropertyNamesContractResolver(),
- Converters = new List
- {
- new Newtonsoft.Json.Converters.StringEnumConverter()
- }
- });
-
- string dataPath = Path.Combine(storageDir, agent.Id + ".json");
-
- File.WriteAllText(dataPath, json);
-
- return true;
- }
-
- public async Task PurgeAllAgents()
- {
- var files = Directory.GetFiles(storageDir);
- for (int i = 0; i < files.Length; i++)
- {
- File.Delete(files[i]);
- }
-
- return files.Length;
- }
-
- public async Task> Query()
- {
- var agents = new List();
-
- var files = Directory.GetFiles(storageDir);
- for (int i = 0; i < files.Length; i++)
- {
- var file = files[i];
- string json = File.ReadAllText(file);
- var agent = JsonConvert.DeserializeObject(json);
- agents.Add(agent);
- }
-
- return agents;
- }
- }
-}
diff --git a/BotSharp.Core/AgentStorage/AgentStorageInMemory.cs b/BotSharp.Core/AgentStorage/AgentStorageInMemory.cs
deleted file mode 100644
index 0ead92e00..000000000
--- a/BotSharp.Core/AgentStorage/AgentStorageInMemory.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.AgentStorage
-{
- ///
- /// Save agent instance into memory.
- /// Caution: Data will be lost once application restarts.
- ///
- public class AgentStorageInMemory : IAgentStorage where TAgent : AgentBase
- {
- private static Dictionary agents;
-
- public AgentStorageInMemory()
- {
- if (agents == null) agents = new Dictionary();
- }
-
- public async Task FetchById(string agentId)
- {
- if (agents.ContainsKey(agentId))
- {
- return agents[agentId];
- }
- else
- {
- return null;
- }
- }
-
- public async Task FetchByName(string agentName)
- {
- var data = agents.FirstOrDefault(x => x.Value.Name == agentName);
-
- return data.Value;
- }
-
- public async Task Persist(TAgent agent)
- {
- if (String.IsNullOrEmpty(agent.Id))
- {
- agent.Id = Guid.NewGuid().ToString();
- agents[agent.Id] = agent;
- }
- else
- {
- agents[agent.Id] = agent;
- }
-
- return true;
- }
-
- public async Task PurgeAllAgents()
- {
- int count = agents.Count;
-
- agents.Clear();
-
- return count;
- }
-
- public async Task> Query()
- {
- return agents.Select(x => x.Value).ToList();
- }
- }
-}
diff --git a/BotSharp.Core/AgentStorage/AgentStorageInRedis.cs b/BotSharp.Core/AgentStorage/AgentStorageInRedis.cs
deleted file mode 100644
index 8bc5a73e5..000000000
--- a/BotSharp.Core/AgentStorage/AgentStorageInRedis.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using CSRedis;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.AgentStorage
-{
- public class AgentStorageInRedis : IAgentStorage
- where TAgent : AgentBase
- {
- private static CSRedisClient csredis;
- private static string prefix = String.Empty;
-
- public AgentStorageInRedis()
- {
- if (csredis == null)
- {
- IConfiguration config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration");
- var db = config.GetSection("Database:Default").Value;
- var dbConnStr = config.GetSection($"Database:ConnectionStrings:{db}").Value;
-
- prefix = dbConnStr.Split(',').First(x => x.StartsWith("prefix=")).Split('=')[1];
-
- csredis = new CSRedisClient(dbConnStr);
- }
- }
-
- public async Task FetchById(string agentId)
- {
- var key = agentId;
- if (await csredis.ExistsAsync(key))
- {
- return JsonConvert.DeserializeObject(await csredis.GetAsync(key));
- }
- else
- {
- return null;
- }
- }
-
- public async Task FetchByName(string agentName)
- {
- var keys = csredis.Keys($"{prefix}*");
- foreach (string key in keys)
- {
- var data = await csredis.GetAsync(key.Substring(prefix.Length));
- var agent = JsonConvert.DeserializeObject(data);
-
- if(agent.Name == agentName)
- {
- return agent;
- }
- }
-
- return default(TAgent);
- }
-
- public async Task Persist(TAgent agent)
- {
- if (String.IsNullOrEmpty(agent.Id))
- {
- agent.Id = Guid.NewGuid().ToString();
- }
-
- var json = JsonConvert.SerializeObject(agent, new JsonSerializerSettings
- {
- NullValueHandling = NullValueHandling.Ignore,
- Formatting = Formatting.Indented,
- });
-
- await csredis.SetAsync(agent.Id, json);
-
- return true;
- }
-
- public async Task PurgeAllAgents()
- {
- var keys = csredis.Keys($"{prefix}*");
-
- await csredis.DelAsync(keys.Select(x => x.Substring(prefix.Length)).ToArray());
-
- return keys.Count();
- }
-
- public async Task> Query()
- {
- var agents = new List();
-
- var keys = csredis.Keys($"{prefix}*");
- foreach (string key in keys)
- {
- var data = await csredis.GetAsync(key.Substring(prefix.Length));
- var agent = JsonConvert.DeserializeObject(data);
- agents.Add(agent);
- }
-
- return agents;
- }
- }
-}
diff --git a/BotSharp.Core/AgentStorage/AgentStorageServiceRegister.cs b/BotSharp.Core/AgentStorage/AgentStorageServiceRegister.cs
deleted file mode 100644
index f366d1aff..000000000
--- a/BotSharp.Core/AgentStorage/AgentStorageServiceRegister.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection.Extensions;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.AgentStorage
-{
- public class AgentStorageServiceRegister
- {
- public static void Register(IServiceCollection services)
- where TAgent : AgentBase
- {
- services.AddSingleton, AgentStorageFactory>();
-
- services.AddSingleton>();
- services.AddSingleton>();
- services.AddSingleton>();
-
- services.AddSingleton(factory =>
- {
- Func> accesor = key =>
- {
- if (key.Equals("AgentStorageInRedis"))
- {
- return factory.GetService>();
- }
- else if (key.Equals("AgentStorageInMemory"))
- {
- return factory.GetService>();
- }
- else if (key.Equals("AgentStorageInFile"))
- {
- return factory.GetService>();
- }
- else
- {
- throw new ArgumentException($"Not Support key : {key}");
- }
- };
-
- return accesor;
- });
- }
- }
-}
diff --git a/BotSharp.Core/BotSharp.Core.csproj b/BotSharp.Core/BotSharp.Core.csproj
deleted file mode 100644
index 22799830f..000000000
--- a/BotSharp.Core/BotSharp.Core.csproj
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
- $(DefaultTargetFramework)
- true
- 0.4.0
-
-
-
- SAK
- SAK
- SAK
- SAK
- AnyCPU;x64
- Debug;Release;
-
-
-
- Haiping Chen
- SciSharp STACK
- AI Bot Platform Builder
-
- 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.
-
- If you feel that this project is helpful to you, please Star on the project, we will be very grateful.
-
- git
- https://github.com/SciSharp/BotSharp
- NLU, Chatbot, Bot, AI Bot, Artificial Intelligence
- Support dialogue status tracking.
- Since 2018 Haiping Chen
- https://github.com/SciSharp/BotSharp
- https://raw.githubusercontent.com/SciSharp/BotSharp/master/docs/static/logos/BotSharp.png
- https://raw.githubusercontent.com/SciSharp/BotSharp/master/LICENSE
-
-
-
- TRACE;DEBUG
-
-
-
- TRACE;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BotSharp.Core/ContextStorage/ContextStorageFactory.cs b/BotSharp.Core/ContextStorage/ContextStorageFactory.cs
deleted file mode 100644
index fa56b4f37..000000000
--- a/BotSharp.Core/ContextStorage/ContextStorageFactory.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.ContextStorage
-{
- public class ContextStorageFactory : IContextStorageFactory
- {
- private readonly Func> func;
- private readonly IPlatformSettings platformSetting;
-
- public ContextStorageFactory(IPlatformSettings setting, Func> serviceAccessor)
- {
- this.func = serviceAccessor;
- this.platformSetting = setting;
- }
-
- public IContextStorage Get()
- {
- IContextStorage storage = null;
- string storageName = this.platformSetting.ContextStorage;
- storage = func(storageName);
- return storage as IContextStorage;
- }
- }
-}
diff --git a/BotSharp.Core/ContextStorage/ContextStorageInFile.cs b/BotSharp.Core/ContextStorage/ContextStorageInFile.cs
deleted file mode 100644
index b57a427da..000000000
--- a/BotSharp.Core/ContextStorage/ContextStorageInFile.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Serialization;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.ContextStorage
-{
- public class ContextStorageInFile : IContextStorage
- {
- private static string storageDir;
-
- public ContextStorageInFile()
- {
- IConfiguration config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration");
- var db = config.GetSection("Database:Default").Value;
- storageDir = config.GetSection($"Database:ConnectionStrings:{db}").Value;
- string contentDir = AppDomain.CurrentDomain.GetData("DataPath").ToString();
- storageDir = storageDir.Replace("|DataDirectory|", contentDir + Path.DirectorySeparatorChar + "SessionStorage" + Path.DirectorySeparatorChar);
-
- if (!Directory.Exists(storageDir))
- {
- Directory.CreateDirectory(storageDir);
- }
- }
-
- public async Task Fetch(string sessionId)
- {
- string dataPath = Path.Combine(storageDir, sessionId + ".json");
- if (File.Exists(dataPath))
- {
- string json = File.ReadAllText(dataPath);
- return JsonConvert.DeserializeObject(json);
- }
- else
- {
- return new T[0];
- }
- }
-
- public async Task Persist(string sessionId, T[] context)
- {
- var json = JsonConvert.SerializeObject(context, new JsonSerializerSettings
- {
- NullValueHandling = NullValueHandling.Ignore,
- Formatting = Formatting.Indented,
- ContractResolver = new CamelCasePropertyNamesContractResolver(),
- Converters = new List
- {
- new Newtonsoft.Json.Converters.StringEnumConverter()
- }
- });
-
- string dataPath = Path.Combine(storageDir, sessionId + ".json");
-
- File.WriteAllText(dataPath, json);
-
- return true;
- }
- }
-}
diff --git a/BotSharp.Core/ContextStorage/ContextStorageServiceRegister.cs b/BotSharp.Core/ContextStorage/ContextStorageServiceRegister.cs
deleted file mode 100644
index 6b6350e61..000000000
--- a/BotSharp.Core/ContextStorage/ContextStorageServiceRegister.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using BotSharp.Platform.Abstractions;
-using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.ContextStorage
-{
- public class ContextStorageServiceRegister
- {
- public static void Register(IServiceCollection services)
- {
- services.AddSingleton, ContextStorageFactory>();
-
- services.AddSingleton>();
-
- services.AddSingleton(factory =>
- {
- Func> accesor = key =>
- {
- if (key.Equals("ContextStorageInFile"))
- {
- return factory.GetService>();
- }
- else
- {
- throw new ArgumentException($"Not Support key : {key}");
- }
- };
-
- return accesor;
- });
- }
- }
-}
diff --git a/BotSharp.Core/Conversations/Conversation.cs b/BotSharp.Core/Conversations/Conversation.cs
deleted file mode 100644
index 645487e6e..000000000
--- a/BotSharp.Core/Conversations/Conversation.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using EntityFrameworkCore.BootKit;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using System.Text;
-
-namespace BotSharp.Core.Conversations
-{
- [Table("Bot_Conversation")]
- public class Conversation : DbRecord, IDbRecord
- {
- [Required]
- [StringLength(36)]
- public String AgentId { get; set; }
-
- [StringLength(36)]
- public String UserId { get; set; }
-
- [Required]
- public DateTime StartTime { get; set; }
- }
-}
diff --git a/BotSharp.Core/Conversations/ConversationContext.cs b/BotSharp.Core/Conversations/ConversationContext.cs
deleted file mode 100644
index 6fb14225e..000000000
--- a/BotSharp.Core/Conversations/ConversationContext.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using EntityFrameworkCore.BootKit;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using System.Text;
-
-namespace BotSharp.Core.Conversations
-{
- [Table("Bot_ConversationContext")]
- public class ConversationContext : DbRecord, IDbRecord
- {
- [Required]
- [StringLength(36)]
- public String ConversationId { get; set; }
-
- [Required]
- [MaxLength(64)]
- public String Context { get; set; }
-
- public int Lifespan { get; set; }
- }
-}
diff --git a/BotSharp.Core/CoreController.cs b/BotSharp.Core/CoreController.cs
deleted file mode 100644
index 1b3f2d76f..000000000
--- a/BotSharp.Core/CoreController.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using EntityFrameworkCore.BootKit;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Core
-{
- [Authorize]
- [Produces("application/json")]
- [Route("v1/[controller]")]
- public class CoreController : ControllerBase
- {
- protected Database dc { get; set; }
-
- public CoreController()
- {
- dc = new DefaultDataContextLoader().GetDefaultDc();
- }
-
- /*protected string GetConfig(string path)
- {
- if (string.IsNullOrEmpty(path)) return String.Empty;
-
- return Database.Configuration.GetSection(path).Value;
- }
-
- protected List> GetSection(string path)
- {
- return Database.Configuration.GetSection(path).AsEnumerable().ToList();
- }*/
-
- protected string CurrentUserId
- {
- get
- {
- return this.User.Claims.FirstOrDefault(x => x.Type.Equals("UserId")).Value;
- }
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotEngineBase.cs b/BotSharp.Core/Engines/BotEngineBase.cs
deleted file mode 100644
index 240c430d9..000000000
--- a/BotSharp.Core/Engines/BotEngineBase.cs
+++ /dev/null
@@ -1,221 +0,0 @@
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.AiRequest;
-using BotSharp.Platform.Models.AiResponse;
-using BotSharp.Platform.Models.Entities;
-using EntityFrameworkCore.BootKit;
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Engines
-{
- ///
- /// Bot engine/ platform base class
- ///
- public abstract class BotEngineBase
- {
- protected Database Dc;
-
- protected AgentBase Agent { get; set; }
-
- public BotEngineBase()
- {
- Dc = new DefaultDataContextLoader().GetDefaultDc();
- }
-
- public Task TextRequest(AiRequest request)
- {
- var preditor = new BotPredictor();
- var doc = preditor.Predict(Agent, new AiRequest
- {
- AgentDir = request.AgentDir,
- Model = request.Model,
- SessionId = request.SessionId,
- Text = request.Text
- }).Result;
-
- var parameters = new Dictionary();
- if(doc.Sentences[0].Entities == null)
- {
- doc.Sentences[0].Entities = new List();
- }
- doc.Sentences[0].Entities.ForEach(x => parameters[x.Entity] = x.Value);
- return Task.FromResult(new AiResponse
- {
- /*Lang = request.Language,
- Timestamp = DateTime.UtcNow,
- SessionId = request.SessionId,
- Status = new AIResponseStatus(),
- Result = new AIResponseResult
- {
- Score = doc.Sentences[0].Intent == null ? 0 : doc.Sentences[0].Intent.Confidence,
- ResolvedQuery = doc.Sentences[0].Text,
- Fulfillment = new AIResponseFulfillment
- {
- Speech = agent.Intents.FirstOrDefault(tnt => tnt.Name == doc.Sentences[0].Intent?.Label)?.Responses?.Random()?.Messages?.Random()?.Speech
- },
- Parameters = parameters,
- Entities = doc.Sentences[0].Entities,
- Metadata = new AIResponseMetadata
- {
- IntentName = doc.Sentences[0].Intent?.Label
- }
- }*/
- });
- }
-
- /*public TrainingCorpus GetIntentExpressions(AgentBase agent)
- {
- TrainingCorpus corpus = new TrainingCorpus()
- {
- UserSays = new List>(),
- Entities = new List()
- };
-
- var expressParts = new List();
-
- var intents = agent.Intents;
-
- intents.ForEach(intent =>
- {
- intent.UserSays.ForEach(exp =>
- {
- exp.Data = exp.Data.OrderBy(x => x.UpdatedTime).ToList();
-
- var say = new TrainingIntentExpression
- {
- Intent = intent.Name,
- Text = String.Join("", exp.Data.Select(x => x.Text)),
- ContextHash = intent.ContextHash
- };
-
- // convert entity format
- exp.Data.Where(x => !String.IsNullOrEmpty(x.Meta))
- .ToList()
- .ForEach(x =>
- {
- var part = new TrainingIntentExpressionPart
- {
- Value = x.Text,
- Entity = $"{x.Meta}:{x.Alias}",
- Start = x.Start
- };
-
- 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))
- {
- var allSynonyms = (from e in dc.Table()
- join ee in dc.Table() on e.Id equals ee.EntityId
- join ees in dc.Table() on ee.Id equals ees.EntityEntryId
- where e.Name == x.Alias && ee.Value == x.Text & ees.Synonym != x.Text
- select ees.Synonym).ToList();
-
- var te = new TrainingEntity
- {
- EntityType = $"{x.Meta}:{x.Alias}",
- EntityValue = x.Text,
- Synonyms = allSynonyms
- };
-
- trainingData.Entities.Add(te);
- }
- });
-
- corpus.UserSays.Add(say);
- });
- });
-
- // remove Default Fallback Intent
- corpus.UserSays = corpus.UserSays.Where(x => x.Intent != "Default Fallback Intent").ToList();
-
- return corpus;
- }*/
-
- public TrainingCorpus GetIntentExpressions()
- {
- TrainingCorpus corpus = new TrainingCorpus()
- {
- UserSays = new List>(),
- Entities = new List()
- };
-
- /*var expressParts = new List();
-
- var intents = dc.Table()
- .Include(x => x.Contexts)
- .Include(x => x.UserSays).ThenInclude(say => say.Data)
- .Where(x => x.AgentId == agent.Id && x.UserSays.Count > 0)
- .ToList();
-
- intents.ForEach(intent =>
- {
- intent.UserSays.ForEach(exp =>
- {
- exp.Data = exp.Data.OrderBy(x => x.UpdatedTime).ToList();
-
- var say = new TrainingIntentExpression
- {
- Intent = intent.Name,
- Text = String.Join("", exp.Data.Select(x => x.Text)),
- ContextHash = intent.ContextHash
- };
-
- // convert entity format
- exp.Data.Where(x => !String.IsNullOrEmpty(x.Meta))
- .ToList()
- .ForEach(x =>
- {
- var part = new TrainingIntentExpressionPart
- {
- Value = x.Text,
- Entity = $"{x.Meta}:{x.Alias}",
- Start = x.Start
- };
-
- 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))
- {
- var allSynonyms = (from e in dc.Table()
- join ee in dc.Table() on e.Id equals ee.EntityId
- join ees in dc.Table() on ee.Id equals ees.EntityEntryId
- where e.Name == x.Alias && ee.Value == x.Text & ees.Synonym != x.Text
- select ees.Synonym).ToList();
-
- var te = new TrainingEntity
- {
- EntityType = $"{x.Meta}:{x.Alias}",
- EntityValue = x.Text,
- Synonyms = allSynonyms
- };
-
- trainingData.Entities.Add(te);
- }
- });
-
- corpus.UserSays.Add(say);
- });
- });
-
- // remove Default Fallback Intent
- corpus.UserSays = corpus.UserSays.Where(x => x.Intent != "Default Fallback Intent").ToList();*/
-
- return corpus;
- }
-
- public virtual Task Train(BotTrainOptions options)
- {
- return Task.CompletedTask;
- }
-
- }
-}
diff --git a/BotSharp.Core/Engines/BotPredictor.cs b/BotSharp.Core/Engines/BotPredictor.cs
deleted file mode 100644
index 356852ffc..000000000
--- a/BotSharp.Core/Engines/BotPredictor.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using BotSharp.Core.Abstractions;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.AiRequest;
-using BotSharp.Platform.Models.MachineLearning;
-using DotNetToolkit;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Console = Colorful.Console;
-
-namespace BotSharp.Core.Engines
-{
- public class BotPredictor
- {
- public async Task Predict(AgentBase agent, AiRequest request)
- {
- // load model per context
- var dir = Path.Combine(request.AgentDir, request.Model);
- Console.WriteLine($"Load model from {dir}");
- var metaJson = File.ReadAllText(Path.Combine(dir, "model-meta.json"));
- var meta = JsonConvert.DeserializeObject(metaJson);
-
- // Get NLP Provider
- var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration");
- var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies");
-
- var providerPipe = meta.Pipeline.First();
- var provider = TypeHelper.GetInstance(providerPipe.Name, assemblies) as INlpProvider;
- provider.Configuration = config.GetSection(meta.Platform);
-
- var data = new NlpDoc
- {
- Sentences = new List
- {
- new NlpDocSentence
- {
- Text = request.Text
- }
- }
- };
-
- await provider.Load(agent, providerPipe);
- meta.Pipeline.RemoveAt(0);
-
- var settings = new PipeSettings
- {
- ModelDir = dir,
- ProjectDir = request.AgentDir
- };
-
-
- // pipe process
- var pipelines = config.GetValue($"{meta.BotEngine}_{agent.Language}:pipe")
- .Split(',')
- .Select(x => x.Trim())
- .ToList();
-
- for(int pipeIdx = 0; pipeIdx < pipelines.Count; pipeIdx++)
- {
- var pipe = TypeHelper.GetInstance(pipelines[pipeIdx], assemblies) as INlpPredict;
- pipe.Configuration = config.GetSection($"{meta.BotEngine}_{agent.Language}").GetSection(pipelines[pipeIdx]);
- pipe.Settings = settings;
- var pipeModel = meta.Pipeline.FirstOrDefault(x => x.Name == pipelines[pipeIdx]);
- await pipe.Predict(agent, data, pipeModel);
- }
-
- /*Console.WriteLine($"Prediction result:", Color.Green);
- Console.WriteLine(JsonConvert.SerializeObject(data, new JsonSerializerSettings
- {
- Formatting = Formatting.Indented,
- NullValueHandling = NullValueHandling.Ignore,
- ContractResolver = new CamelCasePropertyNamesContractResolver()
- }));*/
-
- return data;
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpIntentClassifier.cs b/BotSharp.Core/Engines/BotSharp/BotSharpIntentClassifier.cs
deleted file mode 100644
index 39f6c2669..000000000
--- a/BotSharp.Core/Engines/BotSharp/BotSharpIntentClassifier.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using BotSharp.Core.Abstractions;
-using CherubNLP;
-using CherubNLP.Classify;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.AiResponse;
-using BotSharp.Platform.Models.MachineLearning;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-
-namespace BotSharp.Core.Engines.BotSharp
-{
- public class BotSharpIntentClassifier : INlpTrain, INlpPredict
- {
- public IConfiguration Configuration { get; set; }
- public PipeSettings Settings { get; set; }
- private ClassifierFactory _classifier;
-
- public async Task Train(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- Init(meta);
-
- var sentences = doc.Sentences.Select(x => new Sentence
- {
- Label = x.Intent.Label,
- Text = x.Text,
- Words = x.Tokens
- }).ToList();
-
- _classifier.Train(sentences);
-
- Console.WriteLine($"Saved model to {Settings.ModelDir}");
-
- return true;
- }
-
- public async Task Predict(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- Init(meta);
-
- var sentence = doc.Sentences.Select(s => new Sentence
- {
- Text = s.Text,
- Words = s.Tokens
- }).First();
-
-
- var result = _classifier.Classify(sentence);
-
- doc.Sentences[0].Intent = new TextClassificationResult
- {
- Classifier = "BotSharpIntentClassifier",
- Label = result.First().Item1,
- Confidence = result.First().Item2
- };
-
- return true;
- }
-
- private void Init(PipeModel meta)
- {
- if (_classifier == null)
- {
- meta.Model = "intent.model";
-
- var options = new ClassifyOptions
- {
- ModelFilePath = Path.Combine(Settings.ModelDir, meta.Model),
- ModelDir = Settings.ModelDir,
- ModelName = meta.Model,
- Word2VecFilePath = Configuration.GetValue("wordvecModel")
- };
-
- if (!String.IsNullOrEmpty(options.Word2VecFilePath))
- {
- string contentDir = AppDomain.CurrentDomain.GetData("DataPath").ToString();
- options.Word2VecFilePath = options.Word2VecFilePath.Replace("|App_Data|", contentDir + System.IO.Path.DirectorySeparatorChar);
- }
-
- _classifier = new ClassifierFactory(options, SupportedLanguage.English);
-
- string classifierName = Configuration.GetValue($"classifer");
-
- _classifier.GetClassifer(classifierName);
- }
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpNER.cs b/BotSharp.Core/Engines/BotSharp/BotSharpNER.cs
deleted file mode 100644
index a1d1887dc..000000000
--- a/BotSharp.Core/Engines/BotSharp/BotSharpNER.cs
+++ /dev/null
@@ -1,272 +0,0 @@
-using BotSharp.Core.Abstractions;
-using Bigtree.Algorithm.CRFLite;
-using Bigtree.Algorithm.CRFLite.Decoder;
-using Bigtree.Algorithm.CRFLite.Encoder;
-using CherubNLP.Tokenize;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using BotSharp.Platform.Models.Entities;
-
-namespace BotSharp.Core.Engines.BotSharp
-{
- public class BotSharpNER : INlpTrain, INlpPredict
- {
- public IConfiguration Configuration { get; set; }
- public PipeSettings Settings { get; set; }
-
- public async Task Train(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- var corpus = agent.Corpus;
-
- meta.Model = "ner-crf.model";
-
- List> userSays = corpus.UserSays;
- List> list = new List>();
-
- string rawTrainingDataFileName = System.IO.Path.Combine(Settings.ModelDir, "ner-crf.corpus.txt");
- string modelFileName = System.IO.Path.Combine(Settings.ModelDir, meta.Model);
-
- using (FileStream fs = new FileStream(rawTrainingDataFileName, FileMode.Create))
- {
- using (StreamWriter sw = new StreamWriter(fs))
- {
- for (int i = 0; i < doc.Sentences.Count; i++)
- {
- List curLine = Merge(doc, doc.Sentences[i].Tokens, userSays[i].Entities);
- curLine.ForEach(trainingData =>
- {
- string[] wordParams = { trainingData.Token, trainingData.Pos, trainingData.Entity };
- string wordStr = string.Join("\t", wordParams);
- sw.WriteLine(wordStr);
- });
- list.Add(curLine);
- sw.WriteLine();
- }
- sw.Flush();
- }
- }
-
- string contentDir = AppDomain.CurrentDomain.GetData("DataPath").ToString();
- string template = Configuration.GetValue($"template");
- template = template.Replace("|App_Data|", contentDir + System.IO.Path.DirectorySeparatorChar);
-
- var encoder = new CRFEncoder();
- bool result = encoder.Learn(new EncoderOptions
- {
- TrainingCorpusFileName = rawTrainingDataFileName,
- TemplateFileName = template,
- ModelFileName = modelFileName,
- });
-
- return result;
- }
-
- private List Merge(NlpDoc doc, List tokens, List entities)
- {
- List trainingTuple = new List();
- HashSet entityWordBag = new HashSet();
- int wordCandidateCount = 0;
-
- for (int i = 0; i < tokens.Count; i++)
- {
- TrainingIntentExpressionPart curEntity = null;
- if (entities == null) continue;
-
- bool entityFinded = false;
- for (int entityIndex = 0; entityIndex < entities.Count; entityIndex++)
- {
- var entity = entities[entityIndex];
-
- if (!entityFinded)
- {
- var vDoc = new NlpDoc { Sentences = new List { new NlpDocSentence { Text = entity.Value } } };
- doc.Tokenizer.Predict(null, vDoc, null);
- string[] words = vDoc.Sentences[0].Tokens.Select(x => x.Text).ToArray();
-
- for (int j = 0; j < words.Length; j++)
- {
- if (tokens[i + j].Text == words[j])
- {
- wordCandidateCount++;
- if (j == words.Length - 1)
- {
- curEntity = entity;
- }
- }
- else
- {
- wordCandidateCount = 0;
- break;
- }
- }
- if (wordCandidateCount != 0) // && entity.Start == tokens[i].Offset)
- {
- String entityName = curEntity.Entity.Contains(":") ? curEntity.Entity.Substring(curEntity.Entity.IndexOf(":") + 1) : curEntity.Entity;
-
- for(int wordIndex = 0; wordIndex < words.Length; wordIndex++)
- {
- var tag = entityName;
-
- if (wordIndex == 0)
- {
- if (words.Length == 1)
- {
- tag = "S_" + entityName;
- }
- else
- {
- tag = "B_" + entityName;
- }
- }
- else if (wordIndex == words.Length - 1)
- {
- tag = "E_" + entityName;
- }
- else
- {
- tag = "M_" + entityName;
- }
-
- var word = words[wordIndex];
- trainingTuple.Add(new TrainingData(tag, word, tokens[i].Pos));
- }
-
- entityFinded = true;
- }
- }
- }
-
- if (wordCandidateCount == 0)
- {
- trainingTuple.Add(new TrainingData("S", tokens[i].Text, tokens[i].Pos));
- }
- else
- {
- i = i + wordCandidateCount - 1;
- }
- }
-
- return trainingTuple;
- }
-
- public async Task Predict(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- var decoder = new CRFDecoder();
- var options = new DecoderOptions
- {
- ModelFileName = System.IO.Path.Combine(Settings.ModelDir, meta.Model)
- };
-
- //Load encoded model from file
- decoder.LoadModel(options.ModelFileName);
-
- //Create decoder tagger instance.
- var tagger = decoder.CreateTagger(options.NBest, options.MaxWord);
- tagger.set_vlevel(options.ProbLevel);
-
- //Initialize result
- var crf_out = new CRFSegOut[options.NBest];
- for (var i = 0; i < options.NBest; i++)
- {
- crf_out[i] = new CRFSegOut(options.MaxWord);
- }
-
- doc.Sentences.ForEach(sent =>
- {
- List> dataset = new List>();
- dataset.AddRange(sent.Tokens.Select(token => new List { token.Text, token.Pos }).ToList());
- //predict given string's tags
- decoder.Segment(crf_out, tagger, dataset);
-
- var entities = new List();
-
- for (int i = 0; i < sent.Tokens.Count; i++)
- {
- for (int crf_index = 0; crf_index < crf_out.Length; crf_index++)
- {
- //entity can be extract in more than 1 run/index
- //var entity = crf_out[0].result_;
- var entity = crf_out[crf_index].result_;
- var contains = entities.Exists(x => x.Entity == entity[i]);
- if (!contains)
- {
- entities.Add(new NlpEntity
- {
- Entity = entity[i],
- Start = doc.Sentences[0].Tokens[i].Start,
- Value = doc.Sentences[0].Tokens[i].Text,
- Confidence = 0,
- Extrator = "BotSharpNER"
- });
- }
- }
- }
-
- sent.Entities = MergeEntity(doc.Sentences[0].Text, entities);
- });
-
- return true;
- }
-
- private List MergeEntity(string sentence, List tokens)
- {
- List res = new List();
-
- for(int i = 0; i < tokens.Count; i++)
- {
- var entity = tokens[i];
-
- if (entity.Entity.StartsWith("S_"))
- {
- entity.Entity = entity.Entity.Split('_')[1];
- res.Add(entity);
- }
- else if (entity.Entity.StartsWith("B_"))
- {
- entity.Entity = entity.Entity.Split('_')[1];
-
- for(int j = i; j < tokens.Count; j++)
- {
- var token = tokens[j];
- if (token.Entity.StartsWith("E_"))
- {
- res.Add(new NlpEntity
- {
- Value = sentence.Substring(entity.Start, token.End - entity.Start + 1),
- Entity = entity.Entity,
- Extrator = entity.Extrator,
- Start = entity.Start,
- Confidence = entity.Confidence
- });
- }
-
- i++;
- }
- }
- }
-
- return res;
- }
-
- public class TrainingData
- {
- public String Token { get; set; }
- public String Entity { get; set; }
- public String Pos { get; set; }
-
- public TrainingData(string entity, string token, string pos)
- {
- Token = token;
- Entity = entity;
- Pos = pos;
- }
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpNLU.cs b/BotSharp.Core/Engines/BotSharp/BotSharpNLU.cs
deleted file mode 100644
index e7e7f04bd..000000000
--- a/BotSharp.Core/Engines/BotSharp/BotSharpNLU.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-
-namespace BotSharp.Core.Engines.BotSharp
-{
- public class BotSharpNLU : BotEngineBase, IBotEngine
- {
- public override async Task Train(BotTrainOptions options)
- {
- var trainer = new BotTrainer(Agent.Id, Dc);
- await trainer.Train(Agent, options);
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpProvider.cs b/BotSharp.Core/Engines/BotSharp/BotSharpProvider.cs
deleted file mode 100644
index 490e28201..000000000
--- a/BotSharp.Core/Engines/BotSharp/BotSharpProvider.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using BotSharp.Core.Abstractions;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Engines.BotSharp
-{
- public class BotSharpProvider : INlpProvider
- {
- public IConfiguration Configuration { get; set; }
- public PipeSettings Settings { get; set; }
-
- public async Task Load(AgentBase agent, PipeModel meta)
- {
- meta.Meta = JObject.FromObject(new { version = "0.1.0" });
-
- return true;
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpTagger.cs b/BotSharp.Core/Engines/BotSharp/BotSharpTagger.cs
deleted file mode 100644
index 4276e21ee..000000000
--- a/BotSharp.Core/Engines/BotSharp/BotSharpTagger.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using BotSharp.Core.Abstractions;
-using CherubNLP;
-using CherubNLP.Corpus;
-using CherubNLP.Tag;
-using CherubNLP.Tokenize;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Engines.BotSharp
-{
- public class BotSharpTagger : INlpTrain, INlpPredict
- {
- public IConfiguration Configuration { get; set; }
- public PipeSettings Settings { get; set; }
-
- private TaggerFactory _tagger;
-
- public BotSharpTagger()
- {
-
- }
-
- public async Task Predict(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- Init();
-
- doc.Sentences.ForEach(x => _tagger.Tag(new Sentence
- {
- Words = x.Tokens,
- Text = x.Text
- }));
-
- return true;
- }
-
- public async Task Train(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- Init();
-
- doc.Sentences.ForEach(x => _tagger.Tag(new Sentence
- {
- Words = x.Tokens,
- Text = x.Text
- }));
-
- return true;
- }
-
- private void Init()
- {
- if (_tagger == null)
- {
- _tagger = new TaggerFactory(new TagOptions
- {
- CorpusDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Corpus")
- }, SupportedLanguage.English);
-
- string tokenizerName = Configuration.GetValue($"tagger");
-
- _tagger.GetTagger(tokenizerName);
- }
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpTokenizer.cs b/BotSharp.Core/Engines/BotSharp/BotSharpTokenizer.cs
deleted file mode 100644
index 254a92fd7..000000000
--- a/BotSharp.Core/Engines/BotSharp/BotSharpTokenizer.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using BotSharp.Core.Abstractions;
-using CherubNLP;
-using CherubNLP.Tokenize;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.AiResponse;
-using BotSharp.Platform.Models.MachineLearning;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Engines.BotSharp
-{
- public class BotSharpTokenizer : INlpTrain, INlpPredict
- {
- public IConfiguration Configuration { get; set; }
- public PipeSettings Settings { get; set; }
- private TokenizerFactory _tokenizer;
-
- public BotSharpTokenizer()
- {
-
- }
-
- public async Task Predict(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- Init();
-
- doc.Tokenizer = this;
-
- // same as train
- doc.Sentences.ForEach(snt =>
- {
- snt.Tokens = _tokenizer.Tokenize(snt.Text);
- });
-
- return true;
- }
-
- public async Task Train(AgentBase agent, NlpDoc doc, PipeModel meta)
- {
- Init();
-
- doc.Tokenizer = this;
- doc.Sentences = new List();
-
- agent.Corpus.UserSays.ForEach(say =>
- {
- doc.Sentences.Add(new NlpDocSentence
- {
- Tokens = _tokenizer.Tokenize(say.Text),
- Text = say.Text,
- Intent = new TextClassificationResult { Label = say.Intent }
- });
- });
-
- return true;
- }
-
- private void Init()
- {
- if(_tokenizer == null)
- {
- _tokenizer = new TokenizerFactory(new TokenizationOptions
- {
- Pattern = Configuration.GetValue("options:pattern")
- }, SupportedLanguage.English);
-
- string tokenizerName = Configuration.GetValue($"tokenizer");
-
- _tokenizer.GetTokenizer(tokenizerName);
- }
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotTrainer.cs b/BotSharp.Core/Engines/BotTrainer.cs
deleted file mode 100644
index 8b7690df2..000000000
--- a/BotSharp.Core/Engines/BotTrainer.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BotSharp.Core.Abstractions;
-using BotSharp.Platform.Abstractions;
-using BotSharp.Platform.Models;
-using BotSharp.Platform.Models.MachineLearning;
-using DotNetToolkit;
-using EntityFrameworkCore.BootKit;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Serialization;
-
-namespace BotSharp.Core.Engines
-{
- public class BotTrainer
- {
- private readonly Database dc;
-
- private readonly string agentId;
- private readonly IPlatformSettings settings;
-
- public BotTrainer(IPlatformSettings setting)
- {
- this.settings = setting;
- }
-
- public BotTrainer(string agentId, Database dc)
- {
- this.dc = dc;
- this.agentId = agentId;
- }
-
- public async Task Train(AgentBase agent, BotTrainOptions options)
- {
- var data = new NlpDoc();
-
- // Get NLP Provider
- var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration");
- var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies");
- var platform = config.GetSection($"platformModuleName").Value;
- var engine = this.settings.BotEngine;
- string providerName = config.GetSection($"{engine}_{agent.Language}:Provider").Value;
- var provider = TypeHelper.GetInstance(providerName, assemblies) as INlpProvider;
- provider.Configuration = config.GetSection($"{engine}_{agent.Language}");
-
- var pipeModel = new PipeModel
- {
- Name = providerName,
- Class = provider.ToString(),
- Meta = new JObject(),
- Time = DateTime.UtcNow
- };
-
- await provider.Load(agent, pipeModel);
-
- var settings = new PipeSettings
- {
- ProjectDir = options.AgentDir
- };
-
- settings.ModelDir = Path.Combine(options.AgentDir, options.Model);
-
- if (!Directory.Exists(settings.ProjectDir))
- {
- Directory.CreateDirectory(settings.ProjectDir);
- }
-
- if (!Directory.Exists(settings.ModelDir))
- {
- Directory.CreateDirectory(settings.ModelDir);
- }
-
- var meta = new ModelMetaData
- {
- Platform = platform,
- BotEngine = engine,
- Language = agent.Language,
- TrainingDate = DateTime.UtcNow,
- Version = config.GetValue($"Version"),
- Pipeline = new List() { pipeModel },
- Model = settings.ModelDir
- };
-
- // pipe process
- var pipelines = provider.Configuration.GetValue($"pipe")
- .Split(',')
- .Select(x => x.Trim())
- .ToList();
-
- for (int pipeIdx = 0; pipeIdx < pipelines.Count; pipeIdx++)
- {
- Console.WriteLine("");
- Console.WriteLine($"Executing {pipeModel.Name}");
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
-
- var pipe = TypeHelper.GetInstance(pipelines[pipeIdx], assemblies) as INlpTrain;
- // set configuration to current section
- pipe.Configuration = provider.Configuration.GetSection(pipelines[pipeIdx]);
- pipe.Settings = settings;
- pipeModel = new PipeModel
- {
- Name = pipelines[pipeIdx],
- Class = pipe.ToString(),
- Time = DateTime.UtcNow
- };
- meta.Pipeline.Add(pipeModel);
-
- Console.WriteLine(JsonConvert.SerializeObject(pipeModel, Formatting.Indented));
- await pipe.Train(agent, data, pipeModel);
-
- stopwatch.Stop();
- Console.WriteLine($"Executed pipe {pipeModel.Name} elapsed {stopwatch.Elapsed}");
- }
-
- // save model meta data
- var metaJson = JsonConvert.SerializeObject(meta, new JsonSerializerSettings
- {
- Formatting = Formatting.Indented,
- NullValueHandling = NullValueHandling.Ignore,
- ContractResolver = new CamelCasePropertyNamesContractResolver()
- });
- File.WriteAllText(Path.Combine(settings.ModelDir, "model-meta.json"), metaJson);
-
- return meta;
- }
- }
-}
diff --git a/BotSharp.Core/Engines/DbInitializer.cs b/BotSharp.Core/Engines/DbInitializer.cs
deleted file mode 100644
index 3a955d25e..000000000
--- a/BotSharp.Core/Engines/DbInitializer.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-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.Text;
-
-namespace BotSharp.Core.Engines
-{
- public class DbInitializer : IInitializationLoader
- {
- public int Priority => 1;
-
- public void Initialize(IConfiguration config, IWebHostEnvironment env)
- {
- var dc = new DefaultDataContextLoader().GetDefaultDc();
-
- var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies");
- var instances = TypeHelper.GetInstanceWithInterface(assemblies);
-
- // initial app db order by priority
- instances.OrderBy(x => x.Priority).ToList()
- .ForEach(instance =>
- {
- Console.WriteLine($"DbInitializer: {instance.ToString()}");
- dc.Transaction(() => instance.Load(dc));
- });
- }
- }
-}
diff --git a/BotSharp.Core/Engines/NERs/DucklingEntityRecognizer.cs b/BotSharp.Core/Engines/NERs/DucklingEntityRecognizer.cs
deleted file mode 100644
index 2405aa202..000000000
--- a/BotSharp.Core/Engines/NERs/DucklingEntityRecognizer.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using BotSharp.Core.Abstractions;
-using Microsoft.Extensions.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Engines.NERs
-{
- public class DucklingEntityRecognizer : INlpNer
- {
- public List Ontologies => throw new NotImplementedException();
-
- public IConfiguration Configuration { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- public PipeSettings Settings { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- }
-}
diff --git a/BotSharp.Core/Engines/NERs/OntologyEnum.cs b/BotSharp.Core/Engines/NERs/OntologyEnum.cs
deleted file mode 100644
index fdbbac1e2..000000000
--- a/BotSharp.Core/Engines/NERs/OntologyEnum.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Engines.NERs
-{
- ///
- /// Ontology encompasses a representation, formal naming, and definition of the categories, properties, and relations between the concepts, data, and entities that substantiate one, many, or all domains.
- ///
- public enum OntologyEnum
- {
- ///
- /// 6 miles
- ///
- Distance = 1,
- ///
- /// 3 mins
- ///
- Duration = 2,
- ///
- /// team@botsharp.com
- ///
- Email = 3,
- ///
- /// eighty eight
- ///
- Numeral = 4,
- ///
- /// 33rd
- ///
- Ordinal = 5,
- ///
- /// +1 (312) 292-6741
- ///
- PhoneNumber = 6,
- ///
- /// 3 cups of sugar
- ///
- Quantity = 7,
- ///
- /// 80F
- ///
- Temperature = 8,
- ///
- /// today at 9am
- ///
- DateTime = 9,
- ///
- /// https://github.com/Oceania2018/BotSharp
- ///
- Url = 10,
- ///
- /// 4 gallons
- ///
- Volume = 11,
- ///
- /// Chicago
- ///
- Location = 12
- }
-}
diff --git a/BotSharp.Core/Engines/NERs/README.md b/BotSharp.Core/Engines/NERs/README.md
deleted file mode 100644
index 126a4d9b9..000000000
--- a/BotSharp.Core/Engines/NERs/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Extend Botsharp's entity recognition capabilities
-
-## Expand with Facebook Duckling
-Duckling is a Haskell library that parses text into structured data. A Haskell environment is required.
-```
-sudo apt install haskell-stack
-
-```
-Clone ducking from github
-```
-git clone https://github.com/facebook/duckling
-cd duckling
-stack setup
-stack build
-```
\ No newline at end of file
diff --git a/BotSharp.Core/Engines/NERs/WitAiEntityRecognizer.cs b/BotSharp.Core/Engines/NERs/WitAiEntityRecognizer.cs
deleted file mode 100644
index 4c32a60a0..000000000
--- a/BotSharp.Core/Engines/NERs/WitAiEntityRecognizer.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using BotSharp.Core.Abstractions;
-using BotSharp.Core.Agents;
-using BotSharp.Models.NLP;
-using DotNetToolkit;
-using Microsoft.Extensions.Configuration;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Serialization;
-using RestSharp;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BotSharp.Core.Engines.NERs
-{
- public class WitAiEntityRecognizer : INlpPredict, INlpNer
- {
- public List Ontologies
- {
- get
- {
- return new List
- {
- OntologyEnum.DateTime,
- OntologyEnum.Location
- };
- }
- }
-
- public IConfiguration Configuration { get; set; }
- public PipeSettings Settings { get; set; }
-
- public async Task Predict(Agent agent, NlpDoc doc, PipeModel meta)
- {
- var client = new RestClient($"{Configuration.GetSection("WitAiEntityRecognizer:url").Value}");
- var request = new RestRequest(Configuration.GetSection("WitAiEntityRecognizer:resource").Value, Method.GET);
- request.AddHeader("Authorization", "Bearer " + Configuration.GetSection("WitAiEntityRecognizer:serverAccessToken").Value);
- request.AddQueryParameter("v", Configuration.GetSection("WitAiEntityRecognizer:version").Value);
- request.AddQueryParameter("q", doc.Sentences[0].Text);
- request.AddQueryParameter("verbose", "true");
- request.AddQueryParameter("autosuggest", "true");
-
- var result = client.Execute(request);
-
- var entities = result.Data.Entities[0];
- if(entities.Datetime != null)
- {
- doc.Sentences[0].Entities.AddRange(entities.Datetime.Select(x => Map(x)));
- }
-
- if(entities.Location != null)
- {
- doc.Sentences[0].Entities.AddRange(entities.Location.Select(x => Map(x)));
- }
-
- return true;
- }
-
- private NlpEntity Map(WitAiEntity entity)
- {
- return new NlpEntity
- {
- Confidence = entity.Confidence,
- Start = entity.Start,
- Value = entity.Value,
- Entity = entity.Entity
- };
- }
-
- public async Task Train(Agent agent, NlpDoc doc, PipeModel meta)
- {
- return true;
- }
-
- private class WitAiResponse
- {
- public List Entities { get; set; }
- }
-
- private class WitAiEntityResponse
- {
- public List Location { get; set; }
- public List Datetime { get; set; }
- }
-
- private class WitAiEntity
- {
- [JsonProperty("_entity")]
- public string Entity { get; set; }
- [JsonProperty("_start")]
- public int Start { get; set; }
- public string Value { get; set; }
- public decimal Confidence { get; set; }
- }
- }
-}
diff --git a/BotSharp.Core/Engines/NlpDoc.cs b/BotSharp.Core/Engines/NlpDoc.cs
deleted file mode 100644
index ea0f05aac..000000000
--- a/BotSharp.Core/Engines/NlpDoc.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using BotSharp.Core.Abstractions;
-using CherubNLP.Tokenize;
-using BotSharp.Platform.Models.AiResponse;
-using BotSharp.Platform.Models.Entities;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace BotSharp.Core.Engines
-{
- public class NlpDoc
- {
- public INlpPredict Tokenizer { get; set; }
- public List Sentences { get; set; }
- }
-
- public class NlpDocSentence
- {
- public string Text { get; set; }
- public List Tokens { get; set; }
- public List Entities { get; set; }
- public TextClassificationResult Intent { get; set; }
- }
-}
diff --git a/BotSharp.Core/Engines/PipeSettings.cs b/BotSharp.Core/Engines/PipeSettings.cs
deleted file mode 100644
index e28811406..000000000
--- a/BotSharp.Core/Engines/PipeSettings.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-namespace BotSharp.Core.Engines
-{
- public class PipeSettings
- {
- public string ProjectDir { get; set; }
- public string ModelDir { get; set; }
- }
-}
diff --git a/BotSharp.Core/Engines/QuickQA/AgentImporterInQuickQA.cs b/BotSharp.Core/Engines/QuickQA/AgentImporterInQuickQA.cs
deleted file mode 100644
index 11c6f9898..000000000
--- a/BotSharp.Core/Engines/QuickQA/AgentImporterInQuickQA.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using BotSharp.Core.Agents;
-using BotSharp.Core.Intents;
-using BotSharp.Platform.Abstraction;
-using BotSharp.Platform.Models;
-using Newtonsoft.Json;
-
-namespace BotSharp.Core.Engines.QuickQA
-{
- public class AgentImporterInQuickQA : IAgentImporter
- {
- public string AgentDir { get; set; }
-
- public Agent LoadAgent(AgentImportHeader agentHeader)
- {
- var agent = new Agent();
- agent.ClientAccessToken = Guid.NewGuid().ToString("N");
- agent.DeveloperAccessToken = Guid.NewGuid().ToString("N");
- agent.Id = agentHeader.Id;
- agent.Name = agentHeader.Name;
-
- return agent;
- }
-
- public void LoadBuildinEntities(Agent agent)
- {
-
- }
-
- public void LoadCustomEntities(Agent agent)
- {
-
- }
-
- public void LoadIntents(Agent agent)
- {
- string lines = File.ReadAllText(Path.Combine(AgentDir, "corpus.txt"));
-
- var questions = Regex.Matches(lines, @"^Q - .+\n", RegexOptions.Multiline).Cast().ToArray();
- var answers = Regex.Matches(lines, @"^A - ", RegexOptions.Multiline).Cast().ToArray();
-
- int qNumber = 1;
- agent.Intents = questions.Select(x => new Intent
- {
- Name = $"Q{qNumber++}",
- UserSays = new List
- {
- new IntentExpression
- {
- Data = new List
- {
- new IntentExpressionPart
- {
- Text = x.Value.Substring(4).Trim()
- }
- }
- }
- }
- }).ToList();
-
- // assemble answers
- for (int idx = 0; idx < agent.Intents.Count(); idx++)
- {
- var intent = agent.Intents[idx];
- var answer = answers[idx];
-
- var start = answer.Index + 4;
- var length = ((idx == agent.Intents.Count() - 1) ? lines.Length : questions[idx + 1].Index) - answer.Index - 4;
-
- intent.Responses = new List