add ContextStorageFactory
persist context to file
This commit is contained in:
parent
0520eddc6e
commit
3c7c3c183b
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -291,3 +291,4 @@ __pycache__/
|
||||||
/docs/_build
|
/docs/_build
|
||||||
*.RestApi.xml
|
*.RestApi.xml
|
||||||
/BotSharp.WebHost/App_Data/AgentStorage
|
/BotSharp.WebHost/App_Data/AgentStorage
|
||||||
|
/BotSharp.WebHost/App_Data/SessionStorage
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace BotSharp.Core.AgentStorage
|
||||||
this.platformSetting = setting;
|
this.platformSetting = setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IAgentStorage<TAgent>> Get()
|
public IAgentStorage<TAgent> Get()
|
||||||
{
|
{
|
||||||
IAgentStorage<TAgent> storage = null;
|
IAgentStorage<TAgent> storage = null;
|
||||||
string storageName = this.platformSetting.AgentStorage;
|
string storageName = this.platformSetting.AgentStorage;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,6 @@ namespace BotSharp.Core.AgentStorage
|
||||||
public class AgentStorageInFile<TAgent> : IAgentStorage<TAgent>
|
public class AgentStorageInFile<TAgent> : IAgentStorage<TAgent>
|
||||||
where TAgent : AgentBase
|
where TAgent : AgentBase
|
||||||
{
|
{
|
||||||
private static CSRedisClient csredis;
|
|
||||||
private static string prefix = String.Empty;
|
|
||||||
|
|
||||||
private static string storageDir;
|
private static string storageDir;
|
||||||
|
|
||||||
public AgentStorageInFile()
|
public AgentStorageInFile()
|
||||||
|
|
@ -27,7 +24,7 @@ namespace BotSharp.Core.AgentStorage
|
||||||
var db = config.GetSection("Database:Default").Value;
|
var db = config.GetSection("Database:Default").Value;
|
||||||
storageDir = config.GetSection($"Database:ConnectionStrings:{db}").Value;
|
storageDir = config.GetSection($"Database:ConnectionStrings:{db}").Value;
|
||||||
string contentDir = AppDomain.CurrentDomain.GetData("DataPath").ToString();
|
string contentDir = AppDomain.CurrentDomain.GetData("DataPath").ToString();
|
||||||
storageDir = storageDir.Replace("|DataDirectory|", contentDir + Path.DirectorySeparatorChar);
|
storageDir = storageDir.Replace("|DataDirectory|", contentDir + Path.DirectorySeparatorChar + "AgentStorage" + Path.DirectorySeparatorChar);
|
||||||
|
|
||||||
if (!Directory.Exists(storageDir))
|
if (!Directory.Exists(storageDir))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
28
BotSharp.Core/ContextStorage/ContextStorageFactory.cs
Normal file
28
BotSharp.Core/ContextStorage/ContextStorageFactory.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
using BotSharp.Platform.Abstraction;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.ContextStorage
|
||||||
|
{
|
||||||
|
public class ContextStorageFactory<T> : IContextStorageFactory<T>
|
||||||
|
{
|
||||||
|
private readonly Func<string, IContextStorage<T>> func;
|
||||||
|
private readonly IPlatformSettings platformSetting;
|
||||||
|
|
||||||
|
public ContextStorageFactory(IPlatformSettings setting, Func<string, IContextStorage<T>> serviceAccessor)
|
||||||
|
{
|
||||||
|
this.func = serviceAccessor;
|
||||||
|
this.platformSetting = setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IContextStorage<T> Get()
|
||||||
|
{
|
||||||
|
IContextStorage<T> storage = null;
|
||||||
|
string storageName = this.platformSetting.ContextStorage;
|
||||||
|
storage = func(storageName);
|
||||||
|
return storage as IContextStorage<T>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,51 @@
|
||||||
using BotSharp.Platform.Abstraction;
|
using BotSharp.Platform.Abstraction;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace BotSharp.Core.ContextStorage
|
namespace BotSharp.Core.ContextStorage
|
||||||
{
|
{
|
||||||
public class ContextStorageInFile : IContextStorage
|
public class ContextStorageInFile<T> : IContextStorage<T>
|
||||||
{
|
{
|
||||||
|
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<bool> Persist(string sessionId, T[] context)
|
||||||
|
{
|
||||||
|
var json = JsonConvert.SerializeObject(context, new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||||
|
Converters = new List<JsonConverter>
|
||||||
|
{
|
||||||
|
new Newtonsoft.Json.Converters.StringEnumConverter()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
string dataPath = Path.Combine(storageDir, sessionId + ".json");
|
||||||
|
|
||||||
|
File.WriteAllText(dataPath, json);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
using BotSharp.Platform.Abstraction;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.ContextStorage
|
||||||
|
{
|
||||||
|
public class ContextStorageServiceRegister
|
||||||
|
{
|
||||||
|
public static void Register<T>(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IContextStorageFactory<T>, ContextStorageFactory<T>>();
|
||||||
|
|
||||||
|
services.AddSingleton<ContextStorageInFile<T>>();
|
||||||
|
|
||||||
|
services.AddSingleton(factory =>
|
||||||
|
{
|
||||||
|
Func<string, IContextStorage<T>> accesor = key =>
|
||||||
|
{
|
||||||
|
if (key.Equals("ContextStorageInFile"))
|
||||||
|
{
|
||||||
|
return factory.GetService<ContextStorageInFile<T>>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Not Support key : {key}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return accesor;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,12 +32,11 @@ namespace BotSharp.Core
|
||||||
{
|
{
|
||||||
this.agentStorageFactory = agentStorageFactory;
|
this.agentStorageFactory = agentStorageFactory;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
GetAgentStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<TAgent>> GetAllAgents()
|
public async Task<List<TAgent>> GetAllAgents()
|
||||||
{
|
{
|
||||||
await GetStorage();
|
|
||||||
|
|
||||||
return await Storage.Query();
|
return await Storage.Query();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,15 +79,11 @@ namespace BotSharp.Core
|
||||||
|
|
||||||
public async Task<TAgent> GetAgentById(string agentId)
|
public async Task<TAgent> GetAgentById(string agentId)
|
||||||
{
|
{
|
||||||
GetStorage();
|
|
||||||
|
|
||||||
return await Storage.FetchById(agentId);
|
return await Storage.FetchById(agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TAgent> GetAgentByName(string agentName)
|
public async Task<TAgent> GetAgentByName(string agentName)
|
||||||
{
|
{
|
||||||
await GetStorage();
|
|
||||||
|
|
||||||
return await Storage.FetchByName(agentName);
|
return await Storage.FetchByName(agentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,7 +190,7 @@ namespace BotSharp.Core
|
||||||
|
|
||||||
Console.WriteLine($"TextResponse: {aiResponse.Intent}, {request.SessionId}");
|
Console.WriteLine($"TextResponse: {aiResponse.Intent}, {request.SessionId}");
|
||||||
|
|
||||||
return await AssembleResult<TResult>(aiResponse);
|
return await AssembleResult<TResult>(request, aiResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<TextClassificationResult> FallbackResponse(AiRequest request)
|
public virtual async Task<TextClassificationResult> FallbackResponse(AiRequest request)
|
||||||
|
|
@ -222,27 +217,25 @@ namespace BotSharp.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<TResult> AssembleResult<TResult>(AiResponse response)
|
public virtual async Task<TResult> AssembleResult<TResult>(AiRequest request, AiResponse response)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<bool> SaveAgent(TAgent agent)
|
public virtual async Task<bool> SaveAgent(TAgent agent)
|
||||||
{
|
{
|
||||||
await GetStorage();
|
|
||||||
|
|
||||||
// default save agent in FileStorage
|
// default save agent in FileStorage
|
||||||
await Storage.Persist(agent);
|
await Storage.Persist(agent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
protected IAgentStorage<TAgent> GetAgentStorage()
|
||||||
protected async Task<IAgentStorage<TAgent>> GetStorage()
|
|
||||||
{
|
{
|
||||||
if (Storage == null)
|
if (Storage == null)
|
||||||
{
|
{
|
||||||
Storage = await agentStorageFactory.Get();
|
Storage = agentStorageFactory.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Storage;
|
return Storage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,13 @@ namespace BotSharp.Core
|
||||||
{
|
{
|
||||||
BotEngine = "BotSharpNLU";
|
BotEngine = "BotSharpNLU";
|
||||||
AgentStorage = "AgentStorageInFile";
|
AgentStorage = "AgentStorageInFile";
|
||||||
|
ContextStorage = "ContextStorageInFile";
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BotEngine { get; set; }
|
public string BotEngine { get; set; }
|
||||||
|
|
||||||
|
public string ContextStorage { get; set; }
|
||||||
|
|
||||||
public string AgentStorage { get; set; }
|
public string AgentStorage { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ namespace BotSharp.Platform.Abstraction
|
||||||
{
|
{
|
||||||
public interface IAgentStorageFactory<TAgent> where TAgent : AgentBase
|
public interface IAgentStorageFactory<TAgent> where TAgent : AgentBase
|
||||||
{
|
{
|
||||||
Task<IAgentStorage<TAgent>> Get();
|
IAgentStorage<TAgent> Get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace BotSharp.Platform.Abstraction
|
namespace BotSharp.Platform.Abstraction
|
||||||
{
|
{
|
||||||
public interface IContextStorage
|
public interface IContextStorage<T>
|
||||||
{
|
{
|
||||||
|
Task<bool> Persist(string sessionId, T[] context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
BotSharp.Platform.Abstraction/IContextStorageFactory.cs
Normal file
11
BotSharp.Platform.Abstraction/IContextStorageFactory.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using BotSharp.Platform.Abstraction;
|
||||||
|
using BotSharp.Platform.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BotSharp.Platform.Abstraction
|
||||||
|
{
|
||||||
|
public interface IContextStorageFactory<T>
|
||||||
|
{
|
||||||
|
IContextStorage<T> Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ namespace BotSharp.Platform.Abstraction
|
||||||
|
|
||||||
Task<TResult> TextRequest<TResult>(AiRequest request);
|
Task<TResult> TextRequest<TResult>(AiRequest request);
|
||||||
|
|
||||||
Task<TResult> AssembleResult<TResult>(AiResponse response);
|
Task<TResult> AssembleResult<TResult>(AiRequest request, AiResponse response);
|
||||||
|
|
||||||
Task<TextClassificationResult> FallbackResponse(AiRequest request);
|
Task<TextClassificationResult> FallbackResponse(AiRequest request);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,7 @@ namespace BotSharp.Platform.Abstraction
|
||||||
string BotEngine { get; set; }
|
string BotEngine { get; set; }
|
||||||
|
|
||||||
string AgentStorage { get; set; }
|
string AgentStorage { get; set; }
|
||||||
|
|
||||||
|
string ContextStorage { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,13 @@ namespace BotSharp.Platform.Dialogflow
|
||||||
where TAgent : AgentModel
|
where TAgent : AgentModel
|
||||||
{
|
{
|
||||||
IConfiguration config;
|
IConfiguration config;
|
||||||
|
IContextStorageFactory<AIContext> contextStorageFactory;
|
||||||
|
|
||||||
public DialogflowAi(IAgentStorageFactory<TAgent> agentStorageFactory, IPlatformSettings settings, IConfiguration config)
|
public DialogflowAi(IAgentStorageFactory<TAgent> agentStorageFactory, IContextStorageFactory<AIContext> contextStorageFactory, IPlatformSettings settings, IConfiguration config)
|
||||||
:base(agentStorageFactory, settings)
|
:base(agentStorageFactory, settings)
|
||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.contextStorageFactory = contextStorageFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TrainingCorpus> ExtractorCorpus(TAgent agent)
|
public async Task<TrainingCorpus> ExtractorCorpus(TAgent agent)
|
||||||
|
|
@ -110,7 +112,7 @@ namespace BotSharp.Platform.Dialogflow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<TResult> AssembleResult<TResult>(AiResponse response)
|
public override async Task<TResult> AssembleResult<TResult>(AiRequest request, AiResponse response)
|
||||||
{
|
{
|
||||||
var intent = Agent.Intents.Find(x => x.Name == response.Intent);
|
var intent = Agent.Intents.Find(x => x.Name == response.Intent);
|
||||||
var presetResponse = intent.Responses.FirstOrDefault();
|
var presetResponse = intent.Responses.FirstOrDefault();
|
||||||
|
|
@ -135,7 +137,7 @@ namespace BotSharp.Platform.Dialogflow
|
||||||
var matches = Regex.Matches(presetResponse.Messages.Random().Speech, "\".*?\"").Cast<Match>();
|
var matches = Regex.Matches(presetResponse.Messages.Random().Speech, "\".*?\"").Cast<Match>();
|
||||||
var speech = matches.Count() == 0 ? String.Empty : matches.ToList().Random().Value;
|
var speech = matches.Count() == 0 ? String.Empty : matches.ToList().Random().Value;
|
||||||
|
|
||||||
var contexts = HandleContexts(presetResponse);
|
var contexts = HandleContexts(request.SessionId, presetResponse);
|
||||||
|
|
||||||
var aiResponse = new AIResponseResult
|
var aiResponse = new AIResponseResult
|
||||||
{
|
{
|
||||||
|
|
@ -160,7 +162,7 @@ namespace BotSharp.Platform.Dialogflow
|
||||||
return (TResult)(object)aiResponse;
|
return (TResult)(object)aiResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AIContext> HandleContexts(IntentResponse response)
|
private List<AIContext> HandleContexts(string sessionId, IntentResponse response)
|
||||||
{
|
{
|
||||||
var newContexts = response.Contexts.Select(x => new AIContext
|
var newContexts = response.Contexts.Select(x => new AIContext
|
||||||
{
|
{
|
||||||
|
|
@ -170,6 +172,8 @@ namespace BotSharp.Platform.Dialogflow
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
// persist
|
// persist
|
||||||
|
var ctxStore = contextStorageFactory.Get();
|
||||||
|
ctxStore.Persist(sessionId, newContexts.ToArray());
|
||||||
|
|
||||||
return newContexts;
|
return newContexts;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using BotSharp.Core;
|
using BotSharp.Core;
|
||||||
using BotSharp.Core.AgentStorage;
|
using BotSharp.Core.AgentStorage;
|
||||||
|
using BotSharp.Core.ContextStorage;
|
||||||
using BotSharp.Core.Modules;
|
using BotSharp.Core.Modules;
|
||||||
using BotSharp.Platform.Abstraction;
|
using BotSharp.Platform.Abstraction;
|
||||||
using BotSharp.Platform.Dialogflow.Models;
|
using BotSharp.Platform.Dialogflow.Models;
|
||||||
|
|
@ -21,6 +22,7 @@ namespace BotSharp.Platform.Dialogflow
|
||||||
services.AddSingleton<DialogflowAi<AgentModel>>();
|
services.AddSingleton<DialogflowAi<AgentModel>>();
|
||||||
AgentStorageServiceRegister.Register<AgentModel>(services);
|
AgentStorageServiceRegister.Register<AgentModel>(services);
|
||||||
PlatformConfigServiceRegister.Register<PlatformSettings>("dialogflowAi", services, config);
|
PlatformConfigServiceRegister.Register<PlatformSettings>("dialogflowAi", services, config);
|
||||||
|
ContextStorageServiceRegister.Register<AIContext>(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// if you want to override platform setting, please set corresponding value, otherwise you don't need this section.
|
// if you want to override platform setting, please set corresponding value, otherwise you don't need this section.
|
||||||
"dialogflowAi": {
|
"dialogflowAi": {
|
||||||
"botEngine": "BotSharpNLU",
|
"botEngine": "BotSharpNLU",
|
||||||
"agentStorage": "AgentStorageInFile"
|
"agentStorage": "AgentStorageInFile",
|
||||||
|
"contextStorage": "ContextStorageInFile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
"Redis": "127.0.0.1:6379,defaultDatabase=BotSharp,poolsize=50,ssl=false,writeBuffer=10240,prefix=agent_",
|
"Redis": "127.0.0.1:6379,defaultDatabase=BotSharp,poolsize=50,ssl=false,writeBuffer=10240,prefix=agent_",
|
||||||
"Sqlite": "Data Source=|DataDirectory|BotSharp.db;",
|
"Sqlite": "Data Source=|DataDirectory|BotSharp.db;",
|
||||||
"SqlServer": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=BotSharp;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
"SqlServer": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=BotSharp;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
||||||
"File": "|DataDirectory|AgentStorage"
|
"File": "|DataDirectory|"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue