Add entity synonym support

This commit is contained in:
haiping008@gmail.com 2018-04-02 17:42:11 -05:00
parent 6c472545c0
commit 10616332e7
17 changed files with 166 additions and 34 deletions

View file

@ -0,0 +1,5 @@
{
"Rasa": {
"Host": "http://rasa.local:5000"
}
}

View file

@ -3,8 +3,8 @@
"Default": "SqlServer",
"ConnectionStrings": {
"InMemory": "DataSource=:memory:",
"Sqlite": "Data Source=|DataDirectory|RasaBot.db;",
"SqlServer": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=RasaBot;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
"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"
}
}
}

View file

@ -1,5 +0,0 @@
{
"Rasa": {
"Host": "http://81a1f75c.ngrok.io"
}
}

View file

@ -1,4 +1,5 @@
using Newtonsoft.Json;
using BotSharp.Core.Entities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
@ -11,8 +12,9 @@ namespace BotSharp.Core.Adapters.Dialogflow
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("synonyms")]
public List<String> Synonyms { get; set; }
public List<String> RawSynonyms { get; set; }
public List<EntityEntrySynonym> Synonyms { get; set; }
public DialogflowEntityEntry()
{
@ -21,7 +23,7 @@ namespace BotSharp.Core.Adapters.Dialogflow
public DialogflowEntityEntry(string value, List<string> synonyms)
{
this.Value = value;
this.Synonyms = synonyms;
this.RawSynonyms = synonyms;
}
public DialogflowEntityEntry(string value, string[] synonyms) : this(value, new List<string>(synonyms))

View file

@ -0,0 +1,17 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Core.Adapters.Rasa
{
public class RasaTraningEntity
{
public String EntityType { get; set; }
[JsonProperty("value")]
public String EntityValue { get; set; }
public List<String> Synonyms { get; set; }
}
}

View file

@ -1,4 +1,6 @@
using BotSharp.Core.Entities;
using BotSharp.Core.Adapters.Rasa;
using BotSharp.Core.Entities;
using BotSharp.Core.Expressions;
using BotSharp.Core.Intents;
using BotSharp.Core.Models;
using EntityFrameworkCore.BootKit;
@ -32,9 +34,12 @@ namespace BotSharp.Core.Agents
{
var trainingData = new RasaTrainingData
{
Entities = new List<RasaTraningEntity>(),
UserSays = new List<RasaIntentExpression>()
};
var expressParts = new List<IntentExpressionPart>();
var intents = dc.Table<Intent>()
.Include(x => x.Contexts)
.Include(x => x.UserSays).ThenInclude(say => say.Data)
@ -81,13 +86,35 @@ namespace BotSharp.Core.Agents
End = start + x.Text.Length
};
if (say.Entities == null) say.Entities = new List<RasaIntentExpressionPart>();
say.Entities.Add(part);
// assemble entity synonmus
if (!trainingData.Entities.Any(y => y.EntityType == x.Alias && y.EntityValue == x.Text))
{
var allSynonyms = (from e in dc.Table<Entity>()
join ee in dc.Table<EntityEntry>() on e.Id equals ee.EntityId
join ees in dc.Table<EntityEntrySynonym>() on ee.Id equals ees.EntityEntryId
where e.Name == x.Alias && ee.Value == x.Text & ees.Synonym != x.Text
select ees.Synonym ).ToList();
var te = new RasaTraningEntity
{
EntityType = x.Alias,
EntityValue = x.Text,
Synonyms = allSynonyms
};
trainingData.Entities.Add(te);
}
});
trainingData.UserSays.Add(say);
});
});
return trainingData;
}
}

View file

@ -1,5 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

View file

@ -46,7 +46,12 @@ namespace BotSharp.Core.Engines
if (File.Exists(entriesFileName))
{
string entriesJson = File.ReadAllText($"{entriesFileName}");
entriesJson = entriesJson.Replace("\"synonyms\":", "\"rawSynonyms\":");
entity.Entries = JsonConvert.DeserializeObject<List<DialogflowEntityEntry>>(entriesJson);
entity.Entries.ForEach(x => x.Synonyms = x.RawSynonyms.Select(s => new EntityEntrySynonym
{
Synonym = s
}).ToList());
}
agent.Entities.Add(entity.ToObject<Entity>());

View file

@ -258,7 +258,8 @@ namespace BotSharp.Core.Engines
string json = JsonConvert.SerializeObject(new { rasa_nlu_data = corpus },
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
});
var client = new RestClient($"{Database.Configuration.GetSection("Rasa:Host").Value}");
@ -267,10 +268,11 @@ namespace BotSharp.Core.Engines
rest.AddParameter("application/json", json, ParameterType.RequestBody);
var response = client.Execute(rest);
var result = JObject.Parse(response.Content);
if (response.IsSuccessful)
{
var result = JObject.Parse(response.Content);
string modelName = result["info"].Value<String>().Split(": ")[1];
dc.Table<ContextModelMapping>().Add(new ContextModelMapping
@ -284,6 +286,8 @@ namespace BotSharp.Core.Engines
}
else
{
var result = JObject.Parse(response.Content);
Console.WriteLine(result["error"]);
return String.Empty;

View file

@ -18,10 +18,11 @@ namespace BotSharp.Core.Entities
[MaxLength(64)]
public String Name { get; set; }
[NotMapped]
public List<String> Values { get; set; }
[ForeignKey("EntityId")]
public List<EntityEntry> Entries { get; set; }
public bool IsOverridable { get; set; }
public bool IsEnum { get; set; }
}
}

View file

@ -14,10 +14,10 @@ namespace BotSharp.Core.Entities
[StringLength(36)]
public String EntityId { get; set; }
[MaxLength(128)]
[MaxLength(64)]
public String Value { get; set; }
[NotMapped]
public List<String> Synonyms { get; set; }
[ForeignKey("EntityEntryId")]
public List<EntityEntrySynonym> Synonyms { get; set; }
}
}

View file

@ -0,0 +1,20 @@
using EntityFrameworkCore.BootKit;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace BotSharp.Core.Entities
{
[Table("Bot_EntityEntrySynonym")]
public class EntityEntrySynonym : DbRecord, IDbRecord
{
[Required]
[StringLength(36)]
public String EntityEntryId { get; set; }
[MaxLength(64)]
public String Synonym { get; set; }
}
}

View file

@ -9,7 +9,6 @@ namespace BotSharp.Core.Models
{
public RasaIntentExpression()
{
Entities = new List<RasaIntentExpressionPart>();
}
public String Text { get; set; }

View file

@ -1,4 +1,5 @@
using Newtonsoft.Json;
using BotSharp.Core.Adapters.Rasa;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
@ -9,5 +10,8 @@ namespace BotSharp.Core.Models
{
[JsonProperty("common_examples")]
public List<RasaIntentExpression> UserSays { get; set; }
[JsonProperty("entity_synonyms")]
public List<RasaTraningEntity> Entities { get; set; }
}
}

View file

@ -0,0 +1,29 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.UnitTest
{
[TestClass]
public class EntityEntryTest : TestEssential
{
[TestMethod]
public void CreateEntityEntryTest()
{
}
[TestMethod]
public void UpdateEntityEntryeTest()
{
}
[TestMethod]
public void DeleteEntityEntryTest()
{
}
}
}

View file

@ -1,12 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.UnitTest
{
[TestClass]
public class EntityTest : TestEssential
{
}
}

View file

@ -0,0 +1,29 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.UnitTest
{
[TestClass]
public class EntityTypeTest : TestEssential
{
[TestMethod]
public void CreateEntityTypeTest()
{
}
[TestMethod]
public void UpdateEntityTypeTest()
{
}
[TestMethod]
public void DeleteEntityTypeTest()
{
}
}
}