From 8628b34ecdd0d393e7dbbd52ba0942c543631ff5 Mon Sep 17 00:00:00 2001 From: Wenbo Cao <104199@smsassist.com> Date: Sat, 17 Aug 2024 18:34:31 -0500 Subject: [PATCH] Chang load local model logic --- .../MLTasks/ISpeechToText.cs | 2 +- .../Controllers/AudioController.cs | 5 +- .../Provider/NativeWhisperProvider.cs | 73 +++++++++++++------ .../Providers/Audio/SpeechToTextProvider.cs | 7 +- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/ISpeechToText.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/ISpeechToText.cs index 9544118f..9e0dd574 100644 --- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/ISpeechToText.cs +++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/ISpeechToText.cs @@ -6,5 +6,5 @@ public interface ISpeechToText Task GenerateTextFromAudioAsync(string filePath); // Task AudioToTextTranscript(Stream stream); - void SetModelName(string modelType); + Task SetModelName(string modelType); } diff --git a/src/Plugins/BotSharp.Plugin.AudioHandler/Controllers/AudioController.cs b/src/Plugins/BotSharp.Plugin.AudioHandler/Controllers/AudioController.cs index ae5f785e..45f4c8a4 100644 --- a/src/Plugins/BotSharp.Plugin.AudioHandler/Controllers/AudioController.cs +++ b/src/Plugins/BotSharp.Plugin.AudioHandler/Controllers/AudioController.cs @@ -32,10 +32,7 @@ namespace BotSharp.Plugin.AudioHandler.Controllers Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); #endif - if (!string.IsNullOrEmpty(audioInputString)) - { - _nativeWhisperProvider.SetModelName(modelType); - } + await _nativeWhisperProvider.SetModelName(modelType); var result = await _nativeWhisperProvider.GenerateTextFromAudioAsync(audioInputString); #if DEBUG diff --git a/src/Plugins/BotSharp.Plugin.AudioHandler/Provider/NativeWhisperProvider.cs b/src/Plugins/BotSharp.Plugin.AudioHandler/Provider/NativeWhisperProvider.cs index 48fa0fed..df995207 100644 --- a/src/Plugins/BotSharp.Plugin.AudioHandler/Provider/NativeWhisperProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AudioHandler/Provider/NativeWhisperProvider.cs @@ -14,8 +14,10 @@ public class NativeWhisperProvider : ISpeechToText private static WhisperProcessor _processor; private readonly ILogger _logger; - private string _modelName; - private GgmlType _modelType = GgmlType.Tiny; + private string MODEL_DIR = "model"; + private string? _currentModelPath; + private Dictionary _modelPathDict = new Dictionary(); + private GgmlType? _modelType; public NativeWhisperProvider( IAudioProcessUtilities audioProcessUtilities, @@ -32,8 +34,7 @@ public class NativeWhisperProvider : ISpeechToText { throw new Exception($"Unsupported audio type: {fileExtension}"); } - await InitModel(); - // var _streamHandler = _audioHandlerFactory.CreateAudioHandler(audioType); + using var stream = _audioProcessUtilities.ConvertToStream(filePath); if (stream == null) @@ -48,6 +49,8 @@ public class NativeWhisperProvider : ISpeechToText textResult.Add(result); } + _processor.Dispose(); + var audioOutput = new AudioOutput { Segments = textResult @@ -58,14 +61,38 @@ public class NativeWhisperProvider : ISpeechToText { try { - _modelName = $"ggml-{modelType}.bin"; + if (!Directory.Exists(MODEL_DIR)) + Directory.CreateDirectory(MODEL_DIR); - if (!File.Exists(_modelName)) + var availableModelPaths = Directory.GetFiles(MODEL_DIR, "*.bin") + .ToArray(); + + if (!availableModelPaths.Any()) { - using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(GgmlType.TinyEn); - using var fileWriter = File.OpenWrite(_modelName); - await modelStream.CopyToAsync(fileWriter); + _currentModelPath = SetModelPath(MODEL_DIR, modelType); + await DownloadModel(modelType, _currentModelPath); } + else + { + var modelFilePath = availableModelPaths.FirstOrDefault(x => Path.GetFileName(x) == $"ggml-{modelType}.bin"); + if (modelFilePath == null) + { + _currentModelPath = SetModelPath(MODEL_DIR, modelType); + await DownloadModel(modelType, _currentModelPath); + } + else + { + _currentModelPath = modelFilePath; + } + } + + _processor = WhisperFactory + .FromPath(path: _currentModelPath) + .CreateBuilder() + .WithLanguage("auto") + .Build(); + + _modelType = modelType; } catch (Exception ex) { @@ -73,26 +100,28 @@ public class NativeWhisperProvider : ISpeechToText } } - private async Task InitModel(GgmlType modelType = GgmlType.TinyEn) + private async Task DownloadModel(GgmlType modelType, string modelDir) { - if (_processor == null) - { - await LoadWhisperModel(modelType); - _processor = WhisperFactory - .FromPath(_modelName) - .CreateBuilder() - .WithLanguage("auto") - .Build(); - } + using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(modelType); + using var fileWriter = File.OpenWrite(modelDir); + await modelStream.CopyToAsync(fileWriter); } - public void SetModelName(string modelType) + private string SetModelPath(string rootPath, GgmlType modelType) + { + string currentModelPath = Path.Combine(rootPath, $"ggml-{modelType}.bin"); + return currentModelPath; + } + + public async Task SetModelName(string modelType) { if (Enum.TryParse(modelType, true, out GgmlType ggmlType)) { - _modelType = ggmlType; + await LoadWhisperModel(ggmlType); return; } - _logger.LogWarning($"Unsupported model type: {modelType}"); + + _logger.LogWarning($"Unsupported model type: {modelType}. Use Tiny model instead!"); + await LoadWhisperModel(GgmlType.Tiny); } } diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Audio/SpeechToTextProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Audio/SpeechToTextProvider.cs index af4b5523..2314b431 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Audio/SpeechToTextProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Audio/SpeechToTextProvider.cs @@ -27,12 +27,9 @@ public class SpeechToTextProvider : ISpeechToText return transcription.Value.Text; } - public void SetModelName(string modelName) + public async Task SetModelName(string modelName) { - if (string.IsNullOrEmpty(_modelName)) - { - _modelName = modelName; - } + _modelName = modelName; } public void SetOptions(AudioTranscriptionOptions? options = null)