From eaab096ca0972d85c9173a9bb1436f1df10966f1 Mon Sep 17 00:00:00 2001 From: Wenbo Cao <104199@smsassist.com> Date: Mon, 11 Sep 2023 14:20:33 -0500 Subject: [PATCH] solve RoutingSpeeder path issue --- .../Controllers/RoutingSpeederController.cs | 11 ++- .../Providers/IntentClassifier.cs | 79 +++++++++++-------- .../Models/DialoguePredictionModel.cs | 6 +- .../Settings/classifierSetting.cs | 11 +-- 4 files changed, 63 insertions(+), 44 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Controllers/RoutingSpeederController.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Controllers/RoutingSpeederController.cs index 67cb0c40..6c4deebb 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Controllers/RoutingSpeederController.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Controllers/RoutingSpeederController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading.Tasks; +using BotSharp.Abstraction.Conversations.Models; using BotSharp.Plugin.RoutingSpeeder.Providers; using BotSharp.Plugin.RoutingSpeeder.Providers.Models; using Microsoft.AspNetCore.Authorization; @@ -24,9 +25,17 @@ public class RoutingSpeederController : ControllerBase public IActionResult TrainIntentClassifier(TrainingParams trainingParams) { var intentClassifier = _service.GetRequiredService(); - intentClassifier.InitClassifer(trainingParams.Inference); + // intentClassifier.InitClassifer(trainingParams.Inference); intentClassifier.Train(trainingParams); return Ok(intentClassifier.Labels); } + [HttpPost("/routing-speeder/classifier/inference")] + public IActionResult TrainIntentClassifier([FromBody] DialoguePredictionModel message) + { + var intentClassifier = _service.GetRequiredService(); + var vector = intentClassifier.GetTextEmbedding(message.Text); + var predText = intentClassifier.Predict(vector); + return Ok(predText); + } } diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs index 08acb673..2d4f2911 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/IntentClassifier.cs @@ -27,15 +27,9 @@ public class IntentClassifier private bool _isModelReady; public bool isModelReady => _isModelReady; private ClassifierSetting _settings; + private bool _inferenceMode = true; private string[] _labels; - public string[] Labels => GetLabels(); - private int _numLabels - { - get - { - return Labels.Length; - } - } + public string[] Labels => _labels == null ? GetLabels() : _labels; public IntentClassifier(IServiceProvider services, ClassifierSetting settings, KnowledgeBaseSettings knowledgeBaseSettings) { @@ -65,7 +59,7 @@ public class IntentClassifier keras.layers.InputLayer((vector.Dimension), name: "Input"), keras.layers.Dense(256, activation:"relu"), keras.layers.Dense(256, activation:"relu"), - keras.layers.Dense(_numLabels, activation: keras.activations.Softmax) + keras.layers.Dense(GetLabels().Length, activation: keras.activations.Softmax) }; _model = keras.Sequential(layers); @@ -73,7 +67,6 @@ public class IntentClassifier Console.WriteLine(); _model.summary(); #endif - _isModelReady = true; } private void Fit(NDArray x, NDArray y, TrainingParams trainingParams) @@ -97,7 +90,7 @@ public class IntentClassifier earlyStop }; - var weights = LoadWeights(trainingParams.Inference); + var weights = LoadWeights(); _model.fit(x, y, batch_size: trainingParams.BatchSize, @@ -110,15 +103,15 @@ public class IntentClassifier _isModelReady = true; } - public string LoadWeights(bool inference = true) + public string LoadWeights() { var agentService = _services.CreateScope() .ServiceProvider .GetRequiredService(); - var weightsFile = Path.Combine(agentService.GetDataDir(), _settings.MODEL_DIR, $"intent-classifier.h5"); + var weightsFile = Path.Combine(agentService.GetDataDir(), _settings.MODEL_DIR, _settings.WEIGHT_FILE_NAME); - if (File.Exists(weightsFile) && inference) + if (File.Exists(weightsFile) && _inferenceMode) { _model.load_weights(weightsFile); _isModelReady = true; @@ -126,7 +119,8 @@ public class IntentClassifier } else { - var logInfo = inference ? "No available weights." : "Will implement model training process and write trained weights into local"; + var logInfo = _inferenceMode ? "No available weights." : "Will implement model training process and write trained weights into local"; + _isModelReady = false; Console.WriteLine(logInfo); } @@ -159,7 +153,14 @@ public class IntentClassifier if (!Directory.Exists(rootDirectory)) { - throw new Exception($"No training data found! Please put training data in this path: {rootDirectory}"); + Directory.CreateDirectory(rootDirectory); + } + + int numFiles = Directory.GetFiles(rootDirectory).Length; + + if (numFiles == 0) + { + throw new Exception($"No dialogue data found in {rootDirectory} folder! Please put dialogue data in this path: {rootDirectory}"); } // Do embedding and store results @@ -214,25 +215,32 @@ public class IntentClassifier public string[] GetLabels() { - if (_labels == null) + var agentService = _services.CreateScope() + .ServiceProvider + .GetRequiredService(); + string labelPath = Path.Combine( + agentService.GetDataDir(), + _settings.MODEL_DIR, + _settings.LABEL_FILE_NAME); + + if (_inferenceMode) { - var agentService = _services.CreateScope() - .ServiceProvider - .GetRequiredService(); - - string[] labels = GetFiles() + if (_labels == null) + { + if (!File.Exists(labelPath)) + { + throw new Exception($"Label file doesn't exist. Please training model first or move label.txt to {labelPath}"); + } + _labels = File.ReadAllLines(labelPath); + } + } + else + { + _labels = GetFiles() .Select(x => Path.GetFileName(x).Split(".")[^2]) + .OrderBy(x => x) .ToArray(); - - string writePath = Path.Combine( - agentService.GetDataDir(), - _settings.MODEL_DIR, - _settings.LABEL_FILE_NAME); - - _labels = labels.OrderBy(x => x).ToArray(); - - // Write labels into the local txt file - File.WriteAllLines(writePath, _labels); + File.WriteAllLines(labelPath, _labels); } return _labels; } @@ -248,24 +256,25 @@ public class IntentClassifier var prob = _model.predict(vector).numpy(); var probLabel = tf.arg_max(prob, -1).numpy().ToArray(); prob = np.squeeze(prob, axis: 0); + var labelIndex = probLabel[0]; if (prob[probLabel[0]] < confidenceScore) { return string.Empty; } - var labelIndex = probLabel[0]; return _labels[labelIndex]; } - public void InitClassifer(bool inference = true) + public void InitClassifer() { Reset(); Build(); - LoadWeights(inference); + LoadWeights(); } public void Train(TrainingParams trainingParams) { + _inferenceMode = false; Reset(); (var x, var y) = PrepareLoadData(); Build(); diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/DialoguePredictionModel.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/DialoguePredictionModel.cs index 4641b9cd..36b7c38c 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/DialoguePredictionModel.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Providers/Models/DialoguePredictionModel.cs @@ -7,7 +7,7 @@ namespace BotSharp.Plugin.RoutingSpeeder.Providers.Models; public class DialoguePredictionModel { public int Id { get; set; } - public string text { get; set; } - public string? label { get; set; } - public string? prediction { get; set; } + public string Text { get; set; } + public string? Label { get; set; } + public string? Prediction { get; set; } } diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs index 09bda6e8..5e8c34c8 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/Settings/classifierSetting.cs @@ -7,13 +7,14 @@ namespace BotSharp.Plugin.RoutingSpeeder.Settings; public class ClassifierSetting { public Dictionary LabelMappingDict { get; set; } = new Dictionary() - { - {"goodbye", 0f}, - {"greeting", 1f}, - {"other", 2f} - }; + { + {"goodbye", 0f}, + {"greeting", 1f}, + {"other", 2f} + }; public string RAW_DATA_DIR { get; set; } = "raw_data"; public string MODEL_DIR { get; set; } = "models"; public string LABEL_FILE_NAME { get; set; } = "label.txt"; + public string WEIGHT_FILE_NAME { get; set; } = "intent-classifier.h5"; }