refactor di and modify async/await

feat : refactor di and modify async/await
This commit is contained in:
geffzhang 2018-10-05 14:39:39 +08:00
parent 8871a6c3a7
commit 83b9a2347e
23 changed files with 271 additions and 78 deletions

View file

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Core
{
@ -20,7 +21,7 @@ namespace BotSharp.Core
if (agents == null) agents = new Dictionary<string, TAgent>();
}
public TAgent FetchById(string agentId)
public async Task<TAgent> FetchById(string agentId)
{
if (agents.ContainsKey(agentId))
{
@ -32,14 +33,14 @@ namespace BotSharp.Core
}
}
public TAgent FetchByName(string agentName)
public async Task<TAgent> FetchByName(string agentName)
{
var data = agents.FirstOrDefault(x => x.Value.Name == agentName);
return data.Value;
}
public bool Persist(TAgent agent)
public async Task<bool> Persist(TAgent agent)
{
if (String.IsNullOrEmpty(agent.Id))
{
@ -54,7 +55,7 @@ namespace BotSharp.Core
return true;
}
public int PurgeAllAgents()
public async Task<int> PurgeAllAgents()
{
int count = agents.Count;
@ -63,7 +64,7 @@ namespace BotSharp.Core
return count;
}
public List<TAgent> Query()
public async Task<List<TAgent>> Query()
{
return agents.Select(x => x.Value).ToList();
}

View file

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Core
{
@ -30,7 +31,7 @@ namespace BotSharp.Core
}
}
public TAgent FetchById(string agentId)
public async Task<TAgent> FetchById(string agentId)
{
var key = agentId;
if (csredis.Exists(key))
@ -43,7 +44,7 @@ namespace BotSharp.Core
}
}
public TAgent FetchByName(string agentName)
public async Task<TAgent> FetchByName(string agentName)
{
var agents = new List<TAgent>();
@ -62,7 +63,7 @@ namespace BotSharp.Core
return default(TAgent);
}
public bool Persist(TAgent agent)
public async Task<bool> Persist(TAgent agent)
{
if (String.IsNullOrEmpty(agent.Id))
{
@ -80,7 +81,7 @@ namespace BotSharp.Core
return true;
}
public int PurgeAllAgents()
public async Task<int> PurgeAllAgents()
{
var keys = csredis.Keys($"{prefix}*");
@ -89,7 +90,7 @@ namespace BotSharp.Core
return keys.Count();
}
public List<TAgent> Query()
public async Task<List<TAgent>> Query()
{
var agents = new List<TAgent>();

View file

@ -79,6 +79,7 @@ If you feel that this project is helpful to you, please Star on the project, we
<PackageReference Include="DotNetToolkit" Version="1.6.0" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="1.9.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="RestSharp" Version="106.4.2" />
</ItemGroup>

View file

@ -24,19 +24,19 @@ namespace BotSharp.Core.Engines
/// </summary>
public abstract class BotEngineBase
{
protected Database dc;
protected Database Dc;
protected AgentBase agent { get; set; }
protected AgentBase Agent { get; set; }
public BotEngineBase()
{
dc = new DefaultDataContextLoader().GetDefaultDc();
Dc = new DefaultDataContextLoader().GetDefaultDc();
}
public AiResponse TextRequest(AiRequest request)
public async Task<AiResponse> TextRequest(AiRequest request)
{
var preditor = new BotPredictor();
var doc = preditor.Predict(agent, new AiRequest
var doc = preditor.Predict(Agent, new AiRequest
{
AgentDir = request.AgentDir,
Model = request.Model,

View file

@ -11,8 +11,8 @@ namespace BotSharp.Core.Engines.BotSharp
{
public override async Task Train(BotTrainOptions options)
{
var trainer = new BotTrainer(agent.Id, dc);
await trainer.Train(agent, options);
var trainer = new BotTrainer(Agent.Id, Dc);
await trainer.Train(Agent, options);
}
}
}

View file

@ -19,9 +19,9 @@ namespace BotSharp.Core.Engines
{
public class BotTrainer
{
private Database dc;
private readonly Database dc;
private string agentId;
private readonly string agentId;
public BotTrainer()
{

View file

@ -0,0 +1,11 @@
using BotSharp.Platform.Abstraction;
using BotSharp.Platform.Models;
using System.Threading.Tasks;
namespace BotSharp.Core
{
public interface IAgentStorageFactory
{
Task<IAgentStorage<TAgent>> Get<TAgent>() where TAgent : AgentBase;
}
}

View file

@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace BotSharp.Core.Modules
{
/// <summary>
/// Represents a configurable module containing multiple servies.
/// </summary>
public interface IModule
{
/// <summary>
/// Configurates the module services.
/// </summary>
/// <param name="services">
/// Instance of <see cref="IServiceCollection"/>.
/// </param>
/// <returns>
/// Instance of <see cref="IServiceProvider"/>.
/// </returns>
void ConfigureServices(IServiceCollection services, IConfiguration configuration);
/// <summary>
/// Configures module services.
/// </summary>
/// <param name="app">
/// Instance of <see cref="IApplicationBuilder"/>.
/// </param>
void Configure(IApplicationBuilder app);
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Modules
{
/// <summary>
/// Module configuration .
/// </summary>
public class ModuleOptions
{
/// <summary>
/// Module type.
/// </summary>
public string Type { get; set; }
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Modules
{
/// <summary>
/// Module Host configuration.
/// </summary>
public class ModulesOptions
{
/// <summary>
/// List of module configurations.
/// </summary>
public List<ModuleOptions> Modules { get; set; }
}
}

View file

@ -0,0 +1,79 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BotSharp.Core.Modules
{
/// <summary>
/// Startup class for configurable modules
/// </summary>
public class ModulesStartup
{
private readonly IEnumerable<IModule> _modules;
private readonly IConfiguration _configuration;
/// <summary>
/// Create an instance of <see cref="ModulesStartup"/>
/// </summary>
/// <param name="configuration">
/// Application configuration containing modules configuration
/// </param>
public ModulesStartup(IConfiguration configuration)
{
this._configuration = configuration ??
throw new ArgumentNullException(nameof(configuration));
ModulesOptions options = configuration.Get<ModulesOptions>();
this._modules = options.Modules
.Select(s =>
{
Type type = Type.GetType(s.Type);
if (type == null)
{
throw new TypeLoadException(
$"Cannot load type \"{s.Type}\"");
}
IModule module = (IModule)Activator.CreateInstance(type);
return module;
}
);
}
/// <summary>
/// Configurates the services.
/// </summary>
/// <param name="services">
/// Instance of <see cref="IServiceCollection"/>.
/// </param>
/// <returns>
/// Instance of <see cref="IServiceProvider"/>.
/// </returns>
public void ConfigureServices(IServiceCollection services)
{
foreach (IModule module in this._modules)
{
module.ConfigureServices(services, this._configuration);
}
}
/// <summary>
/// Configures module services.
/// </summary>
/// <param name="app">
/// Instance of <see cref="IApplicationBuilder"/>.
/// </param>
public void Configure(IApplicationBuilder app)
{
foreach (IModule module in this._modules)
{
module.Configure(app);
}
}
}
}

View file

@ -0,0 +1,17 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core
{
public class NLUSetting
{
public string BotEngine { get; set; }
public string AgentStorage { get; set; }
}
}

View file

@ -18,34 +18,39 @@ namespace BotSharp.Core
{
public IAgentStorage<TAgent> Storage { get; set; }
public IConfiguration PlatformConfig { get; set; }
private readonly IAgentStorageFactory agentStorageFactory;
public List<TAgent> GetAllAgents()
public PlatformBuilderBase(IAgentStorageFactory agentStorageFactory)
{
GetStorage();
return Storage.Query();
this.agentStorageFactory = agentStorageFactory;
}
public TAgent LoadAgentFromFile<TImporter>(string dataDir) where TImporter : IAgentImporter<TAgent>, new()
public async Task<List<TAgent>> GetAllAgents()
{
await GetStorage();
return await Storage.Query();
}
public async Task<TAgent> LoadAgentFromFile<TImporter>(string dataDir) where TImporter : IAgentImporter<TAgent>, new()
{
var meta = LoadMeta(dataDir);
var importer = new TImporter();
importer.AgentDir = dataDir;
var importer = new TImporter
{
AgentDir = dataDir
};
// Load agent summary
var agent = importer.LoadAgent(meta);
var agent = await importer.LoadAgent(meta);
// Load user custom entities
importer.LoadCustomEntities(agent);
await importer.LoadCustomEntities(agent);
// Load agent intents
importer.LoadIntents(agent);
await importer.LoadIntents(agent);
// Load system buildin entities
importer.LoadBuildinEntities(agent);
await importer.LoadBuildinEntities(agent);
return agent;
}
@ -58,18 +63,18 @@ namespace BotSharp.Core
return JsonConvert.DeserializeObject<AgentImportHeader>(metaJson);
}
public TAgent GetAgentById(string agentId)
public async Task<TAgent> GetAgentById(string agentId)
{
GetStorage();
return Storage.FetchById(agentId);
return await Storage.FetchById(agentId);
}
public TAgent GetAgentByName(string agentName)
public async Task<TAgent> GetAgentByName(string agentName)
{
GetStorage();
await GetStorage();
return Storage.FetchByName(agentName);
return await Storage.FetchByName(agentName);
}
public virtual async Task<ModelMetaData> Train(TAgent agent, TrainingCorpus corpus, BotTrainOptions options)
@ -92,32 +97,22 @@ namespace BotSharp.Core
return info;
}
public virtual bool SaveAgent(TAgent agent)
public virtual async Task<bool> SaveAgent(TAgent agent)
{
GetStorage();
await GetStorage();
// default save agent in FileStorage
Storage.Persist(agent);
await Storage.Persist(agent);
return true;
}
private IAgentStorage<TAgent> GetStorage()
protected async Task<IAgentStorage<TAgent>> GetStorage()
{
if (Storage == null)
{
string storageName = PlatformConfig.GetValue<String>("AgentStorage");
switch (storageName)
{
case "AgentStorageInRedis":
Storage = Activator.CreateInstance<AgentStorageInRedis<TAgent>>();
break;
case "AgentStorageInMemory":
Storage = Activator.CreateInstance<AgentStorageInMemory<TAgent>>();
break;
}
Storage = await agentStorageFactory.Get<TAgent>();
}
return Storage;
}
}

View file

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Platform.Abstraction
{
@ -16,24 +17,24 @@ namespace BotSharp.Platform.Abstraction
/// Load agent summary
/// </summary>
/// <returns></returns>
TAgent LoadAgent(AgentImportHeader agentHeader);
Task<TAgent> LoadAgent(AgentImportHeader agentHeader);
/// <summary>
/// Load user customized entity type which defined in dictionary
/// </summary>
/// <param name="agent"></param>
void LoadCustomEntities(TAgent agent);
Task LoadCustomEntities(TAgent agent);
/// <summary>
/// Load user customized intents
/// </summary>
/// <param name="agent"></param>
void LoadIntents(TAgent agent);
Task LoadIntents(TAgent agent);
/// <summary>
/// Add entities that labeled in intent.UserSays into user customized entity dictionary
/// </summary>
/// <param name="agent"></param>
void LoadBuildinEntities(TAgent agent);
Task LoadBuildinEntities(TAgent agent);
}
}

View file

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Platform.Abstraction
{
@ -16,32 +17,32 @@ namespace BotSharp.Platform.Abstraction
/// </summary>
/// <param name="agent"></param>
/// <returns></returns>
bool Persist(TAgent agent);
Task<bool> Persist(TAgent agent);
/// <summary>
/// Get agent by id
/// </summary>
/// <param name="agentId"></param>
/// <returns></returns>
TAgent FetchById(string agentId);
Task<TAgent> FetchById(string agentId);
/// <summary>
/// Get agent by name
/// </summary>
/// <param name="agentName"></param>
/// <returns></returns>
TAgent FetchByName(string agentName);
Task<TAgent> FetchByName(string agentName);
/// <summary>
/// Query agents
/// </summary>
/// <returns></returns>
List<TAgent> Query();
Task<List<TAgent>> Query();
/// <summary>
/// Delete agents
/// </summary>
/// <returns></returns>
int PurgeAllAgents();
Task<int> PurgeAllAgents();
}
}

View file

@ -1,9 +1,6 @@
using BotSharp.Platform.Models;
using BotSharp.Platform.Models.AiRequest;
using BotSharp.Platform.Models.AiResponse;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Platform.Abstraction
@ -13,7 +10,7 @@ namespace BotSharp.Platform.Abstraction
/// </summary>
public interface IBotEngine
{
AiResponse TextRequest(AiRequest request);
Task<AiResponse> TextRequest(AiRequest request);
Task Train(BotTrainOptions options);
}

View file

@ -2,9 +2,6 @@
using BotSharp.Platform.Models.AiRequest;
using BotSharp.Platform.Models.AiResponse;
using BotSharp.Platform.Models.MachineLearning;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Platform.Abstraction
@ -30,7 +27,7 @@ namespace BotSharp.Platform.Abstraction
/// </summary>
/// <param name="agent"></param>
/// <returns></returns>
TrainingCorpus ExtractorCorpus(TAgent agent);
Task<TrainingCorpus> ExtractorCorpus(TAgent agent);
/// <summary>
/// Load agent from files.
@ -38,7 +35,7 @@ namespace BotSharp.Platform.Abstraction
/// </summary>
/// <param name="dataDir"></param>
/// <returns></returns>
TAgent LoadAgentFromFile<TImporter>(string dataDir) where TImporter : IAgentImporter<TAgent>, new();
Task<TAgent> LoadAgentFromFile<TImporter>(string dataDir) where TImporter : IAgentImporter<TAgent>, new();
/// <summary>
///
@ -46,10 +43,10 @@ namespace BotSharp.Platform.Abstraction
/// <typeparam name="TStorage"></typeparam>
/// <param name="agent"></param>
/// <returns></returns>
bool SaveAgent(TAgent agent);
Task<bool> SaveAgent(TAgent agent);
Task<ModelMetaData> Train(TAgent agent, TrainingCorpus corpus, BotTrainOptions options);
AiResponse TextRequest(AiRequest request);
Task<AiResponse> TextRequest(AiRequest request);
}
}

View file

@ -78,6 +78,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\botsharp-dialogflow\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj" />
<ProjectReference Include="..\..\botsharp-rasa\BotSharp.Platform.Rasa\BotSharp.Platform.Rasa.csproj" />
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
</ItemGroup>

View file

@ -2,6 +2,6 @@
"dialogflowAi": {
"botEngine": "BotSharpNLU",
"agentStorage": "AgentStorageInRedis"
"agentStorage": "AgentStorageInMemory"
}
}

View file

@ -2,6 +2,6 @@
"rasaAi": {
"botEngine": "BotSharpNLU",
"agentStorage": "AgentStorageInRedis"
"agentStorage": "AgentStorageInMemory"
}
}

View file

@ -8,5 +8,10 @@
"machineLearning": {
"dataDir": "D:\\Projects\\BotSharp\\Data"
}
},
"Modules": [
{ "Type": "BotSharp.Platform.Dialogflow.DialogflowModule, BotSharp.Platform.Dialogflow" },
//{ "Type": "BotSharp.Platform.Rasa.RasaModule, BotSharp.Platform.Rasa" }
]
}

View file

@ -1,4 +1,5 @@
using DotNetToolkit.JwtHelper;
using BotSharp.Core.Modules;
using DotNetToolkit.JwtHelper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
@ -18,8 +19,11 @@ namespace BotSharp.WebHost
public Startup(IConfiguration configuration)
{
Configuration = configuration;
this.modulesStartup = new ModulesStartup(configuration);
}
private readonly ModulesStartup modulesStartup;
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
@ -36,7 +40,8 @@ namespace BotSharp.WebHost
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
services.AddPlatformEmulator(Configuration, assembly => mvcBuilder.AddApplicationPart(assembly));
this.modulesStartup.ConfigureServices(services);
//services.AddPlatformEmulator(Configuration, assembly => mvcBuilder.AddApplicationPart(assembly));
services.AddSwaggerGen(c =>
{

View file

@ -24,6 +24,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Platform.Models",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Platform.Dialogflow", "..\botsharp-dialogflow\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj", "{83D56CDD-7122-48D3-9CDC-BCE21CB10681}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Platform.Rasa", "..\botsharp-rasa\BotSharp.Platform.Rasa\BotSharp.Platform.Rasa.csproj", "{2902810C-F8F2-400E-88DB-72CBE393B175}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -130,6 +132,18 @@ Global
{83D56CDD-7122-48D3-9CDC-BCE21CB10681}.Release|Any CPU.Build.0 = Release|Any CPU
{83D56CDD-7122-48D3-9CDC-BCE21CB10681}.Release|x64.ActiveCfg = Release|Any CPU
{83D56CDD-7122-48D3-9CDC-BCE21CB10681}.Release|x64.Build.0 = Release|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Debug|x64.ActiveCfg = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Debug|x64.Build.0 = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.DIALOGFLOW|Any CPU.ActiveCfg = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.DIALOGFLOW|Any CPU.Build.0 = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.DIALOGFLOW|x64.ActiveCfg = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.DIALOGFLOW|x64.Build.0 = Debug|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Release|Any CPU.Build.0 = Release|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Release|x64.ActiveCfg = Release|Any CPU
{2902810C-F8F2-400E-88DB-72CBE393B175}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE