Add quick question and answer function.

This commit is contained in:
botsharp2018 2018-08-30 08:04:10 -05:00
parent 66b62fcd16
commit 47623056f7
8 changed files with 121 additions and 10 deletions

1
.gitignore vendored
View file

@ -302,3 +302,4 @@ __pycache__/
/Data
/docs/build
/docs/_build
/BotSharp.WebHost/App_Data/AgentArchive/Smart Niraj.zip

View file

@ -1,8 +1,11 @@
using BotSharp.Core.Agents;
using BotSharp.Core.Engines.QuickQA;
using BotSharp.Core.Engines.Rasa;
using BotSharp.Core.Entities;
using BotSharp.Core.Intents;
using BotSharp.Core.Models;
using BotSharp.Models.NLP;
using DotNetToolkit;
using EntityFrameworkCore.BootKit;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
@ -36,6 +39,10 @@ namespace BotSharp.Core.Engines
var preditor = new BotPredictor();
var doc = preditor.Predict(agent, request).Result;
var parameters = new Dictionary<String, Object>();
if(doc.Sentences[0].Entities == null)
{
doc.Sentences[0].Entities = new List<NlpEntity>();
}
doc.Sentences[0].Entities.ForEach(x => parameters.Add(x.Entity, x.Value));
return new AIResponse
@ -48,7 +55,10 @@ namespace BotSharp.Core.Engines
{
Score = doc.Sentences[0].Intent == null ? 0 : doc.Sentences[0].Intent.Confidence,
ResolvedQuery = doc.Sentences[0].Text,
Fulfillment = new AIResponseFulfillment { },
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
@ -111,6 +121,9 @@ namespace BotSharp.Core.Engines
case "Sebis":
importer = new AgentImporterInSebis();
break;
case "QuickQA":
importer = new AgentImporterInQuickQA();
break;
default:
break;
}

View file

@ -94,21 +94,21 @@ namespace BotSharp.Core.Engines
.Select(x => x.Trim())
.ToList();
pipelines.ForEach(async pipeName =>
for (int pipeIdx = 0; pipeIdx < pipelines.Count; pipeIdx++)
{
var pipe = TypeHelper.GetInstance(pipeName, assemblies) as INlpTrain;
var pipe = TypeHelper.GetInstance(pipelines[pipeIdx], assemblies) as INlpTrain;
pipe.Configuration = provider.Configuration;
pipe.Settings = settings;
pipeModel = new PipeModel
{
Name = pipeName,
Name = pipelines[pipeIdx],
Class = pipe.ToString(),
Time = DateTime.UtcNow
};
meta.Pipeline.Add(pipeModel);
await pipe.Train(agent, data, pipeModel);
});
}
// save model meta data
var metaJson = JsonConvert.SerializeObject(meta, new JsonSerializerSettings

View file

@ -25,7 +25,7 @@ namespace BotSharp.Core.Engines.Classifiers
string predictFileName = Path.Combine(Settings.TempDir, "fasttext.txt");
File.WriteAllText(predictFileName, doc.Sentences[0].Text);
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "fasttext"), $"predict-prob {modelFileName}.bin {predictFileName}");
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "fasttext"), $"predict-prob \"{modelFileName}.bin\" \"{predictFileName}\"");
File.Delete(predictFileName);
@ -52,7 +52,7 @@ namespace BotSharp.Core.Engines.Classifiers
File.WriteAllText(parsedTrainingDataFileName, corpus.ToString());
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "fasttext"), $"supervised -input {parsedTrainingDataFileName} -output {modelFileName}", false);
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "fasttext"), $"supervised -input \"{parsedTrainingDataFileName}\" -output \"{modelFileName}\"", false);
Console.WriteLine($"Saved model to {modelFileName}");
meta.Meta = new JObject();

View file

@ -79,7 +79,7 @@ namespace BotSharp.Core.Engines.NERs
var algorithmDir = Path.Combine(AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(), "Algorithms");
CmdHelper.Run(Path.Combine(algorithmDir, "crfsuite"), $"learn -m {modelFileName} {parsedTrainingDataFileName}", false); // --split=3 -x
CmdHelper.Run(Path.Combine(algorithmDir, "crfsuite"), $"learn -m \"{modelFileName}\" \"{parsedTrainingDataFileName}\"", false); // --split=3 -x
Console.WriteLine($"Saved model to {modelFileName}");
meta.Meta = new JObject();
meta.Meta["fields"] = fields;
@ -197,7 +197,7 @@ namespace BotSharp.Core.Engines.NERs
new NLP.Models.CRFsuite.Ner()
.NerStart(rawPredictingDataFileName, parsedPredictingDataFileName, field, uniFeatures.Split(' '), biFeatures.Split(' '));
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "crfsuite"), $"tag -i -m {modelFileName} {parsedPredictingDataFileName}", false);
var output = CmdHelper.Run(Path.Combine(Settings.AlgorithmDir, "crfsuite"), $"tag -i -m \"{modelFileName}\" \"{parsedPredictingDataFileName}\"", false);
var entities = new List<NlpEntity>();

View file

@ -0,0 +1,94 @@
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 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<Match>().ToArray();
var answers = Regex.Matches(lines, @"^A - ", RegexOptions.Multiline).Cast<Match>().ToArray();
int qNumber = 1;
agent.Intents = questions.Select(x => new Intent
{
Name = $"Q{qNumber++}",
UserSays = new List<IntentExpression>
{
new IntentExpression
{
Data = new List<IntentExpressionPart>
{
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<IntentResponse>
{
new IntentResponse
{
Messages = new List<IntentResponseMessage>
{
new IntentResponseMessage
{
Speech = lines.Substring(start, length).Trim()
}
}
}
};
}
}
public void AssembleTrainData(Agent agent)
{
}
}
}

View file

@ -9,6 +9,8 @@ namespace BotSharp.Core.Models
{
public RasaResponseIntent Intent { get; set; }
public AIResponseFulfillment Fullfillment { get; set; }
[JsonProperty("intent_ranking")]
public List<RasaResponseIntent> IntentRanking { get; set; }

View file

@ -95,7 +95,8 @@ namespace BotSharp.RestApi.Rasa
Name = aIResponse.Result.Metadata.IntentName,
Confidence = aIResponse.Result.Score
}
}
},
Fullfillment = aIResponse.Result.Fulfillment
};
return rasaResponse;