2018-07-15 12:31:52 +00:00
|
|
|
|
using BotSharp.Core.Agents;
|
2018-04-02 22:42:11 +00:00
|
|
|
|
using BotSharp.Core.Entities;
|
2018-03-28 22:08:49 +00:00
|
|
|
|
using BotSharp.Core.Intents;
|
|
|
|
|
|
using BotSharp.Core.Models;
|
2017-12-30 20:26:35 +00:00
|
|
|
|
using EntityFrameworkCore.BootKit;
|
2017-12-18 13:31:15 +00:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2018-08-08 21:39:00 +00:00
|
|
|
|
using Newtonsoft.Json;
|
2017-12-18 13:31:15 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2018-07-15 12:31:52 +00:00
|
|
|
|
using System.IO;
|
2017-12-18 13:31:15 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
2018-08-08 21:39:00 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2017-12-18 13:31:15 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
namespace BotSharp.Core.Engines
|
2017-12-18 13:31:15 +00:00
|
|
|
|
{
|
2018-07-15 12:31:52 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Bot engine/ platform base class
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public abstract class BotEngineBase
|
2017-12-18 13:31:15 +00:00
|
|
|
|
{
|
2018-07-15 12:31:52 +00:00
|
|
|
|
protected Database dc;
|
|
|
|
|
|
|
|
|
|
|
|
public AIConfiguration AiConfig { get; set; }
|
2018-05-23 05:11:15 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
protected Agent agent { get; set; }
|
2018-05-23 05:11:15 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
public String DbInitializerPath { get; private set; }
|
2018-05-23 05:11:15 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
public BotEngineBase()
|
|
|
|
|
|
{
|
|
|
|
|
|
dc = new DefaultDataContextLoader().GetDefaultDc();
|
2018-08-02 21:14:46 +00:00
|
|
|
|
string dataPath = AppDomain.CurrentDomain.GetData("DataPath").ToString();
|
|
|
|
|
|
DbInitializerPath = Path.Join(dataPath, $"DbInitializer");
|
2018-05-23 05:11:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-08-08 21:39:00 +00:00
|
|
|
|
public AIResponse TextRequest(AIRequest request)
|
|
|
|
|
|
{
|
|
|
|
|
|
var preditor = new BotPreditor();
|
|
|
|
|
|
var text = preditor.Predict(agent, request);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
public Agent LoadAgent(string id)
|
2018-05-22 00:39:33 +00:00
|
|
|
|
{
|
2018-07-15 12:31:52 +00:00
|
|
|
|
if (agent == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
agent = dc.Table<Agent>()
|
|
|
|
|
|
.Include(x => x.Intents).ThenInclude(x => x.Contexts)
|
|
|
|
|
|
.Include(x => x.Entities).ThenInclude(x => x.Entries).ThenInclude(x => x.Synonyms)
|
|
|
|
|
|
.Include(x => x.MlConfig)
|
|
|
|
|
|
.FirstOrDefault(x => x.Id == id ||
|
|
|
|
|
|
x.ClientAccessToken == id ||
|
|
|
|
|
|
x.DeveloperAccessToken == id);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return agent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return agent;
|
2018-05-22 00:39:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-01-02 18:05:35 +00:00
|
|
|
|
/// <summary>
|
2018-05-22 00:39:33 +00:00
|
|
|
|
/// Restore a agent instance from backup json files
|
2018-01-02 18:05:35 +00:00
|
|
|
|
/// </summary>
|
2018-07-15 12:31:52 +00:00
|
|
|
|
/// <param name="importer"></param>
|
|
|
|
|
|
/// <param name="agentHeader"></param>
|
|
|
|
|
|
/// <param name="dataDir"></param>
|
2018-01-02 18:05:35 +00:00
|
|
|
|
/// <returns></returns>
|
2018-07-15 12:31:52 +00:00
|
|
|
|
public bool RestoreAgent<TAgentImporter>(AgentImportHeader agentHeader) where TAgentImporter : IAgentImporter, new()
|
2018-01-02 18:05:35 +00:00
|
|
|
|
{
|
2018-07-15 12:31:52 +00:00
|
|
|
|
var importer = new TAgentImporter();
|
2018-05-22 00:39:33 +00:00
|
|
|
|
|
2018-08-02 21:14:46 +00:00
|
|
|
|
string dataDir = Path.Join(DbInitializerPath, "Agents");
|
2018-05-22 00:39:33 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
int row = dc.DbTran(() => {
|
2018-05-22 00:39:33 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
// Load agent summary
|
|
|
|
|
|
agent = importer.LoadAgent(agentHeader, dataDir);
|
2018-06-22 19:42:53 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
// Load user custom entities
|
|
|
|
|
|
importer.LoadCustomEntities(agent, dataDir);
|
|
|
|
|
|
|
|
|
|
|
|
// Load agent intents
|
|
|
|
|
|
importer.LoadIntents(agent, dataDir);
|
|
|
|
|
|
|
|
|
|
|
|
// Load system buildin entities
|
|
|
|
|
|
importer.LoadBuildinEntities(agent, dataDir);
|
|
|
|
|
|
|
|
|
|
|
|
SaveAgent();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return row > 0;
|
2018-01-02 18:05:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
public String SaveAgent()
|
2017-12-30 20:26:35 +00:00
|
|
|
|
{
|
2018-05-22 00:39:33 +00:00
|
|
|
|
var existedAgent = dc.Table<Agent>().FirstOrDefault(x => x.Id == agent.Id || x.Name == agent.Name);
|
|
|
|
|
|
if (existedAgent == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
dc.Table<Agent>().Add(agent);
|
|
|
|
|
|
return agent.Id;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
agent.Id = existedAgent.Id;
|
|
|
|
|
|
return existedAgent.Id;
|
|
|
|
|
|
}
|
2017-12-30 20:26:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
public TrainingCorpus GetIntentExpressions()
|
2018-04-06 22:39:30 +00:00
|
|
|
|
{
|
2018-07-15 12:31:52 +00:00
|
|
|
|
TrainingCorpus corpus = new TrainingCorpus()
|
2018-04-06 22:39:30 +00:00
|
|
|
|
{
|
2018-07-15 12:31:52 +00:00
|
|
|
|
UserSays = new List<TrainingIntentExpression<TrainingIntentExpressionPart>>(),
|
|
|
|
|
|
Entities = new List<TrainingEntity>()
|
2018-04-06 22:39:30 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var expressParts = new List<IntentExpressionPart>();
|
|
|
|
|
|
|
|
|
|
|
|
var intents = dc.Table<Intent>()
|
|
|
|
|
|
.Include(x => x.Contexts)
|
|
|
|
|
|
.Include(x => x.UserSays).ThenInclude(say => say.Data)
|
2018-06-06 16:20:02 +00:00
|
|
|
|
.Where(x => x.AgentId == agent.Id && x.UserSays.Count > 0)
|
2018-04-06 22:39:30 +00:00
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
intents.ForEach(intent =>
|
|
|
|
|
|
{
|
|
|
|
|
|
intent.UserSays.ForEach(exp =>
|
|
|
|
|
|
{
|
2018-08-06 18:39:26 +00:00
|
|
|
|
exp.Data = exp.Data.OrderBy(x => x.UpdatedTime).ToList();
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
var say = new TrainingIntentExpression<TrainingIntentExpressionPart>
|
2018-04-06 22:39:30 +00:00
|
|
|
|
{
|
|
|
|
|
|
Intent = intent.Name,
|
2018-08-06 18:39:26 +00:00
|
|
|
|
Text = String.Join("", exp.Data.Select(x => x.Text)),
|
2018-06-18 22:15:32 +00:00
|
|
|
|
ContextHash = intent.ContextHash
|
2018-04-06 22:39:30 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// convert entity format
|
|
|
|
|
|
exp.Data.Where(x => !String.IsNullOrEmpty(x.Meta))
|
|
|
|
|
|
.ToList()
|
|
|
|
|
|
.ForEach(x =>
|
|
|
|
|
|
{
|
|
|
|
|
|
int start = say.Text.IndexOf(x.Text);
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
var part = new TrainingIntentExpressionPart
|
2018-04-06 22:39:30 +00:00
|
|
|
|
{
|
|
|
|
|
|
Value = x.Text,
|
2018-06-22 19:42:53 +00:00
|
|
|
|
Entity = $"{x.Meta}:{x.Alias}",
|
2018-04-06 22:39:30 +00:00
|
|
|
|
Start = start,
|
|
|
|
|
|
End = start + x.Text.Length
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
if (say.Entities == null) say.Entities = new List<TrainingIntentExpressionPart>();
|
2018-04-06 22:39:30 +00:00
|
|
|
|
say.Entities.Add(part);
|
|
|
|
|
|
|
|
|
|
|
|
// assemble entity synonmus
|
2018-07-15 12:31:52 +00:00
|
|
|
|
/*if (!trainingData.Entities.Any(y => y.EntityType == x.Alias && y.EntityValue == x.Text))
|
2018-04-06 22:39:30 +00:00
|
|
|
|
{
|
2018-05-22 00:39:33 +00:00
|
|
|
|
var allSynonyms = (from e in dc.Table<EntityType>()
|
2018-04-06 22:39:30 +00:00
|
|
|
|
join ee in dc.Table<EntityEntry>() on e.Id equals ee.EntityId
|
2018-05-22 00:39:33 +00:00
|
|
|
|
join ees in dc.Table<EntrySynonym>() on ee.Id equals ees.EntityEntryId
|
2018-04-06 22:39:30 +00:00
|
|
|
|
where e.Name == x.Alias && ee.Value == x.Text & ees.Synonym != x.Text
|
|
|
|
|
|
select ees.Synonym).ToList();
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
var te = new TrainingEntity
|
2018-04-06 22:39:30 +00:00
|
|
|
|
{
|
2018-06-22 19:42:53 +00:00
|
|
|
|
EntityType = $"{x.Meta}:{x.Alias}",
|
2018-04-06 22:39:30 +00:00
|
|
|
|
EntityValue = x.Text,
|
|
|
|
|
|
Synonyms = allSynonyms
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
trainingData.Entities.Add(te);
|
2018-07-15 12:31:52 +00:00
|
|
|
|
}*/
|
2018-04-06 22:39:30 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
corpus.UserSays.Add(say);
|
2018-04-06 22:39:30 +00:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2018-06-18 22:15:32 +00:00
|
|
|
|
// remove Default Fallback Intent
|
2018-07-15 12:31:52 +00:00
|
|
|
|
corpus.UserSays = corpus.UserSays.Where(x => x.Intent != "Default Fallback Intent").ToList();
|
2018-06-18 22:15:32 +00:00
|
|
|
|
|
2018-07-15 12:31:52 +00:00
|
|
|
|
return corpus;
|
2017-12-18 13:31:15 +00:00
|
|
|
|
}
|
2018-07-18 16:18:34 +00:00
|
|
|
|
|
2018-08-08 21:39:00 +00:00
|
|
|
|
public virtual Task Train()
|
2018-07-18 16:18:34 +00:00
|
|
|
|
{
|
2018-08-08 21:39:00 +00:00
|
|
|
|
return Task.CompletedTask;
|
2018-07-18 16:18:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-18 13:31:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|