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
|
||||
*.RestApi.xml
|
||||
/BotSharp.WebHost/App_Data/AgentStorage
|
||||
/BotSharp.WebHost/App_Data/SessionStorage
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace BotSharp.Core.AgentStorage
|
|||
this.platformSetting = setting;
|
||||
}
|
||||
|
||||
public async Task<IAgentStorage<TAgent>> Get()
|
||||
public IAgentStorage<TAgent> Get()
|
||||
{
|
||||
IAgentStorage<TAgent> storage = null;
|
||||
string storageName = this.platformSetting.AgentStorage;
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ namespace BotSharp.Core.AgentStorage
|
|||
public class AgentStorageInFile<TAgent> : IAgentStorage<TAgent>
|
||||
where TAgent : AgentBase
|
||||
{
|
||||
private static CSRedisClient csredis;
|
||||
private static string prefix = String.Empty;
|
||||
|
||||
private static string storageDir;
|
||||
|
||||
public AgentStorageInFile()
|
||||
|
|
@ -27,7 +24,7 @@ namespace BotSharp.Core.AgentStorage
|
|||
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);
|
||||
storageDir = storageDir.Replace("|DataDirectory|", contentDir + Path.DirectorySeparatorChar + "AgentStorage" + Path.DirectorySeparatorChar);
|
||||
|
||||
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 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
|
||||
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.settings = settings;
|
||||
GetAgentStorage();
|
||||
}
|
||||
|
||||
public async Task<List<TAgent>> GetAllAgents()
|
||||
{
|
||||
await GetStorage();
|
||||
|
||||
return await Storage.Query();
|
||||
}
|
||||
|
||||
|
|
@ -80,15 +79,11 @@ namespace BotSharp.Core
|
|||
|
||||
public async Task<TAgent> GetAgentById(string agentId)
|
||||
{
|
||||
GetStorage();
|
||||
|
||||
return await Storage.FetchById(agentId);
|
||||
}
|
||||
|
||||
public async Task<TAgent> GetAgentByName(string agentName)
|
||||
{
|
||||
await GetStorage();
|
||||
|
||||
return await Storage.FetchByName(agentName);
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +190,7 @@ namespace BotSharp.Core
|
|||
|
||||
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)
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
public virtual async Task<bool> SaveAgent(TAgent agent)
|
||||
{
|
||||
await GetStorage();
|
||||
|
||||
// default save agent in FileStorage
|
||||
await Storage.Persist(agent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async Task<IAgentStorage<TAgent>> GetStorage()
|
||||
protected IAgentStorage<TAgent> GetAgentStorage()
|
||||
{
|
||||
if (Storage == null)
|
||||
{
|
||||
Storage = await agentStorageFactory.Get();
|
||||
Storage = agentStorageFactory.Get();
|
||||
}
|
||||
|
||||
return Storage;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@ namespace BotSharp.Core
|
|||
{
|
||||
BotEngine = "BotSharpNLU";
|
||||
AgentStorage = "AgentStorageInFile";
|
||||
ContextStorage = "ContextStorageInFile";
|
||||
}
|
||||
|
||||
public string BotEngine { get; set; }
|
||||
|
||||
public string ContextStorage { get; set; }
|
||||
|
||||
public string AgentStorage { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ namespace BotSharp.Platform.Abstraction
|
|||
{
|
||||
public interface IAgentStorageFactory<TAgent> where TAgent : AgentBase
|
||||
{
|
||||
Task<IAgentStorage<TAgent>> Get();
|
||||
IAgentStorage<TAgent> Get();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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> AssembleResult<TResult>(AiResponse response);
|
||||
Task<TResult> AssembleResult<TResult>(AiRequest request, AiResponse response);
|
||||
|
||||
Task<TextClassificationResult> FallbackResponse(AiRequest request);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,5 +9,7 @@ namespace BotSharp.Platform.Abstraction
|
|||
string BotEngine { get; set; }
|
||||
|
||||
string AgentStorage { get; set; }
|
||||
|
||||
string ContextStorage { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ namespace BotSharp.Platform.Dialogflow
|
|||
where TAgent : AgentModel
|
||||
{
|
||||
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)
|
||||
{
|
||||
this.config = config;
|
||||
this.contextStorageFactory = contextStorageFactory;
|
||||
}
|
||||
|
||||
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 presetResponse = intent.Responses.FirstOrDefault();
|
||||
|
|
@ -135,7 +137,7 @@ namespace BotSharp.Platform.Dialogflow
|
|||
var matches = Regex.Matches(presetResponse.Messages.Random().Speech, "\".*?\"").Cast<Match>();
|
||||
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
|
||||
{
|
||||
|
|
@ -160,7 +162,7 @@ namespace BotSharp.Platform.Dialogflow
|
|||
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
|
||||
{
|
||||
|
|
@ -170,6 +172,8 @@ namespace BotSharp.Platform.Dialogflow
|
|||
}).ToList();
|
||||
|
||||
// persist
|
||||
var ctxStore = contextStorageFactory.Get();
|
||||
ctxStore.Persist(sessionId, newContexts.ToArray());
|
||||
|
||||
return newContexts;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Core;
|
||||
using BotSharp.Core.AgentStorage;
|
||||
using BotSharp.Core.ContextStorage;
|
||||
using BotSharp.Core.Modules;
|
||||
using BotSharp.Platform.Abstraction;
|
||||
using BotSharp.Platform.Dialogflow.Models;
|
||||
|
|
@ -21,6 +22,7 @@ namespace BotSharp.Platform.Dialogflow
|
|||
services.AddSingleton<DialogflowAi<AgentModel>>();
|
||||
AgentStorageServiceRegister.Register<AgentModel>(services);
|
||||
PlatformConfigServiceRegister.Register<PlatformSettings>("dialogflowAi", services, config);
|
||||
ContextStorageServiceRegister.Register<AIContext>(services);
|
||||
}
|
||||
|
||||
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.
|
||||
"dialogflowAi": {
|
||||
"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_",
|
||||
"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",
|
||||
"File": "|DataDirectory|AgentStorage"
|
||||
"File": "|DataDirectory|"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue