Added RASA platform emulator.
This commit is contained in:
parent
bb764cd80c
commit
a639e1210e
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj" />
|
||||
<ProjectReference Include="..\BotSharp.Platform.Rasa\BotSharp.Platform.Rasa.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj" />
|
||||
<ProjectReference Include="..\BotSharp.Platform.Rasa\BotSharp.Platform.Rasa.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
190
BotSharp.Platform.Rasa/AgentImporterInRasa.cs
Normal file
190
BotSharp.Platform.Rasa/AgentImporterInRasa.cs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BotSharp.Platform.Abstraction;
|
||||
using BotSharp.Platform.Models;
|
||||
using BotSharp.Platform.Models.Intents;
|
||||
using BotSharp.Platform.Rasa.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BotSharp.Platform.Rasa
|
||||
{
|
||||
public class AgentImporterInRasa<TAgent> : IAgentImporter<TAgent> where TAgent : AgentModel, new()
|
||||
{
|
||||
public string AgentDir { get; set; }
|
||||
|
||||
public async Task<TAgent> LoadAgent(AgentImportHeader agentHeader)
|
||||
{
|
||||
var agent = new TAgent
|
||||
{
|
||||
Id = agentHeader.Id,
|
||||
Name = agentHeader.Name
|
||||
};
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
public async Task LoadBuildinEntities(TAgent agent)
|
||||
{
|
||||
agent.Intents.ForEach(intent =>
|
||||
{
|
||||
/*if (intent.UserSays != null)
|
||||
{
|
||||
intent.UserSays.ForEach(us =>
|
||||
{
|
||||
us.Data.Where(data => data.Meta != null)
|
||||
.ToList()
|
||||
.ForEach(data =>
|
||||
{
|
||||
LoadBuildinEntityTypePerUserSay(agent, data);
|
||||
});
|
||||
});
|
||||
}*/
|
||||
});
|
||||
}
|
||||
|
||||
private void LoadBuildinEntityTypePerUserSay(TAgent agent, IntentExpressionPart data)
|
||||
{
|
||||
/*var existedEntityType = agent.Entities.FirstOrDefault(x => x.Name == data.Meta);
|
||||
|
||||
if (existedEntityType == null)
|
||||
{
|
||||
existedEntityType = new EntityType
|
||||
{
|
||||
Name = data.Meta,
|
||||
Entries = new List<EntityEntry>(),
|
||||
IsOverridable = true
|
||||
};
|
||||
|
||||
agent.Entities.Add(existedEntityType);
|
||||
}
|
||||
|
||||
var entries = existedEntityType.Entries.Select(x => x.Value.ToLower()).ToList();
|
||||
if (!entries.Contains(data.Text.ToLower()))
|
||||
{
|
||||
existedEntityType.Entries.Add(new EntityEntry
|
||||
{
|
||||
Value = data.Text,
|
||||
Synonyms = new List<EntrySynonym>
|
||||
{
|
||||
new EntrySynonym
|
||||
{
|
||||
Synonym = data.Text
|
||||
}
|
||||
}
|
||||
});
|
||||
}*/
|
||||
}
|
||||
|
||||
public async Task LoadCustomEntities(TAgent agent)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task LoadIntents(TAgent agent)
|
||||
{
|
||||
string data = File.ReadAllText(Path.Combine(AgentDir, "corpus.json"));
|
||||
var rasa = JsonConvert.DeserializeObject<RasaAgentImportModel>(data);
|
||||
|
||||
agent.Intents = rasa.Data.Intents;
|
||||
agent.Entities = rasa.Data.Entities;
|
||||
}
|
||||
|
||||
private void ImportIntentUserSays(RasaIntentExpression intent, List<RasaIntentExpression> sentences)
|
||||
{
|
||||
var intents = new List<RasaIntentExpression>();
|
||||
|
||||
var userSays = sentences.Where(x => x.Intent == intent.Intent).ToList();
|
||||
|
||||
userSays.ForEach(say =>
|
||||
{
|
||||
var expression = new IntentExpression();
|
||||
|
||||
say.Entities = say.Entities.OrderBy(x => x.Start).ToList();
|
||||
|
||||
expression.Data = new List<IntentExpressionPart>();
|
||||
|
||||
int pos = 0;
|
||||
for (int entityIdx = 0; entityIdx < say.Entities.Count; entityIdx++)
|
||||
{
|
||||
var entity = say.Entities[entityIdx];
|
||||
|
||||
// previous
|
||||
if (entity.Start > 0)
|
||||
{
|
||||
expression.Data.Add(new IntentExpressionPart
|
||||
{
|
||||
Text = say.Text.Substring(pos, entity.Start - pos),
|
||||
Start = pos
|
||||
});
|
||||
}
|
||||
|
||||
// self
|
||||
expression.Data.Add(new IntentExpressionPart
|
||||
{
|
||||
Alias = entity.Entity,
|
||||
Meta = entity.Entity,
|
||||
Text = say.Text.Substring(entity.Start, entity.Value.Length),
|
||||
Start = entity.Start
|
||||
});
|
||||
|
||||
pos = entity.End + 1;
|
||||
|
||||
if (pos < say.Text.Length && entityIdx == say.Entities.Count - 1)
|
||||
{
|
||||
// end
|
||||
expression.Data.Add(new IntentExpressionPart
|
||||
{
|
||||
Text = say.Text.Substring(pos),
|
||||
Start = pos
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (say.Entities.Count == 0)
|
||||
{
|
||||
expression.Data.Add(new IntentExpressionPart
|
||||
{
|
||||
Text = say.Text.Substring(pos)
|
||||
});
|
||||
}
|
||||
|
||||
int second = 0;
|
||||
expression.Data.ForEach(x => x.UpdatedTime = DateTime.UtcNow.AddSeconds(second++));
|
||||
|
||||
intents.Add(say);
|
||||
});
|
||||
}
|
||||
|
||||
/*public void AssembleTrainData(TAgent agent)
|
||||
{
|
||||
// convert agent to training corpus
|
||||
agent.Corpus = new TrainingCorpus
|
||||
{
|
||||
Entities = new List<TrainingEntity>(),
|
||||
UserSays = new List<TrainingIntentExpression<TrainingIntentExpressionPart>>()
|
||||
};
|
||||
|
||||
agent.Intents.ForEach(intent =>
|
||||
{
|
||||
intent.UserSays.ForEach(say => {
|
||||
agent.Corpus.UserSays.Add(new TrainingIntentExpression<TrainingIntentExpressionPart>
|
||||
{
|
||||
Intent = intent.Name,
|
||||
Text = String.Join("", say.Data.Select(x => x.Text)),
|
||||
Entities = say.Data.Where(x => !String.IsNullOrEmpty(x.Meta))
|
||||
.Select(x => new TrainingIntentExpressionPart
|
||||
{
|
||||
Value = x.Text,
|
||||
Entity = x.Meta,
|
||||
Start = x.Start
|
||||
})
|
||||
.ToList()
|
||||
});
|
||||
});
|
||||
});
|
||||
}*/
|
||||
}
|
||||
}
|
||||
15
BotSharp.Platform.Rasa/BotSharp.Platform.Rasa.csproj
Normal file
15
BotSharp.Platform.Rasa/BotSharp.Platform.Rasa.csproj
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BotSharp\BotSharp.Core\BotSharp.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
29
BotSharp.Platform.Rasa/Controllers/ConfigController.cs
Normal file
29
BotSharp.Platform.Rasa/Controllers/ConfigController.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using BotSharp.Platform.Rasa.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Controllers
|
||||
{
|
||||
[Route("[controller]")]
|
||||
public class ConfigController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public ActionResult<RasaVersionModel> Get()
|
||||
{
|
||||
var status = new RasaStatusModel
|
||||
{
|
||||
AvailableProjects = JObject.FromObject(new RasaProjectModel
|
||||
{
|
||||
Status = "ready",
|
||||
AvailableModels = new List<string> { "model_XXXXXX" },
|
||||
LoadedModels = new List<string> { "model_XXXXXX" }
|
||||
})
|
||||
};
|
||||
|
||||
return Ok(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
98
BotSharp.Platform.Rasa/Controllers/ParseController.cs
Normal file
98
BotSharp.Platform.Rasa/Controllers/ParseController.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
using BotSharp.Platform.Rasa.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// send a text request
|
||||
/// </summary>
|
||||
[Route("[controller]")]
|
||||
public class ParseController : ControllerBase
|
||||
{
|
||||
private readonly RasaAi<AgentModel> builder;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize dialog controller and get a platform instance
|
||||
/// </summary>
|
||||
/// <param name="platform"></param>
|
||||
public ParseController(RasaAi<AgentModel> configuration)
|
||||
{
|
||||
builder = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// parse request
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, HttpGet]
|
||||
public ActionResult<RasaResponse> Parse(RasaRequestModel request)
|
||||
{
|
||||
/*var config = new AIConfiguration("", SupportedLanguage.English);
|
||||
config.SessionId = "rasa nlu";
|
||||
|
||||
string body = "";
|
||||
using (var reader = new StreamReader(Request.Body))
|
||||
{
|
||||
body = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
Console.WriteLine($"Got message from {Request.Host}: {body}", Color.Green);
|
||||
if(request.Project ==null && !String.IsNullOrEmpty(body))
|
||||
{
|
||||
request = JsonConvert.DeserializeObject<RasaRequestModel>(body);
|
||||
}
|
||||
|
||||
// Load agent
|
||||
var projectPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", request.Project);
|
||||
|
||||
if (String.IsNullOrEmpty(request.Model))
|
||||
{
|
||||
request.Model = Directory.GetDirectories(projectPath).Where(x => x.Contains("model_")).Last().Split(Path.DirectorySeparatorChar).Last();
|
||||
}
|
||||
|
||||
var modelPath = Path.Combine(projectPath, request.Model);
|
||||
|
||||
var agent = _platform.LoadAgentFromFile(modelPath);
|
||||
|
||||
var aIResponse = _platform.TextRequest(new AIRequest
|
||||
{
|
||||
AgentDir = projectPath,
|
||||
Model = request.Model,
|
||||
Query = new String[] { request.Text }
|
||||
});
|
||||
|
||||
var rasaResponse = new RasaResponse
|
||||
{
|
||||
Intent = new RasaResponseIntent
|
||||
{
|
||||
Name = aIResponse.Result.Metadata.IntentName,
|
||||
Confidence = aIResponse.Result.Score
|
||||
},
|
||||
Entities = aIResponse.Result.Entities.Select(x => new RasaResponseEntity
|
||||
{
|
||||
Extractor = x.Extrator,
|
||||
Start = x.Start,
|
||||
Entity = x.Entity,
|
||||
Value = x.Value
|
||||
}).ToList(),
|
||||
Text = request.Text,
|
||||
Model = request.Model,
|
||||
Project = agent.Name,
|
||||
IntentRanking = new List<RasaResponseIntent>
|
||||
{
|
||||
new RasaResponseIntent
|
||||
{
|
||||
Name = aIResponse.Result.Metadata.IntentName,
|
||||
Confidence = aIResponse.Result.Score
|
||||
}
|
||||
},
|
||||
Fullfillment = aIResponse.Result.Fulfillment
|
||||
};
|
||||
|
||||
return rasaResponse;*/
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
BotSharp.Platform.Rasa/Controllers/StatusController.cs
Normal file
65
BotSharp.Platform.Rasa/Controllers/StatusController.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
using BotSharp.Core.Engines;
|
||||
using BotSharp.Platform.Rasa.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// This returns all the currently available projects.
|
||||
/// </summary>
|
||||
[Route("[controller]")]
|
||||
public class StatusController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of available projects the server can use to fulfill /parse requests.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public ActionResult<RasaVersionModel> Get()
|
||||
{
|
||||
var status = new RasaStatusModel();
|
||||
status.AvailableProjects = JObject.FromObject(new { });
|
||||
status.MaxTrainingProcesses = 1;
|
||||
|
||||
// scan dir, get all models
|
||||
var projectPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects");
|
||||
|
||||
if (!Directory.Exists(projectPath))
|
||||
{
|
||||
Directory.CreateDirectory(projectPath);
|
||||
}
|
||||
|
||||
var projectDirs = Directory.GetDirectories(projectPath);
|
||||
for(int idx = 0; idx < projectDirs.Length; idx++)
|
||||
{
|
||||
string project = projectDirs[idx].Split('\\').Last();
|
||||
var modelDirs = Directory.GetDirectories(projectDirs[idx]);
|
||||
|
||||
List<string> availableModels = new List<string>();
|
||||
|
||||
for (int mIdx = 0; mIdx < modelDirs.Length; mIdx++)
|
||||
{
|
||||
string model = modelDirs[mIdx].Split('\\').Last();
|
||||
if (model.StartsWith(project + "_"))
|
||||
{
|
||||
availableModels.Add(model);
|
||||
}
|
||||
}
|
||||
|
||||
status.AvailableProjects.Add(project, JObject.FromObject(new RasaProjectModel
|
||||
{
|
||||
Status = "ready",
|
||||
AvailableModels = availableModels
|
||||
}));
|
||||
}
|
||||
|
||||
return Ok(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
184
BotSharp.Platform.Rasa/Controllers/TrainController.cs
Normal file
184
BotSharp.Platform.Rasa/Controllers/TrainController.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
using BotSharp.Core.Engines;
|
||||
using BotSharp.Platform.Abstraction;
|
||||
using BotSharp.Platform.Models;
|
||||
using BotSharp.Platform.Models.MachineLearning;
|
||||
using BotSharp.Platform.Rasa.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// You can post your training data to this endpoint to train a new model for a project.
|
||||
/// This request will wait for the server answer: either the model was trained successfully or the training exited with an error.
|
||||
/// </summary>
|
||||
[Route("[controller]")]
|
||||
public class TrainController : ControllerBase
|
||||
{
|
||||
private RasaAi<AgentModel> builder;
|
||||
private readonly IPlatformSettings settings;
|
||||
|
||||
public TrainController(RasaAi<AgentModel> configuration, IPlatformSettings settings)
|
||||
{
|
||||
builder = configuration;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using the HTTP server, you must specify the project you want to train a new model for to be able to use it during parse requests later on : /train?project=my_project.
|
||||
/// </summary>
|
||||
/// <param name="model">Model name</param>
|
||||
/// <param name="project">Agent name or agent id</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<ModelMetaData>> Train([FromQuery] string project, [FromQuery] string model)
|
||||
{
|
||||
string agentDir = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", project);
|
||||
if (!Directory.Exists(agentDir))
|
||||
{
|
||||
Directory.CreateDirectory(agentDir);
|
||||
}
|
||||
|
||||
string body = "";
|
||||
using (var reader = new StreamReader(Request.Body))
|
||||
{
|
||||
body = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
var agent = await ImportAgent(project, body);
|
||||
|
||||
var corpus = await builder.ExtractorCorpus(agent);
|
||||
|
||||
var meta = await builder.Train(agent, corpus, new BotTrainOptions { Model = model });
|
||||
|
||||
return meta;
|
||||
|
||||
}
|
||||
|
||||
private async Task<AgentModel> ImportAgent(string project, string body)
|
||||
{
|
||||
Console.WriteLine($"Update agent from http post, data length: {body.Length}");
|
||||
|
||||
// save to file
|
||||
// save corpus to agent dir
|
||||
var projectPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", project);
|
||||
var rawPath = Path.Combine(projectPath, "tmp");
|
||||
|
||||
// clear tmp dir
|
||||
if (Directory.Exists(rawPath))
|
||||
{
|
||||
Directory.Delete(rawPath, true);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(rawPath);
|
||||
|
||||
// Save raw data to file, then parse it to Agent instance.
|
||||
var metaFileName = Path.Combine(rawPath, "meta.json");
|
||||
System.IO.File.WriteAllText(metaFileName, JsonConvert.SerializeObject(new AgentImportHeader
|
||||
{
|
||||
Name = project,
|
||||
Platform = PlatformType.Rasa,
|
||||
Id = Guid.NewGuid().ToString()
|
||||
}, new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
}));
|
||||
|
||||
// in order to unify the process.
|
||||
var fileName = Path.Combine(rawPath, "corpus.json");
|
||||
|
||||
System.IO.File.WriteAllText(fileName, body);
|
||||
|
||||
/*string lang = Regex.Match(body, @"language:.+")?.Value;
|
||||
if (!String.IsNullOrEmpty(lang))
|
||||
{
|
||||
lang = lang.Substring(11, 2);
|
||||
}
|
||||
string data = Regex.Match(body, @"data:([\s\S]*)")?.Value;
|
||||
if (String.IsNullOrEmpty(data))
|
||||
{
|
||||
data = body;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = data.Substring(6);
|
||||
}*/
|
||||
|
||||
/*var agent = builder.GetAgentById(project);
|
||||
|
||||
if (agent == null)
|
||||
{
|
||||
agent = builder.GetAgentByName(project);
|
||||
}
|
||||
|
||||
var corpus = builder.ExtractorCorpus(agent);
|
||||
|
||||
var meta = await builder.Train(agent, corpus);*/
|
||||
|
||||
// var rasa_nlu_data = JsonConvert.DeserializeObject<RasaTrainRequestModel>(data);
|
||||
//rasa_nlu_data.Model = model;
|
||||
//rasa_nlu_data.Project = project;
|
||||
|
||||
var agent = await builder.LoadAgentFromFile<AgentImporterInRasa<AgentModel>>(rawPath);
|
||||
await builder.SaveAgent(agent);
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
private async Task<ActionResult<String>> Train([FromBody] RasaTrainRequestViewModel request, [FromQuery] string project)
|
||||
{
|
||||
var trainer = new BotTrainer(settings);
|
||||
if (String.IsNullOrEmpty(request.Project))
|
||||
{
|
||||
request.Project = project;
|
||||
}
|
||||
|
||||
// save corpus to agent dir
|
||||
var projectPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Projects", project);
|
||||
var modelPath = Path.Combine(projectPath, request.Model);
|
||||
|
||||
if (!Directory.Exists(modelPath))
|
||||
{
|
||||
Directory.CreateDirectory(modelPath);
|
||||
}
|
||||
|
||||
// Save raw data to file, then parse it to Agent instance.
|
||||
var metaFileName = Path.Combine(modelPath, "meta.json");
|
||||
System.IO.File.WriteAllText(metaFileName, JsonConvert.SerializeObject(new AgentImportHeader
|
||||
{
|
||||
Name = project
|
||||
}));
|
||||
// in order to unify the process.
|
||||
var fileName = Path.Combine(modelPath, "corpus.json");
|
||||
|
||||
System.IO.File.WriteAllText(fileName, JsonConvert.SerializeObject(request, new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
}));
|
||||
|
||||
var agent = await builder.GetAgentByName(project);
|
||||
|
||||
var info = await trainer.Train(agent, new BotTrainOptions
|
||||
{
|
||||
AgentDir = projectPath,
|
||||
Model = request.Model
|
||||
});
|
||||
|
||||
return Ok(new { info = info.Model });
|
||||
}
|
||||
}
|
||||
}
|
||||
23
BotSharp.Platform.Rasa/Controllers/VersionController.cs
Normal file
23
BotSharp.Platform.Rasa/Controllers/VersionController.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Controllers
|
||||
{
|
||||
#if RASA
|
||||
[Route("[controller]")]
|
||||
public class VersionController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public ActionResult<RasaVersionModel> Get()
|
||||
{
|
||||
return Ok(new RasaVersionModel
|
||||
{
|
||||
Version = "0.13.0",
|
||||
MinimumCompatibleVersion = "0.13.0"
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
20
BotSharp.Platform.Rasa/Models/AgentModel.cs
Normal file
20
BotSharp.Platform.Rasa/Models/AgentModel.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using BotSharp.Platform.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class AgentModel : AgentBase
|
||||
{
|
||||
[JsonProperty("common_examples")]
|
||||
public List<RasaIntentExpression> Intents { get; set; }
|
||||
|
||||
[JsonProperty("entity_synonyms")]
|
||||
public List<RasaTrainingEntity> Entities { get; set; }
|
||||
|
||||
[JsonProperty("regex_features")]
|
||||
public List<RasaTrainingRegex> Regex { get; set; }
|
||||
}
|
||||
}
|
||||
13
BotSharp.Platform.Rasa/Models/RasaAgentImportModel.cs
Normal file
13
BotSharp.Platform.Rasa/Models/RasaAgentImportModel.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaAgentImportModel
|
||||
{
|
||||
[JsonProperty("rasa_nlu_data")]
|
||||
public AgentModel Data { get; set; }
|
||||
}
|
||||
}
|
||||
13
BotSharp.Platform.Rasa/Models/RasaConfigModel.cs
Normal file
13
BotSharp.Platform.Rasa/Models/RasaConfigModel.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaConfigModel
|
||||
{
|
||||
public string Config { get; set; }
|
||||
|
||||
public string Data { get; set; }
|
||||
}
|
||||
}
|
||||
13
BotSharp.Platform.Rasa/Models/RasaIntentExpression.cs
Normal file
13
BotSharp.Platform.Rasa/Models/RasaIntentExpression.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using BotSharp.Platform.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaIntentExpression : TrainingIntentExpression<TrainingIntentExpressionPart>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
12
BotSharp.Platform.Rasa/Models/RasaIntentExpressionPart.cs
Normal file
12
BotSharp.Platform.Rasa/Models/RasaIntentExpressionPart.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using BotSharp.Core.Engines;
|
||||
using BotSharp.Platform.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaIntentExpressionPart : TrainingIntentExpressionPart
|
||||
{
|
||||
}
|
||||
}
|
||||
15
BotSharp.Platform.Rasa/Models/RasaOptions.cs
Normal file
15
BotSharp.Platform.Rasa/Models/RasaOptions.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaOptions
|
||||
{
|
||||
public string HostUrl { get; set; }
|
||||
public String[] Assembles { get; set; }
|
||||
public string ContentRootPath { get; set; }
|
||||
public String DbName { get; set; }
|
||||
public String DbConnectionString { get; set; }
|
||||
}
|
||||
}
|
||||
272
BotSharp.Platform.Rasa/Models/RasaRequestExtension.cs
Normal file
272
BotSharp.Platform.Rasa/Models/RasaRequestExtension.cs
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
using BotSharp.Core.Conversations;
|
||||
using DotNetToolkit;
|
||||
using EntityFrameworkCore.BootKit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using BotSharp.Platform.Models.AiRequest;
|
||||
using BotSharp.Platform.Models.Intents;
|
||||
using BotSharp.Platform.Models.AiResponse;
|
||||
using BotSharp.Platform.Models;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public static class RasaRequestExtension
|
||||
{
|
||||
public static IntentResponse HandleIntentPerContextIn(AgentModel agent, AiRequest request, RasaResponse response, Database dc)
|
||||
{
|
||||
// Merge input contexts
|
||||
/*var contexts = dc.Table<ConversationContext>()
|
||||
.Where(x => x.ConversationId == request.SessionId && x.Lifespan > 0)
|
||||
.ToList()
|
||||
.Select(x => new AIContext { Name = x.Context.ToLower(), Lifespan = x.Lifespan })
|
||||
.ToList();
|
||||
|
||||
contexts.AddRange(request.Contexts.Select(x => new AIContext { Name = x.Name.ToLower(), Lifespan = x.Lifespan }));
|
||||
contexts = contexts.OrderBy(x => x.Name).ToList();*/
|
||||
|
||||
// search all potential intents which input context included in contexts
|
||||
/*var intents = agent.Intents.Where(it =>
|
||||
{
|
||||
if (contexts.Count == 0)
|
||||
{
|
||||
return it.Contexts.Count() == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it.Contexts.Count() == 0 ||
|
||||
it.Contexts.Count(x => contexts.Select(ctx => ctx.Name).Contains(x.Name.ToLower())) == it.Contexts.Count;
|
||||
}
|
||||
}).OrderByDescending(x => x.Contexts.Count).ToList();*/
|
||||
|
||||
/*if (response.IntentRanking == null)
|
||||
{
|
||||
response.IntentRanking = new List<RasaResponseIntent>
|
||||
{
|
||||
response.Intent
|
||||
};
|
||||
}
|
||||
|
||||
response.IntentRanking = response.IntentRanking.Where(x => x.Confidence > agent.MlConfig.MinConfidence).ToList();
|
||||
response.IntentRanking = response.IntentRanking.Where(x => intents.Select(i => i.Name).Contains(x.Name)).ToList();*/
|
||||
|
||||
// add Default Fallback Intent
|
||||
/*if (response.IntentRanking.Count == 0)
|
||||
{
|
||||
var defaultFallbackIntent = agent.Intents.FirstOrDefault(x => x.Name == "Default Fallback Intent");
|
||||
response.IntentRanking.Add(new RasaResponseIntent
|
||||
{
|
||||
Name = defaultFallbackIntent.Name,
|
||||
Confidence = decimal.Parse("0.8")
|
||||
});
|
||||
}*/
|
||||
|
||||
response.Intent = response.IntentRanking.First();
|
||||
|
||||
var intent = (dc.Table<Intent>().Where(x => x.AgentId == agent.Id && x.Name == response.Intent.Name)
|
||||
.Include(x => x.Responses).ThenInclude(x => x.Contexts)
|
||||
.Include(x => x.Responses).ThenInclude(x => x.Parameters).ThenInclude(x => x.Prompts)
|
||||
.Include(x => x.Responses).ThenInclude(x => x.Messages)).First();
|
||||
|
||||
var intentResponse = ArrayHelper.GetRandom(intent.Responses);
|
||||
intentResponse.IntentName = intent.Name;
|
||||
|
||||
return intentResponse;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="agent"></param>
|
||||
/// <param name="intentResponse"></param>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>Required field is missed</returns>
|
||||
public static void HandleParameter(AgentModel agent, IntentResponse intentResponse, RasaResponse response, AiRequest aiRequest)
|
||||
{
|
||||
if (intentResponse == null) return;
|
||||
|
||||
intentResponse.Parameters.ForEach(p => {
|
||||
string query = aiRequest.Text;
|
||||
var entity = response.Entities.FirstOrDefault(x => x.Entity == p.Name || x.Entity.Split(':').Contains(p.Name));
|
||||
if (entity != null)
|
||||
{
|
||||
p.Value = query.Substring(entity.Start, entity.End - entity.Start);
|
||||
}
|
||||
|
||||
// convert to Standard entity value
|
||||
/*if (!String.IsNullOrEmpty(p.Value) && !p.DataType.StartsWith("sys."))
|
||||
{
|
||||
p.Value = agent.Entities
|
||||
.FirstOrDefault(x => x.Entity == p.DataType)
|
||||
.Entries
|
||||
.FirstOrDefault((entry) =>
|
||||
{
|
||||
return entry.Value.ToLower() == p.Value.ToLower() ||
|
||||
entry.Synonyms.Select(synonym => synonym.Synonym.ToLower()).Contains(p.Value.ToLower());
|
||||
})?.Value;
|
||||
}*/
|
||||
|
||||
// fixed entity per request
|
||||
/*if (aiRequest.Entities != null)
|
||||
{
|
||||
var fixedEntity = request.Entities.FirstOrDefault(x => x.Name == p.Name);
|
||||
if (fixedEntity != null)
|
||||
{
|
||||
if (query.ToLower().Contains(fixedEntity.Entries.First().Value.ToLower()))
|
||||
{
|
||||
p.Value = fixedEntity.Entries.First().Value;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
});
|
||||
}
|
||||
|
||||
public static void HandleMessage(IntentResponse intentResponse)
|
||||
{
|
||||
if (intentResponse == null) return;
|
||||
|
||||
var missingRequiredParameter = intentResponse.Parameters.FirstOrDefault(x => x.Required && String.IsNullOrEmpty(x.Value));
|
||||
if (missingRequiredParameter != null)
|
||||
{
|
||||
intentResponse.Messages = new List<IntentResponseMessage> {
|
||||
new IntentResponseMessage {
|
||||
Type = AIResponseMessageType.Text,
|
||||
Speech = ArrayHelper.GetRandom(missingRequiredParameter.Prompts).Prompt,
|
||||
IntentResponseId = intentResponse.Id,
|
||||
UpdatedTime = DateTime.UtcNow
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
intentResponse.Messages = intentResponse.Messages.OrderBy(x => x.UpdatedTime).ToList();
|
||||
}
|
||||
|
||||
intentResponse.Messages.ToList()
|
||||
.ForEach(msg =>
|
||||
{
|
||||
if (msg.Type == AIResponseMessageType.Custom)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg.Speech != "[]")
|
||||
{
|
||||
msg.Speech = msg.Speech.StartsWith("[") ?
|
||||
ArrayHelper.GetRandom(msg.Speech.Substring(2, msg.Speech.Length - 4).Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList()) :
|
||||
msg.Speech;
|
||||
|
||||
msg.Speech = ReplaceParameters4Response(intentResponse.Parameters, msg.Speech);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static string ReplaceParameters4Response(List<IntentResponseParameter> parameters, string text)
|
||||
{
|
||||
var reg = new Regex(@"\$\w+");
|
||||
|
||||
reg.Matches(text).Cast<Match>().ToList().ForEach(token => {
|
||||
var parameter = parameters.FirstOrDefault(x => x.Name == token.Value.Substring(1));
|
||||
if(parameter != null)
|
||||
{
|
||||
text = text.Replace(token.Value, parameter?.Value?.ToString());
|
||||
}
|
||||
});
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void HandleContext(Database dc, AiRequest aiRequest, IntentResponse intentResponse, AiResponse aiResponse)
|
||||
{
|
||||
if (intentResponse == null) return;
|
||||
|
||||
// Merge context lifespan
|
||||
// override if exists, otherwise add, delete if lifespan is zero
|
||||
dc.DbTran(() =>
|
||||
{
|
||||
var sessionContexts = dc.Table<ConversationContext>().Where(x => x.ConversationId == aiRequest.SessionId).ToList();
|
||||
|
||||
// minus 1 round
|
||||
sessionContexts.Where(x => !intentResponse.Contexts.Select(ctx => ctx.Name).Contains(x.Context))
|
||||
.ToList()
|
||||
.ForEach(ctx => ctx.Lifespan = ctx.Lifespan - 1);
|
||||
|
||||
intentResponse.Contexts.ForEach(ctx =>
|
||||
{
|
||||
var session1 = sessionContexts.FirstOrDefault(x => x.Context == ctx.Name);
|
||||
|
||||
if (session1 != null)
|
||||
{
|
||||
if (ctx.Lifespan == 0)
|
||||
{
|
||||
dc.Table<ConversationContext>().Remove(session1);
|
||||
}
|
||||
else
|
||||
{
|
||||
session1.Lifespan = ctx.Lifespan;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.Table<ConversationContext>().Add(new ConversationContext
|
||||
{
|
||||
ConversationId = aiRequest.SessionId,
|
||||
Context = ctx.Name,
|
||||
Lifespan = ctx.Lifespan
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*aiResponse.Result.Contexts = dc.Table<ConversationContext>()
|
||||
.Where(x => x.Lifespan > 0 && x.ConversationId == AiConfig.SessionId)
|
||||
.Select(x => new AIContext { Name = x.Context.ToLower(), Lifespan = x.Lifespan })
|
||||
.ToArray();*/
|
||||
}
|
||||
|
||||
public static string GetModelPerContexts(AgentModel agent, AiRequest aiRequest, AiRequest request, Database dc)
|
||||
{
|
||||
// Merge input contexts
|
||||
/*var contexts = dc.Table<ConversationContext>()
|
||||
.Where(x => x.ConversationId == aiConfig.SessionId && x.Lifespan > 0)
|
||||
.ToList()
|
||||
.Select(x => new AIContext { Name = x.Context.ToLower(), Lifespan = x.Lifespan })
|
||||
.ToList();
|
||||
|
||||
contexts.AddRange(request.Contexts.Select(x => new AIContext { Name = x.Name.ToLower(), Lifespan = x.Lifespan }));
|
||||
contexts = contexts.OrderBy(x => x.Name).ToList();
|
||||
|
||||
// search all potential intents which input context included in contexts
|
||||
var intents = agent.Intents.Where(it =>
|
||||
{
|
||||
if (contexts.Count == 0)
|
||||
{
|
||||
return it.Contexts.Count() == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it.Contexts.Count() > 0 &&
|
||||
it.Contexts.Count(x => contexts.Select(ctx => ctx.Name).Contains(x.Name.ToLower())) == it.Contexts.Count;
|
||||
}
|
||||
}).OrderByDescending(x => x.Contexts.Count).ToList();
|
||||
|
||||
// query per request contexts
|
||||
var contextHashs = intents.Select(x => x.ContextHash).Distinct().ToList();
|
||||
|
||||
return contextHashs.FirstOrDefault();*/
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
BotSharp.Platform.Rasa/Models/RasaRequestModel.cs
Normal file
17
BotSharp.Platform.Rasa/Models/RasaRequestModel.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaRequestModel
|
||||
{
|
||||
[JsonProperty("q")]
|
||||
public string Text { get; set; }
|
||||
|
||||
public string Project { get; set; }
|
||||
|
||||
public string Model { get; set; }
|
||||
}
|
||||
}
|
||||
32
BotSharp.Platform.Rasa/Models/RasaResponse.cs
Normal file
32
BotSharp.Platform.Rasa/Models/RasaResponse.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaResponse
|
||||
{
|
||||
public RasaResponseIntent Intent { get; set; }
|
||||
|
||||
//public AIResponseFulfillment Fullfillment { get; set; }
|
||||
|
||||
[JsonProperty("intent_ranking")]
|
||||
public List<RasaResponseIntent> IntentRanking { get; set; }
|
||||
|
||||
public List<RasaResponseEntity> Entities { get; set; }
|
||||
|
||||
public String Text { get; set; }
|
||||
|
||||
public String Project { get; set; }
|
||||
|
||||
public String Model { get; set; }
|
||||
}
|
||||
|
||||
public class RasaResponseIntent
|
||||
{
|
||||
public String Name { get; set; }
|
||||
|
||||
public Decimal Confidence { get; set; }
|
||||
}
|
||||
}
|
||||
11
BotSharp.Platform.Rasa/Models/RasaResponseEntity.cs
Normal file
11
BotSharp.Platform.Rasa/Models/RasaResponseEntity.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaResponseEntity : RasaIntentExpressionPart
|
||||
{
|
||||
public string Extractor { get; set; }
|
||||
}
|
||||
}
|
||||
35
BotSharp.Platform.Rasa/Models/RasaStatusModel.cs
Normal file
35
BotSharp.Platform.Rasa/Models/RasaStatusModel.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaStatusModel
|
||||
{
|
||||
[JsonProperty("available_projects")]
|
||||
public JObject AvailableProjects { get; set; }
|
||||
|
||||
[JsonProperty("current_training_processes")]
|
||||
public int CurrentTrainingProcesses { get; set; }
|
||||
|
||||
[JsonProperty("max_training_processes")]
|
||||
public int MaxTrainingProcesses { get; set; }
|
||||
}
|
||||
|
||||
public class RasaProjectModel
|
||||
{
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[JsonProperty("current_training_processes")]
|
||||
public int CurrentTrainingProcesses { get; set; }
|
||||
|
||||
[JsonProperty("available_models")]
|
||||
public List<string> AvailableModels { get; set; }
|
||||
|
||||
[JsonProperty("loaded_models")]
|
||||
public List<string> LoadedModels { get; set; }
|
||||
}
|
||||
}
|
||||
19
BotSharp.Platform.Rasa/Models/RasaTrainingData.cs
Normal file
19
BotSharp.Platform.Rasa/Models/RasaTrainingData.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaTrainingData
|
||||
{
|
||||
[JsonProperty("common_examples")]
|
||||
public List<RasaIntentExpression> UserSays { get; set; }
|
||||
|
||||
[JsonProperty("entity_synonyms")]
|
||||
public List<RasaTrainingEntity> Entities { get; set; }
|
||||
|
||||
[JsonProperty("regex_features")]
|
||||
public List<RasaTrainingRegex> Regex { get; set; }
|
||||
}
|
||||
}
|
||||
17
BotSharp.Platform.Rasa/Models/RasaTrainingEntity.cs
Normal file
17
BotSharp.Platform.Rasa/Models/RasaTrainingEntity.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using BotSharp.Core.Engines;
|
||||
using BotSharp.Platform.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public sealed class RasaTrainingEntity
|
||||
{
|
||||
[JsonProperty("value")]
|
||||
public String Entity { get; set; }
|
||||
|
||||
public List<string> Synonyms { get; set; }
|
||||
}
|
||||
}
|
||||
13
BotSharp.Platform.Rasa/Models/RasaTrainingRegex.cs
Normal file
13
BotSharp.Platform.Rasa/Models/RasaTrainingRegex.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaTrainingRegex
|
||||
{
|
||||
public String Name { get; set; }
|
||||
|
||||
public String Pattern { get; set; }
|
||||
}
|
||||
}
|
||||
15
BotSharp.Platform.Rasa/Models/RasaVersionModel.cs
Normal file
15
BotSharp.Platform.Rasa/Models/RasaVersionModel.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaVersionModel
|
||||
{
|
||||
public string Version { get; set; }
|
||||
|
||||
[JsonProperty("minimum_compatible_version")]
|
||||
public string MinimumCompatibleVersion { get; set; }
|
||||
}
|
||||
}
|
||||
29
BotSharp.Platform.Rasa/ModuleInjector.cs
Normal file
29
BotSharp.Platform.Rasa/ModuleInjector.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using BotSharp.Core;
|
||||
using BotSharp.Core.AgentStorage;
|
||||
using BotSharp.Core.Modules;
|
||||
using BotSharp.Platform.Rasa.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa
|
||||
{
|
||||
public class ModuleInjector : IModule
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddSingleton<RasaAi<AgentModel>>();
|
||||
AgentStorageServiceRegister.Register<AgentModel>(services);
|
||||
PlatformConfigServiceRegister.Register<PlatformSettings>("rasaAi", services, config);
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
BotSharp.Platform.Rasa/PlatformSettings.cs
Normal file
11
BotSharp.Platform.Rasa/PlatformSettings.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using BotSharp.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa
|
||||
{
|
||||
public class PlatformSettings : PlatformSettingsBase
|
||||
{
|
||||
}
|
||||
}
|
||||
2
BotSharp.Platform.Rasa/README.md
Normal file
2
BotSharp.Platform.Rasa/README.md
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# botsharp-rasa
|
||||
BotSharp platform emulator extension which is compatible with RASA NLU.
|
||||
138
BotSharp.Platform.Rasa/RasaAi.cs
Normal file
138
BotSharp.Platform.Rasa/RasaAi.cs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
using BotSharp.Core;
|
||||
using BotSharp.Core.Engines;
|
||||
using BotSharp.Platform.Abstraction;
|
||||
using BotSharp.Platform.Models;
|
||||
using BotSharp.Platform.Models.AiRequest;
|
||||
using BotSharp.Platform.Models.AiResponse;
|
||||
using BotSharp.Platform.Rasa.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Platform.Rasa
|
||||
{
|
||||
/// <summary>
|
||||
/// Rasa nlu >= 0.12
|
||||
/// </summary>
|
||||
public class RasaAi<TAgent> :
|
||||
PlatformBuilderBase<TAgent>,
|
||||
IPlatformBuilder<TAgent>
|
||||
where TAgent : AgentModel
|
||||
{
|
||||
|
||||
public RasaAi(IAgentStorageFactory<TAgent> agentStorageFactory, IPlatformSettings settings)
|
||||
: base(agentStorageFactory, settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task<AiResponse> TextRequest(AiRequest request)
|
||||
{
|
||||
AiResponse aiResponse = new AiResponse();
|
||||
|
||||
/*string model = RasaRequestExtension.GetModelPerContexts(agent, AiConfig, request, dc);
|
||||
var result = CallRasa(agent.Id, request.Query.First(), model);
|
||||
|
||||
result.Content.Log();
|
||||
|
||||
RasaResponse response = result.Data;
|
||||
aiResponse.Id = Guid.NewGuid().ToString();
|
||||
aiResponse.Lang = agent.Language;
|
||||
aiResponse.Status = new AIResponseStatus { };
|
||||
aiResponse.SessionId = AiConfig.SessionId;
|
||||
aiResponse.Timestamp = DateTime.UtcNow;
|
||||
|
||||
var intentResponse = RasaRequestExtension.HandleIntentPerContextIn(agent, AiConfig, request, result.Data, dc);
|
||||
|
||||
RasaRequestExtension.HandleParameter(agent, intentResponse, response, request);
|
||||
|
||||
RasaRequestExtension.HandleMessage(intentResponse);
|
||||
|
||||
aiResponse.Result = new AIResponseResult
|
||||
{
|
||||
Source = "agent",
|
||||
ResolvedQuery = request.Query.First(),
|
||||
Action = intentResponse?.Action,
|
||||
Parameters = intentResponse?.Parameters?.ToDictionary(x => x.Name, x => (object)x.Value),
|
||||
Score = response.Intent.Confidence,
|
||||
Metadata = new AIResponseMetadata { IntentId = intentResponse?.IntentId, IntentName = intentResponse?.IntentName },
|
||||
Fulfillment = new AIResponseFulfillment
|
||||
{
|
||||
Messages = intentResponse?.Messages?.Select(x => {
|
||||
if (x.Type == AIResponseMessageType.Custom)
|
||||
{
|
||||
return (new
|
||||
{
|
||||
x.Type,
|
||||
Payload = JsonConvert.DeserializeObject(x.PayloadJson)
|
||||
}) as Object;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (new { x.Type, x.Speech }) as Object;
|
||||
}
|
||||
|
||||
}).ToList()
|
||||
}
|
||||
};
|
||||
|
||||
RasaRequestExtension.HandleContext(dc, AiConfig, intentResponse, aiResponse);
|
||||
|
||||
Console.WriteLine(JsonConvert.SerializeObject(aiResponse.Result));*/
|
||||
|
||||
return aiResponse;
|
||||
}
|
||||
|
||||
public async Task<TrainingCorpus> ExtractorCorpus(TAgent agent)
|
||||
{
|
||||
var corpus = new TrainingCorpus()
|
||||
{
|
||||
Entities = new List<TrainingEntity>(),
|
||||
UserSays = new List<TrainingIntentExpression<TrainingIntentExpressionPart>>()
|
||||
};
|
||||
|
||||
List<string> entities = new List<string>();
|
||||
|
||||
// generate entity list
|
||||
agent.Intents.ForEach(intent =>
|
||||
{
|
||||
intent.Entities.ForEach(entity =>
|
||||
{
|
||||
if (!entities.Contains(entity.Entity))
|
||||
{
|
||||
corpus.Entities.Add(new TrainingEntity
|
||||
{
|
||||
Entity = entity.Entity,
|
||||
Values = new List<TrainingEntitySynonym>
|
||||
{
|
||||
new TrainingEntitySynonym
|
||||
{
|
||||
Value = entity.Value,
|
||||
Synonyms = new List<string>
|
||||
{
|
||||
entity.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
entities.Add(entity.Entity);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
agent.Intents.ForEach(intent =>
|
||||
{
|
||||
var express = new TrainingIntentExpression<TrainingIntentExpressionPart>()
|
||||
{
|
||||
Text = intent.Text,
|
||||
Intent = intent.Intent,
|
||||
Entities = intent.Entities
|
||||
};
|
||||
|
||||
corpus.UserSays.Add(express);
|
||||
});
|
||||
|
||||
return corpus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Platform.Rasa.Models
|
||||
{
|
||||
public class RasaTrainRequestViewModel
|
||||
{
|
||||
public string Project { get; set; }
|
||||
|
||||
public string Model { get; set; }
|
||||
|
||||
[JsonProperty("rasa_nlu_data")]
|
||||
public RasaTrainingData Corpus { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,10 @@
|
|||
"Name": "DialogflowAi",
|
||||
"Type": "BotSharp.Platform.Dialogflow"
|
||||
},
|
||||
{
|
||||
"Name": "RasaAi",
|
||||
"Type": "BotSharp.Platform.Rasa"
|
||||
},
|
||||
{
|
||||
"Name": "WeixinChannel",
|
||||
"Type": "BotSharp.Channel.Weixin"
|
||||
|
|
|
|||
26
BotSharp.sln
26
BotSharp.sln
|
|
@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Channel.Weixin", "
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Channel.FacebookMessenger", "BotSharp.Channel.FacebookMessenger\BotSharp.Channel.FacebookMessenger.csproj", "{22C52A04-581B-4186-8C04-0CD359FA568A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Platform.Rasa", "BotSharp.Platform.Rasa\BotSharp.Platform.Rasa.csproj", "{2EDE5F82-9219-4827-B636-13717DCDDF01}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
ARTICULATE|Any CPU = ARTICULATE|Any CPU
|
||||
|
|
@ -231,6 +233,30 @@ Global
|
|||
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|x64.ActiveCfg = Debug|Any CPU
|
||||
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|x64.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.ARTICULATE|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.ARTICULATE|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.ARTICULATE|x64.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.ARTICULATE|x64.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.DIALOGFLOW|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.DIALOGFLOW|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.DIALOGFLOW|x64.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.DIALOGFLOW|x64.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.RASA|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.RASA|Any CPU.Build.0 = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.RASA|x64.ActiveCfg = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.RASA|x64.Build.0 = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Test|x64.ActiveCfg = Debug|Any CPU
|
||||
{2EDE5F82-9219-4827-B636-13717DCDDF01}.Test|x64.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
Loading…
Reference in a new issue