From 890df8743a86ffd7016614f21923681751f3cfd5 Mon Sep 17 00:00:00 2001 From: Wenbo Cao <104199@smsassist.com> Date: Thu, 31 Aug 2023 10:48:59 -0500 Subject: [PATCH] Add intent classifier in routing speeder. --- .../Settings}/KnowledgeBaseSettings.cs | 2 +- .../Plugins/Knowledges/KnowledgeBasePlugin.cs | 1 + .../Knowledges/Services/KnowledgeService.cs | 2 +- .../Controllers/KnowledgeController.cs | 2 +- .../BotSharp.Plugin.RoutingSpeeder.csproj | 6 +- ...logueClassifier.cs => IntentClassifier.cs} | 31 ++++---- .../Models/TrainingParams.cs} | 2 +- .../Providers/fastTextEmbeddingProvider.cs | 70 ------------------- .../RoutingConversationHook.cs | 11 +-- .../RoutingSpeederPlugin.cs | 10 +-- .../Settings/classifierSetting.cs | 15 ++-- .../Settings/fastTextSetting.cs | 7 -- .../Settings/routerSpeedSettings.cs | 4 +- src/WebStarter/appsettings.json | 13 ++-- 14 files changed, 53 insertions(+), 123 deletions(-) rename src/Infrastructure/{BotSharp.Core/Plugins/Knowledges => BotSharp.Abstraction/Knowledges/Settings}/KnowledgeBaseSettings.cs (81%) rename src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/{DialogueClassifier.cs => IntentClassifier.cs} (79%) rename src/Plugins/BotSharp.Plugin.RoutingSpeeder/{Settings/trainingParams.cs => Providers/Models/TrainingParams.cs} (82%) delete mode 100644 src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/fastTextEmbeddingProvider.cs delete mode 100644 src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/fastTextSetting.cs diff --git a/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBaseSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Settings/KnowledgeBaseSettings.cs similarity index 81% rename from src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBaseSettings.cs rename to src/Infrastructure/BotSharp.Abstraction/Knowledges/Settings/KnowledgeBaseSettings.cs index 0cb08a48..97f7f55c 100644 --- a/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBaseSettings.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Settings/KnowledgeBaseSettings.cs @@ -1,4 +1,4 @@ -namespace BotSharp.Core.Plugins.Knowledges; +namespace BotSharp.Abstraction.Knowledges.Settings; public class KnowledgeBaseSettings { diff --git a/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBasePlugin.cs b/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBasePlugin.cs index e0c74e83..8f862ca4 100644 --- a/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBasePlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/KnowledgeBasePlugin.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Knowledges.Settings; using BotSharp.Core.Plugins.Knowledges.Services; using Microsoft.Extensions.Configuration; diff --git a/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/Services/KnowledgeService.cs b/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/Services/KnowledgeService.cs index 9ed87e6a..3a627ec9 100644 --- a/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/Services/KnowledgeService.cs +++ b/src/Infrastructure/BotSharp.Core/Plugins/Knowledges/Services/KnowledgeService.cs @@ -1,7 +1,7 @@ using BotSharp.Abstraction.Knowledges.Models; +using BotSharp.Abstraction.Knowledges.Settings; using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.VectorStorage; -using System.Text.Json; namespace BotSharp.Core.Plugins.Knowledges.Services; diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs index 3824f476..bea5597b 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Http; using UglyToad.PdfPig.Content; using UglyToad.PdfPig; using BotSharp.Core.Plugins.Knowledges; - +using BotSharp.Abstraction.Knowledges.Settings; namespace BotSharp.OpenAPI.Controllers; diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj index e0a8e7af..fb145e8d 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj @@ -8,13 +8,11 @@ - + - - - + diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/DialogueClassifier.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs similarity index 79% rename from src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/DialogueClassifier.cs rename to src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs index 788eb641..ea74f54d 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/DialogueClassifier.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs @@ -15,19 +15,20 @@ using BotSharp.Plugin.RoutingSpeeder.Providers.Models; using Microsoft.Extensions.DependencyInjection; using System.Linq; using Tensorflow.Keras; +using BotSharp.Abstraction.Knowledges.Settings; namespace BotSharp.Plugin.RoutingSpeeder.Providers; -public class DialogueClassifier +public class IntentClassifier { private readonly IServiceProvider _services; Model _model; public Model model => _model; private bool _isModelReady; public bool isModelReady => _isModelReady; - private classifierSetting _settings; + private ClassifierSetting _settings; - public DialogueClassifier(IServiceProvider services, classifierSetting settings) + public IntentClassifier(IServiceProvider services, ClassifierSetting settings) { _services = services; _settings = settings; @@ -51,7 +52,7 @@ public class DialogueClassifier keras.layers.InputLayer((300), name: "Input"), keras.layers.Dense(256, activation:"relu"), keras.layers.Dense(256, activation:"relu"), - keras.layers.Dense(_settings.labelMappingDict.Count, activation: keras.activations.Softmax) + keras.layers.Dense(_settings.LabelMappingDict.Count, activation: keras.activations.Softmax) }; _model = keras.Sequential(layers); @@ -64,10 +65,6 @@ public class DialogueClassifier private void Fit(NDArray x, NDArray y, TrainingParams trainingParams) { - // release more memory - var vector = _services.GetRequiredService(); - // vector.UnloadModel(); - _model.compile(optimizer: keras.optimizers.Adam(trainingParams.LearningRate), loss: keras.losses.SparseCategoricalCrossentropy(), metrics: new[] { "accuracy" } @@ -101,7 +98,7 @@ public class DialogueClassifier public string LoadWeights() { - var weightsFile = Path.Combine(_settings.MODEL_DIR, $"wo-dialogue-classifier.h5"); + var weightsFile = Path.Combine(_settings.MODEL_DIR, $"intent-classifier.h5"); if (File.Exists(weightsFile)) { _model.load_weights(weightsFile); @@ -116,7 +113,7 @@ public class DialogueClassifier public (NDArray x, NDArray y) Vectorize(List items) { - var x = np.zeros((items.Count, 300), dtype: np.float32); + var x = np.zeros((items.Count, vector.Dimension), dtype: np.float32); var y = np.zeros((items.Count, 1), dtype: np.float32); var vector = _services.GetRequiredService(); @@ -124,13 +121,23 @@ public class DialogueClassifier for (int i = 0; i < items.Count; i++) { x[i] = vector.GetVector(TextClean(items[i].text)); - if (_settings.labelMappingDict.ContainsKey(items[i].label)) + if (_settings.LabelMappingDict.ContainsKey(items[i].label)) { - y[i] = _settings.labelMappingDict[items[i].label]; + y[i] = _settings.LabelMappingDict[items[i].label]; } } return (x, y); } + + public float[] GetTextEmbedding(string text) + { + var knowledgeSettings = _services.GetRequiredService(); + var embedding = _services.GetServices() + .FirstOrDefault(x => x.GetType().FullName.EndsWith(knowledgeSettings.TextEmbedding)); + + return embedding.GetVector(text); + } + public string TextClean(string text) { // Remove punctuation diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/trainingParams.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/TrainingParams.cs similarity index 82% rename from src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/trainingParams.cs rename to src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/TrainingParams.cs index fcf15ce3..f3c822ac 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/trainingParams.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/TrainingParams.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Text; -namespace BotSharp.Plugin.RoutingSpeeder.Settings; +namespace BotSharp.Plugin.RoutingSpeeder.Providers.Models; public class TrainingParams { diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/fastTextEmbeddingProvider.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/fastTextEmbeddingProvider.cs deleted file mode 100644 index 79925418..00000000 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/fastTextEmbeddingProvider.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime; -using System.Text; -using System.Text.RegularExpressions; -using BotSharp.Abstraction.MLTasks; -using BotSharp.Plugin.RoutingSpeeder.Settings; -using FastText.NetWrapper; - -namespace BotSharp.Plugin.RoutingSpeeder.Providers; - -public class fastTextEmbeddingProvider : ITextEmbedding -{ - private FastTextWrapper _fastText; - private readonly fastTextSetting _settings; - - public int Dimension - { - get - { - if (!_fastText.IsModelReady()) - { - _fastText.LoadModel(_settings.ModelPath); - } - return _fastText.GetModelDimension(); - } - } - - public fastTextEmbeddingProvider(fastTextSetting settings) - { - _settings = settings; - - } - - public float[] GetVector(string text) - { - LoadModel(); - return _fastText.GetSentenceVector(text); - } - - public List GetVectors(List texts) - { - LoadModel(); - var vectors = new List(); - for (int i = 0; i < texts.Count; i++) - { - vectors.Add(GetVector(texts[i])); - } - return vectors; - } - - private void LoadModel() - { - if (_fastText == null) - { - if (!File.Exists(_settings.ModelPath)) - { - throw new FileNotFoundException($"Can't load pre-trained word vectors from {_settings.ModelPath}.\n Try to download from https://fasttext.cc/docs/en/english-vectors.html."); - } - - _fastText = new FastTextWrapper(); - - if (!_fastText.IsModelReady()) - { - _fastText.LoadModel(_settings.ModelPath); - } - } - } -} diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs index 2307c079..e742f169 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs @@ -7,24 +7,25 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; using System.Threading.Tasks; -using FastText.NetWrapper; using BotSharp.Plugin.RoutingSpeeder.Settings; +using BotSharp.Abstraction.Templating; +using BotSharp.Plugin.RoutingSpeeder.Providers; namespace BotSharp.Plugin.RoutingSpeeder; public class RoutingConversationHook: ConversationHookBase { private readonly IServiceProvider _services; - private routerSpeedSettings _settings; - public RoutingConversationHook(IServiceProvider service, routerSpeedSettings settings) + private RouterSpeederSettings _settings; + public RoutingConversationHook(IServiceProvider service, RouterSpeederSettings settings) { _services = service; _settings = settings; } public override async Task BeforeCompletion(RoleDialogModel message) { - var embedding = _services.GetServices() - .FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.TextEmbedding)); + var intentClassifier = _services.GetRequiredService(); + var vector = intentClassifier.GetTextEmbedding(message.Content); // Utilize local discriminative model to predict intent message.IntentName = "greeting"; diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingSpeederPlugin.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingSpeederPlugin.cs index bcb91335..c3dac3a2 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingSpeederPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingSpeederPlugin.cs @@ -12,11 +12,13 @@ public class RoutingSpeederPlugin : IBotSharpPlugin { public void RegisterDI(IServiceCollection services, IConfiguration config) { - var settings = new routerSpeedSettings(); - config.Bind("routerSpeed", settings); + var settings = new RouterSpeederSettings(); + config.Bind("RouterSpeeder", settings); services.AddSingleton(x => settings); - services.AddSingleton(x => settings.fastText); + + services.AddSingleton(); + services.AddScoped(); - services.AddSingleton(); + services.AddSingleton(); } } diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs index 2fe13237..e6352694 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs @@ -4,18 +4,15 @@ using System.Text; namespace BotSharp.Plugin.RoutingSpeeder.Settings; -public class classifierSetting +public class ClassifierSetting { - - public Dictionary labelMappingDict { get; set; } = new Dictionary() + public Dictionary LabelMappingDict { get; set; } = new Dictionary() { {"goodbye", 0f}, {"greeting", 1f}, - {"other", 2f}, - {"wo-followup", 3f}, - {"wo-identifer", 4f}, - {"wo-scheduler", 5} + {"other", 2f} }; - public string RAW_DATA_DIR { get; set; } = "C:\\new_wenbocao\\one_brain\\WebStarter\\data\\raw_data"; - public string MODEL_DIR { get; set; } = "C:\\new_wenbocao\\one_brain\\WebStarter\\data\\models"; + + public string RAW_DATA_DIR { get; set; } = ""; + public string MODEL_DIR { get; set; } = ""; } diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/fastTextSetting.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/fastTextSetting.cs deleted file mode 100644 index e5554402..00000000 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/fastTextSetting.cs +++ /dev/null @@ -1,7 +0,0 @@ - -namespace BotSharp.Plugin.RoutingSpeeder.Settings; - -public class fastTextSetting -{ - public string ModelPath { get; set; } -} diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/routerSpeedSettings.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/routerSpeedSettings.cs index 300ec9e0..fbedf581 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/routerSpeedSettings.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/routerSpeedSettings.cs @@ -4,8 +4,6 @@ using System.Text; namespace BotSharp.Plugin.RoutingSpeeder.Settings; -public class routerSpeedSettings +public class RouterSpeederSettings { - public fastTextSetting fastText { get; set; } - public string TextEmbedding { get; set; } } diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index 42ef6319..e409738f 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -47,11 +47,14 @@ } }, - "MetaAi": { - "fastText": { - "ModelPath": "crawl-300d-2M-subword.bin" - } - }, + "MetaAi": { + "fastText": { + "ModelPath": "crawl-300d-2M-subword.bin" + } + }, + + "RoutingSpeeder": { + }, "MetaMessenger": { "Endpoint": "https://graph.facebook.com",