Merge pull request #1167 from iceljc/features/refine-model-settings
Features/refine model settings
This commit is contained in:
commit
22ce231411
11
BotSharp.sln
11
BotSharp.sln
|
|
@ -145,6 +145,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Test.RealtimeVoice
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.ChartHandler", "src\Plugins\BotSharp.Plugin.ChartHandler\BotSharp.Plugin.ChartHandler.csproj", "{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.ChartHandler", "src\Plugins\BotSharp.Plugin.ChartHandler\BotSharp.Plugin.ChartHandler.csproj", "{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.ExcelHandler", "src\Plugins\BotSharp.Plugin.ExcelHandler\BotSharp.Plugin.ExcelHandler.csproj", "{FC63C875-E880-D8BB-B8B5-978AB7B62983}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -609,6 +611,14 @@ Global
|
||||||
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}.Release|Any CPU.Build.0 = Release|Any CPU
|
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}.Release|x64.ActiveCfg = Release|Any CPU
|
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}.Release|x64.Build.0 = Release|Any CPU
|
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983}.Release|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -679,6 +689,7 @@ Global
|
||||||
{7C0C7D13-D161-4AB0-9C29-83A0F1FF990E} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
|
{7C0C7D13-D161-4AB0-9C29-83A0F1FF990E} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
|
||||||
{B067B126-88CD-4282-BEEF-7369B64423EF} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
|
{B067B126-88CD-4282-BEEF-7369B64423EF} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
|
||||||
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
||||||
|
{FC63C875-E880-D8BB-B8B5-978AB7B62983} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}
|
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ public class LlmModelSetting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ImageSetting? Image { get; set; }
|
public ImageSetting? Image { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Settings for audio
|
||||||
|
/// </summary>
|
||||||
|
public AudioSetting? Audio { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Settings for llm cost
|
/// Settings for llm cost
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -128,6 +133,20 @@ public class ImageVariationSetting
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Audio model settings
|
||||||
|
public class AudioSetting
|
||||||
|
{
|
||||||
|
public AudioTranscriptionSetting? Transcription { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AudioTranscriptionSetting
|
||||||
|
{
|
||||||
|
public float? Temperature { get; set; }
|
||||||
|
public ModelSettingBase? ResponseFormat { get; set; }
|
||||||
|
public ModelSettingBase? Granularity { get; set; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public class ModelSettingBase
|
public class ModelSettingBase
|
||||||
{
|
{
|
||||||
public string? Default { get; set; }
|
public string? Default { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
using BotSharp.Abstraction.Routing;
|
|
||||||
using BotSharp.Core.Infrastructures;
|
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.AudioHandler.Functions;
|
|
||||||
|
|
||||||
public class HandleAudioRequestFn : IFunctionCallback
|
|
||||||
{
|
|
||||||
public string Name => "util-audio-handle_audio_request";
|
|
||||||
public string Indication => "Handling audio request";
|
|
||||||
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
private readonly IFileStorageService _fileStorage;
|
|
||||||
private readonly ILogger<HandleAudioRequestFn> _logger;
|
|
||||||
private readonly BotSharpOptions _options;
|
|
||||||
|
|
||||||
private readonly IEnumerable<string> _audioContentTypes = new List<string>
|
|
||||||
{
|
|
||||||
AudioType.mp3.ToFileType(),
|
|
||||||
AudioType.wav.ToFileType(),
|
|
||||||
};
|
|
||||||
|
|
||||||
public HandleAudioRequestFn(
|
|
||||||
IFileStorageService fileStorage,
|
|
||||||
IServiceProvider serviceProvider,
|
|
||||||
ILogger<HandleAudioRequestFn> logger,
|
|
||||||
BotSharpOptions options)
|
|
||||||
{
|
|
||||||
_fileStorage = fileStorage;
|
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
_logger = logger;
|
|
||||||
_options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
|
||||||
{
|
|
||||||
var args = JsonSerializer.Deserialize<LlmContextIn>(message.FunctionArgs, _options.JsonSerializerOptions);
|
|
||||||
var conv = _serviceProvider.GetRequiredService<IConversationService>();
|
|
||||||
var routingCtx = _serviceProvider.GetRequiredService<IRoutingContext>();
|
|
||||||
|
|
||||||
var wholeDialogs = routingCtx.GetDialogs();
|
|
||||||
if (wholeDialogs.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
wholeDialogs = conv.GetDialogHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
var dialogs = AssembleFiles(conv.ConversationId, wholeDialogs);
|
|
||||||
var response = await GetResponeFromDialogs(dialogs);
|
|
||||||
message.Content = response;
|
|
||||||
dialogs.ForEach(x => x.Files = null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RoleDialogModel> AssembleFiles(string convId, List<RoleDialogModel> dialogs)
|
|
||||||
{
|
|
||||||
if (dialogs.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
return new List<RoleDialogModel>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var messageId = dialogs.Select(x => x.MessageId).Distinct().ToList();
|
|
||||||
var audioFiles = _fileStorage.GetMessageFiles(convId, messageId, options: new()
|
|
||||||
{
|
|
||||||
Sources = [FileSource.User],
|
|
||||||
ContentTypes = _audioContentTypes
|
|
||||||
});
|
|
||||||
|
|
||||||
audioFiles = audioFiles.Where(x => x.ContentType.Contains("audio")).ToList();
|
|
||||||
|
|
||||||
foreach (var dialog in dialogs)
|
|
||||||
{
|
|
||||||
var found = audioFiles.Where(x => x.MessageId == dialog.MessageId
|
|
||||||
&& x.FileSource.IsEqualTo(FileSource.User)).ToList();
|
|
||||||
|
|
||||||
if (found.IsNullOrEmpty() || !dialog.IsFromUser)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog.Files = found.Select(x => new BotSharpFile
|
|
||||||
{
|
|
||||||
ContentType = x.ContentType,
|
|
||||||
FileUrl = x.FileUrl,
|
|
||||||
FileStorageUrl = x.FileStorageUrl
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dialogs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> GetResponeFromDialogs(List<RoleDialogModel> dialogs)
|
|
||||||
{
|
|
||||||
var audioCompletion = PrepareModel();
|
|
||||||
var dialog = dialogs.Where(x => !x.Files.IsNullOrEmpty()).Last();
|
|
||||||
var transcripts = new List<string>();
|
|
||||||
|
|
||||||
foreach (var file in dialog.Files)
|
|
||||||
{
|
|
||||||
if (file == null || string.IsNullOrWhiteSpace(file.FileStorageUrl)) continue;
|
|
||||||
|
|
||||||
var extension = Path.GetExtension(file.FileStorageUrl);
|
|
||||||
|
|
||||||
var fileName = Path.GetFileName(file.FileStorageUrl);
|
|
||||||
if (!ParseAudioFileType(fileName)) continue;
|
|
||||||
|
|
||||||
var binary = _fileStorage.GetFileBytes(file.FileStorageUrl);
|
|
||||||
using var stream = binary.ToStream();
|
|
||||||
stream.Position = 0;
|
|
||||||
|
|
||||||
var result = await audioCompletion.TranscriptTextAsync(stream, fileName);
|
|
||||||
transcripts.Add(result);
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transcripts.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException($"No audio files found in the dialog. MessageId: {dialog.MessageId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Join("\r\n\r\n", transcripts);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IAudioTranscription PrepareModel()
|
|
||||||
{
|
|
||||||
return CompletionProvider.GetAudioTranscriber(_serviceProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ParseAudioFileType(string fileName)
|
|
||||||
{
|
|
||||||
var extension = Path.GetExtension(fileName).TrimStart('.').ToLower();
|
|
||||||
var provider = new FileExtensionContentTypeProvider();
|
|
||||||
bool canParse = Enum.TryParse<AudioType>(extension, out _) || provider.TryGetContentType(fileName, out _);
|
|
||||||
return canParse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
namespace BotSharp.Plugin.AudioHandler.Functions;
|
||||||
|
|
||||||
|
public class ReadAudioFn : IFunctionCallback
|
||||||
|
{
|
||||||
|
public string Name => "util-audio-handle_audio_request";
|
||||||
|
public string Indication => "Reading audio";
|
||||||
|
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly IFileStorageService _fileStorage;
|
||||||
|
private readonly ILogger<ReadAudioFn> _logger;
|
||||||
|
private readonly BotSharpOptions _options;
|
||||||
|
private readonly AudioHandlerSettings _settings;
|
||||||
|
|
||||||
|
private readonly IEnumerable<string> _audioContentTypes = new List<string>
|
||||||
|
{
|
||||||
|
AudioType.mp3.ToFileType(),
|
||||||
|
AudioType.wav.ToFileType(),
|
||||||
|
};
|
||||||
|
|
||||||
|
public ReadAudioFn(
|
||||||
|
IServiceProvider services,
|
||||||
|
ILogger<ReadAudioFn> logger,
|
||||||
|
BotSharpOptions options,
|
||||||
|
AudioHandlerSettings settings,
|
||||||
|
IFileStorageService fileStorage)
|
||||||
|
{
|
||||||
|
_services = services;
|
||||||
|
_logger = logger;
|
||||||
|
_options = options;
|
||||||
|
_settings = settings;
|
||||||
|
_fileStorage = fileStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
|
{
|
||||||
|
var args = JsonSerializer.Deserialize<LlmContextIn>(message.FunctionArgs, _options.JsonSerializerOptions);
|
||||||
|
var conv = _services.GetRequiredService<IConversationService>();
|
||||||
|
var routingCtx = _services.GetRequiredService<IRoutingContext>();
|
||||||
|
|
||||||
|
var wholeDialogs = routingCtx.GetDialogs();
|
||||||
|
if (wholeDialogs.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
wholeDialogs = conv.GetDialogHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
var dialogs = AssembleFiles(conv.ConversationId, wholeDialogs);
|
||||||
|
var response = await GetAudioTranscription(dialogs);
|
||||||
|
message.Content = response;
|
||||||
|
dialogs.ForEach(x => x.Files = null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RoleDialogModel> AssembleFiles(string convId, List<RoleDialogModel> dialogs)
|
||||||
|
{
|
||||||
|
if (dialogs.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return new List<RoleDialogModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageId = dialogs.Select(x => x.MessageId).Distinct().ToList();
|
||||||
|
var audioFiles = _fileStorage.GetMessageFiles(convId, messageId, options: new()
|
||||||
|
{
|
||||||
|
Sources = [FileSource.User],
|
||||||
|
ContentTypes = _audioContentTypes
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var dialog in dialogs)
|
||||||
|
{
|
||||||
|
var found = audioFiles.Where(x => x.MessageId == dialog.MessageId
|
||||||
|
&& x.FileSource.IsEqualTo(FileSource.User)).ToList();
|
||||||
|
|
||||||
|
if (found.IsNullOrEmpty() || !dialog.IsFromUser)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.Files = found.Select(x => new BotSharpFile
|
||||||
|
{
|
||||||
|
ContentType = x.ContentType,
|
||||||
|
FileUrl = x.FileUrl,
|
||||||
|
FileStorageUrl = x.FileStorageUrl
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return dialogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetAudioTranscription(List<RoleDialogModel> dialogs)
|
||||||
|
{
|
||||||
|
var audioCompletion = PrepareModel();
|
||||||
|
var dialog = dialogs.Where(x => !x.Files.IsNullOrEmpty()).LastOrDefault();
|
||||||
|
var transcripts = new List<string>();
|
||||||
|
|
||||||
|
if (dialog != null)
|
||||||
|
{
|
||||||
|
foreach (var file in dialog.Files)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(file?.FileStorageUrl))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = Path.GetExtension(file.FileStorageUrl);
|
||||||
|
var fileName = Path.GetFileName(file.FileStorageUrl);
|
||||||
|
if (!VerifyAudioFileType(fileName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var binary = _fileStorage.GetFileBytes(file.FileStorageUrl);
|
||||||
|
using var stream = binary.ToStream();
|
||||||
|
stream.Position = 0;
|
||||||
|
|
||||||
|
var result = await audioCompletion.TranscriptTextAsync(stream, fileName);
|
||||||
|
transcripts.Add(result);
|
||||||
|
stream.Close();
|
||||||
|
await Task.Delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (transcripts.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
var msg = "No audio is found in the chat.";
|
||||||
|
_logger.LogWarning(msg);
|
||||||
|
transcripts.Add(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join("\r\n\r\n", transcripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IAudioTranscription PrepareModel()
|
||||||
|
{
|
||||||
|
var (provider, model) = GetLlmProviderModel();
|
||||||
|
return CompletionProvider.GetAudioTranscriber(_services, provider: provider, model: model);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool VerifyAudioFileType(string fileName)
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(fileName).TrimStart('.').ToLower();
|
||||||
|
return Enum.TryParse<AudioType>(extension, out _)
|
||||||
|
|| !string.IsNullOrEmpty(FileUtility.GetFileContentType(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private (string, string) GetLlmProviderModel()
|
||||||
|
{
|
||||||
|
var state = _services.GetRequiredService<IConversationStateService>();
|
||||||
|
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
|
||||||
|
|
||||||
|
var provider = state.GetState("audio_read_llm_provider");
|
||||||
|
var model = state.GetState("audio_read_llm_provider");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(provider) && !string.IsNullOrEmpty(model))
|
||||||
|
{
|
||||||
|
return (provider, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
provider = _settings?.Audio?.Reading?.LlmProvider;
|
||||||
|
model = _settings?.Audio?.Reading?.LlmModel;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(provider) && !string.IsNullOrEmpty(model))
|
||||||
|
{
|
||||||
|
return (provider, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
provider = "openai";
|
||||||
|
model = "gpt-4o-mini-transcribe";
|
||||||
|
|
||||||
|
return (provider, model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,19 @@
|
||||||
|
using BotSharp.Abstraction.Models;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.AudioHandler.Settings;
|
namespace BotSharp.Plugin.AudioHandler.Settings;
|
||||||
|
|
||||||
public class AudioHandlerSettings
|
public class AudioHandlerSettings
|
||||||
{
|
{
|
||||||
|
public AudioSettings? Audio { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Audio
|
||||||
|
public class AudioSettings
|
||||||
|
{
|
||||||
|
public AudioReadSettings? Reading { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AudioReadSettings : LlmBase
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
@ -14,11 +14,14 @@ global using BotSharp.Abstraction.Conversations.Models;
|
||||||
global using BotSharp.Abstraction.Files;
|
global using BotSharp.Abstraction.Files;
|
||||||
global using BotSharp.Abstraction.Files.Models;
|
global using BotSharp.Abstraction.Files.Models;
|
||||||
global using BotSharp.Abstraction.Files.Enums;
|
global using BotSharp.Abstraction.Files.Enums;
|
||||||
|
global using BotSharp.Abstraction.Files.Utilities;
|
||||||
global using BotSharp.Abstraction.Functions;
|
global using BotSharp.Abstraction.Functions;
|
||||||
global using BotSharp.Abstraction.MLTasks;
|
global using BotSharp.Abstraction.MLTasks;
|
||||||
global using BotSharp.Abstraction.Options;
|
global using BotSharp.Abstraction.Options;
|
||||||
global using BotSharp.Abstraction.Plugins;
|
global using BotSharp.Abstraction.Plugins;
|
||||||
global using BotSharp.Abstraction.Utilities;
|
global using BotSharp.Abstraction.Utilities;
|
||||||
|
global using BotSharp.Abstraction.Routing;
|
||||||
|
global using BotSharp.Core.Infrastructures;
|
||||||
|
|
||||||
global using BotSharp.Plugin.AudioHandler.Enums;
|
global using BotSharp.Plugin.AudioHandler.Enums;
|
||||||
global using BotSharp.Plugin.AudioHandler.Helpers;
|
global using BotSharp.Plugin.AudioHandler.Helpers;
|
||||||
|
|
@ -26,6 +29,7 @@ global using BotSharp.Plugin.AudioHandler.Hooks;
|
||||||
global using BotSharp.Plugin.AudioHandler.Models;
|
global using BotSharp.Plugin.AudioHandler.Models;
|
||||||
global using BotSharp.Plugin.AudioHandler.LlmContexts;
|
global using BotSharp.Plugin.AudioHandler.LlmContexts;
|
||||||
global using BotSharp.Plugin.AudioHandler.Provider;
|
global using BotSharp.Plugin.AudioHandler.Provider;
|
||||||
|
global using BotSharp.Plugin.AudioHandler.Settings;
|
||||||
|
|
||||||
global using Microsoft.Extensions.Configuration;
|
global using Microsoft.Extensions.Configuration;
|
||||||
global using Microsoft.Extensions.DependencyInjection;
|
global using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
using BotSharp.Abstraction.Plugins;
|
using BotSharp.Abstraction.Plugins;
|
||||||
using BotSharp.Abstraction.Settings;
|
using BotSharp.Abstraction.Settings;
|
||||||
using BotSharp.Plugin.ExcelHandler.Helpers.MySql;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Helpers.Sqlite;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Hooks;
|
using BotSharp.Plugin.ExcelHandler.Hooks;
|
||||||
using BotSharp.Plugin.ExcelHandler.Services;
|
using BotSharp.Plugin.ExcelHandler.Services;
|
||||||
using BotSharp.Plugin.ExcelHandler.Settings;
|
using BotSharp.Plugin.ExcelHandler.Settings;
|
||||||
|
|
@ -25,9 +23,7 @@ public class ExcelHandlerPlugin : IBotSharpPlugin
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddScoped<IAgentUtilityHook, ExcelHandlerUtilityHook>();
|
services.AddScoped<IAgentUtilityHook, ExcelHandlerUtilityHook>();
|
||||||
services.AddScoped<ISqliteDbHelpers, SqliteDbHelpers>();
|
services.AddScoped<IDbService, SqliteService>();
|
||||||
services.AddScoped<IMySqlDbHelper, MySqlDbHelpers>();
|
services.AddScoped<IDbService, MySqlService>();
|
||||||
services.AddScoped<ISqliteService, SqliteService>();
|
|
||||||
services.AddScoped<IMySqlService, MySqlService>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,48 @@
|
||||||
using BotSharp.Abstraction.Files.Enums;
|
using BotSharp.Plugin.ExcelHandler.Settings;
|
||||||
using BotSharp.Abstraction.Files.Models;
|
|
||||||
using BotSharp.Abstraction.Files.Utilities;
|
|
||||||
using BotSharp.Abstraction.Routing;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Models;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Services;
|
|
||||||
using NPOI.SS.UserModel;
|
using NPOI.SS.UserModel;
|
||||||
using NPOI.XSSF.UserModel;
|
using NPOI.XSSF.UserModel;
|
||||||
using System.Linq.Dynamic.Core;
|
using System.Linq.Dynamic.Core;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Functions;
|
namespace BotSharp.Plugin.ExcelHandler.Functions;
|
||||||
|
|
||||||
public class HandleExcelRequestFn : IFunctionCallback
|
public class ReadExcelFn : IFunctionCallback
|
||||||
{
|
{
|
||||||
public string Name => "util-excel-handle_excel_request";
|
public string Name => "util-excel-handle_excel_request";
|
||||||
public string Indication => "Handling excel request";
|
public string Indication => "Reading excel";
|
||||||
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _services;
|
||||||
private readonly IFileStorageService _fileStorage;
|
private readonly IFileStorageService _fileStorage;
|
||||||
private readonly ILogger<HandleExcelRequestFn> _logger;
|
private readonly ILogger<ReadExcelFn> _logger;
|
||||||
private readonly BotSharpOptions _options;
|
private readonly BotSharpOptions _options;
|
||||||
private readonly IMySqlService _mySqlService;
|
private readonly IDbService _dbService;
|
||||||
|
private readonly ExcelHandlerSettings _settings;
|
||||||
|
|
||||||
|
private HashSet<string> _excelFileTypes;
|
||||||
|
|
||||||
private HashSet<string> _excelMimeTypes;
|
public ReadExcelFn(
|
||||||
private double _excelRowSize = 0;
|
IServiceProvider services,
|
||||||
private double _excelColumnSize = 0;
|
ILogger<ReadExcelFn> logger,
|
||||||
private string _tableName = "tempTable";
|
|
||||||
private string _currentFileName = string.Empty;
|
|
||||||
private List<string> _headerColumns = new List<string>();
|
|
||||||
private List<string> _columnTypes = new List<string>();
|
|
||||||
|
|
||||||
public HandleExcelRequestFn(
|
|
||||||
IServiceProvider serviceProvider,
|
|
||||||
IFileStorageService fileStorage,
|
|
||||||
ILogger<HandleExcelRequestFn> logger,
|
|
||||||
BotSharpOptions options,
|
BotSharpOptions options,
|
||||||
IMySqlService mySqlService
|
ExcelHandlerSettings settings,
|
||||||
)
|
IFileStorageService fileStorage,
|
||||||
|
IEnumerable<IDbService> dbServices)
|
||||||
{
|
{
|
||||||
_serviceProvider = serviceProvider;
|
_services = services;
|
||||||
_fileStorage = fileStorage;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_options = options;
|
_options = options;
|
||||||
_mySqlService = mySqlService;
|
_settings = settings;
|
||||||
|
_fileStorage = fileStorage;
|
||||||
|
_dbService = dbServices.FirstOrDefault(x => x.Provider == _settings.DbProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
var args = JsonSerializer.Deserialize<LlmContextIn>(message.FunctionArgs, _options.JsonSerializerOptions);
|
var args = JsonSerializer.Deserialize<LlmContextIn>(message.FunctionArgs, _options.JsonSerializerOptions);
|
||||||
var conv = _serviceProvider.GetRequiredService<IConversationService>();
|
var conv = _services.GetRequiredService<IConversationService>();
|
||||||
var states = _serviceProvider.GetRequiredService<IConversationStateService>();
|
var states = _services.GetRequiredService<IConversationStateService>();
|
||||||
var routingCtx = _serviceProvider.GetRequiredService<IRoutingContext>();
|
var routingCtx = _services.GetRequiredService<IRoutingContext>();
|
||||||
|
|
||||||
if (_excelMimeTypes.IsNullOrEmpty())
|
Init();
|
||||||
{
|
|
||||||
_excelMimeTypes = FileUtility.GetMimeFileTypes(new List<string> { "excel", "spreadsheet" }).ToHashSet<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var dialogs = routingCtx.GetDialogs();
|
var dialogs = routingCtx.GetDialogs();
|
||||||
if (dialogs.IsNullOrEmpty())
|
if (dialogs.IsNullOrEmpty())
|
||||||
|
|
@ -71,8 +57,8 @@ public class HandleExcelRequestFn : IFunctionCallback
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultList = GetResponeFromDialogs(dialogs);
|
var results = GetResponeFromDialogs(dialogs);
|
||||||
message.Content = GenerateSqlExecutionSummary(resultList);
|
message.Content = GenerateSqlExecutionSummary(results);
|
||||||
states.SetState("excel_import_result",message.Content);
|
states.SetState("excel_import_result",message.Content);
|
||||||
dialogs.ForEach(x => x.Files = null);
|
dialogs.ForEach(x => x.Files = null);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -80,6 +66,14 @@ public class HandleExcelRequestFn : IFunctionCallback
|
||||||
|
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
if (_excelFileTypes.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
_excelFileTypes = FileUtility.GetMimeFileTypes(["excel", "spreadsheet"]).ToHashSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool AssembleFiles(string conversationId, List<RoleDialogModel> dialogs)
|
private bool AssembleFiles(string conversationId, List<RoleDialogModel> dialogs)
|
||||||
{
|
{
|
||||||
if (dialogs.IsNullOrEmpty())
|
if (dialogs.IsNullOrEmpty())
|
||||||
|
|
@ -88,7 +82,7 @@ public class HandleExcelRequestFn : IFunctionCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
var messageIds = dialogs.Select(x => x.MessageId).Distinct().ToList();
|
var messageIds = dialogs.Select(x => x.MessageId).Distinct().ToList();
|
||||||
var contentTypes = FileUtility.GetContentFileTypes(mimeTypes: _excelMimeTypes);
|
var contentTypes = FileUtility.GetContentFileTypes(mimeTypes: _excelFileTypes);
|
||||||
var excelFiles = _fileStorage.GetMessageFiles(conversationId, messageIds, options: new()
|
var excelFiles = _fileStorage.GetMessageFiles(conversationId, messageIds, options: new()
|
||||||
{
|
{
|
||||||
Sources = [FileSource.User],
|
Sources = [FileSource.User],
|
||||||
|
|
@ -123,59 +117,61 @@ public class HandleExcelRequestFn : IFunctionCallback
|
||||||
|
|
||||||
private List<SqlContextOut> GetResponeFromDialogs(List<RoleDialogModel> dialogs)
|
private List<SqlContextOut> GetResponeFromDialogs(List<RoleDialogModel> dialogs)
|
||||||
{
|
{
|
||||||
|
var sqlCommands = new List<SqlContextOut>();
|
||||||
var dialog = dialogs.Last(x => !x.Files.IsNullOrEmpty());
|
var dialog = dialogs.Last(x => !x.Files.IsNullOrEmpty());
|
||||||
var sqlCommandList = new List<SqlContextOut>();
|
|
||||||
foreach (var file in dialog.Files)
|
foreach (var file in dialog.Files)
|
||||||
{
|
{
|
||||||
if (file == null || string.IsNullOrWhiteSpace(file.FileStorageUrl)) continue;
|
if (string.IsNullOrWhiteSpace(file?.FileStorageUrl))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
string extension = Path.GetExtension(file.FileStorageUrl);
|
string extension = Path.GetExtension(file.FileStorageUrl);
|
||||||
if (!_excelMimeTypes.Contains(extension)) continue;
|
if (!_excelFileTypes.Contains(extension))
|
||||||
|
{
|
||||||
_currentFileName = Path.GetFileName(file.FileStorageUrl);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var binary = _fileStorage.GetFileBytes(file.FileStorageUrl);
|
var binary = _fileStorage.GetFileBytes(file.FileStorageUrl);
|
||||||
var workbook = ConvertToWorkBook(binary.ToArray());
|
var workbook = ConvertToWorkBook(binary);
|
||||||
|
|
||||||
var currentCommandList = _mySqlService.WriteExcelDataToDB(workbook);
|
var currentCommands = _dbService.WriteExcelDataToDB(workbook);
|
||||||
sqlCommandList.AddRange(currentCommandList);
|
sqlCommands.AddRange(currentCommands);
|
||||||
}
|
}
|
||||||
return sqlCommandList;
|
return sqlCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateSqlExecutionSummary(List<SqlContextOut> messageList)
|
private string GenerateSqlExecutionSummary(List<SqlContextOut> results)
|
||||||
{
|
{
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
if (messageList.Any(x => x.isSuccessful))
|
if (results.Any(x => x.isSuccessful))
|
||||||
{
|
{
|
||||||
stringBuilder.Append("---Success---");
|
stringBuilder.Append("---Success---");
|
||||||
stringBuilder.Append("\r\n");
|
stringBuilder.Append("\r\n");
|
||||||
foreach (var message in messageList.Where(x => x.isSuccessful))
|
foreach (var result in results.Where(x => x.isSuccessful))
|
||||||
{
|
{
|
||||||
stringBuilder.Append(message.Message);
|
stringBuilder.Append(result.Message);
|
||||||
stringBuilder.Append("\r\n\r\n");
|
stringBuilder.Append("\r\n\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (messageList.Any(x => !x.isSuccessful))
|
if (results.Any(x => !x.isSuccessful))
|
||||||
{
|
{
|
||||||
stringBuilder.Append("---Failed---");
|
stringBuilder.Append("---Failed---");
|
||||||
stringBuilder.Append("\r\n");
|
stringBuilder.Append("\r\n");
|
||||||
foreach (var message in messageList.Where(x => !x.isSuccessful))
|
foreach (var result in results.Where(x => !x.isSuccessful))
|
||||||
{
|
{
|
||||||
stringBuilder.Append(message.Message);
|
stringBuilder.Append(result.Message);
|
||||||
stringBuilder.Append("\r\n");
|
stringBuilder.Append("\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWorkbook ConvertToWorkBook(byte[] bytes)
|
private IWorkbook ConvertToWorkBook(BinaryData binary)
|
||||||
{
|
{
|
||||||
IWorkbook workbook;
|
using var fileStream = new MemoryStream(binary.ToArray());
|
||||||
using (var fileStream = new MemoryStream(bytes))
|
IWorkbook workbook = new XSSFWorkbook(fileStream);
|
||||||
{
|
|
||||||
workbook = new XSSFWorkbook(fileStream);
|
|
||||||
}
|
|
||||||
return workbook;
|
return workbook;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Data.Sqlite;
|
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Helpers.MySql
|
|
||||||
{
|
|
||||||
public interface IMySqlDbHelper
|
|
||||||
{
|
|
||||||
MySqlConnection GetDbConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using BotSharp.Plugin.SqlDriver.Settings;
|
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Helpers.MySql
|
|
||||||
{
|
|
||||||
public class MySqlDbHelpers : IMySqlDbHelper
|
|
||||||
{
|
|
||||||
|
|
||||||
private string _mySqlDriverConnection = "";
|
|
||||||
private readonly IServiceProvider _services;
|
|
||||||
private string _databaseName;
|
|
||||||
|
|
||||||
public MySqlDbHelpers(IServiceProvider service)
|
|
||||||
{
|
|
||||||
_services = service;
|
|
||||||
}
|
|
||||||
public MySqlConnection GetDbConnection()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_mySqlDriverConnection))
|
|
||||||
{
|
|
||||||
InitializeDatabase();
|
|
||||||
}
|
|
||||||
var dbConnection = new MySqlConnection(_mySqlDriverConnection);
|
|
||||||
dbConnection.Open();
|
|
||||||
return dbConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeDatabase()
|
|
||||||
{
|
|
||||||
var settingService = _services.GetRequiredService<SqlDriverSetting>();
|
|
||||||
_mySqlDriverConnection = settingService.MySqlTempConnectionString;
|
|
||||||
_databaseName = GetDatabaseName(settingService.MySqlTempConnectionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetDatabaseName(string connectionString)
|
|
||||||
{
|
|
||||||
string pattern = @"database=([^;]+)";
|
|
||||||
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
|
|
||||||
Match match = regex.Match(connectionString);
|
|
||||||
return match.Success ? match.Groups[1].Value : string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
using Microsoft.Data.Sqlite;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Helpers.Sqlite;
|
|
||||||
|
|
||||||
public interface ISqliteDbHelpers
|
|
||||||
{
|
|
||||||
SqliteConnection GetPhysicalDbConnection();
|
|
||||||
SqliteConnection GetInMemoryDbConnection();
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
using BotSharp.Plugin.SqlDriver.Settings;
|
|
||||||
using Microsoft.Data.Sqlite;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Helpers.Sqlite;
|
|
||||||
|
|
||||||
public class SqliteDbHelpers : ISqliteDbHelpers
|
|
||||||
{
|
|
||||||
private string _dbFilePath = string.Empty;
|
|
||||||
private SqliteConnection inMemoryDbConnection = null;
|
|
||||||
|
|
||||||
private readonly IServiceProvider _services;
|
|
||||||
|
|
||||||
public SqliteDbHelpers(IServiceProvider service)
|
|
||||||
{
|
|
||||||
_services = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqliteConnection GetInMemoryDbConnection()
|
|
||||||
{
|
|
||||||
if (inMemoryDbConnection == null)
|
|
||||||
{
|
|
||||||
inMemoryDbConnection = new SqliteConnection("Data Source=:memory:;Mode=ReadWrite");
|
|
||||||
inMemoryDbConnection.Open();
|
|
||||||
return inMemoryDbConnection;
|
|
||||||
}
|
|
||||||
return inMemoryDbConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqliteConnection GetPhysicalDbConnection()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_dbFilePath))
|
|
||||||
{
|
|
||||||
var settingService = _services.GetRequiredService<SqlDriverSetting>();
|
|
||||||
_dbFilePath = settingService.SqlLiteConnectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dbConnection = new SqliteConnection($"Data Source={_dbFilePath};Mode=ReadWrite");
|
|
||||||
dbConnection.Open();
|
|
||||||
return dbConnection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Models;
|
|
||||||
using NPOI.SS.UserModel;
|
using NPOI.SS.UserModel;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Services
|
namespace BotSharp.Plugin.ExcelHandler.Services;
|
||||||
{
|
|
||||||
public interface IDbService
|
public interface IDbService
|
||||||
{
|
{
|
||||||
|
string Provider { get; }
|
||||||
|
|
||||||
IEnumerable<SqlContextOut> WriteExcelDataToDB(IWorkbook workbook);
|
IEnumerable<SqlContextOut> WriteExcelDataToDB(IWorkbook workbook);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Services;
|
|
||||||
|
|
||||||
public interface IMySqlService : IDbService
|
|
||||||
{
|
|
||||||
public bool DeleteTableSqlQuery();
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Models;
|
|
||||||
using NPOI.SS.UserModel;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Services
|
|
||||||
{
|
|
||||||
public interface ISqliteService : IDbService
|
|
||||||
{
|
|
||||||
public void DeleteTableSqlQuery();
|
|
||||||
public string GenerateTableSchema();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using BotSharp.Abstraction.Routing;
|
using System.Text.RegularExpressions;
|
||||||
using BotSharp.Plugin.ExcelHandler.Helpers.MySql;
|
using BotSharp.Plugin.SqlDriver.Settings;
|
||||||
using BotSharp.Plugin.ExcelHandler.Models;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NPOI.SS.UserModel;
|
using NPOI.SS.UserModel;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Services
|
namespace BotSharp.Plugin.ExcelHandler.Services;
|
||||||
|
|
||||||
|
public class MySqlService : IDbService
|
||||||
{
|
{
|
||||||
public class MySqlService : IMySqlService
|
|
||||||
{
|
|
||||||
private readonly IMySqlDbHelper _mySqlDbHelpers;
|
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly ILogger<MySqlService> _logger;
|
||||||
|
|
||||||
|
private string _mysqlConnection = "";
|
||||||
private double _excelRowSize = 0;
|
private double _excelRowSize = 0;
|
||||||
private double _excelColumnSize = 0;
|
private double _excelColumnSize = 0;
|
||||||
private string _tableName = "tempTable";
|
private string _tableName = "tempTable";
|
||||||
|
|
@ -21,86 +21,36 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
private List<string> _headerColumns = new List<string>();
|
private List<string> _headerColumns = new List<string>();
|
||||||
private List<string> _columnTypes = new List<string>();
|
private List<string> _columnTypes = new List<string>();
|
||||||
|
|
||||||
public MySqlService(IMySqlDbHelper mySqlDbHelpers, IServiceProvider services)
|
public MySqlService(
|
||||||
|
IServiceProvider services,
|
||||||
|
ILogger<MySqlService> logger)
|
||||||
{
|
{
|
||||||
_mySqlDbHelpers = mySqlDbHelpers;
|
|
||||||
_services = services;
|
_services = services;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DeleteTableSqlQuery()
|
public string Provider => "mysql";
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*private void ExecuteDropTableQuery(List<string> dropTableNames, MySqlConnection connection)
|
|
||||||
{
|
|
||||||
dropTableNames.ForEach(x =>
|
|
||||||
{
|
|
||||||
var dropTableQuery = $"DROP TABLE IF EXISTS {x}";
|
|
||||||
|
|
||||||
using var selectCmd = new MySqlCommand(dropTableQuery, connection);
|
|
||||||
selectCmd.ExecuteNonQuery();
|
|
||||||
});
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public List<string> GetAllTableSchema(MySqlConnection mySqlDbConnection)
|
|
||||||
{
|
|
||||||
string schemaQuery = $@"
|
|
||||||
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA
|
|
||||||
FROM INFORMATION_SCHEMA.COLUMNS
|
|
||||||
WHERE TABLE_SCHEMA = '{mySqlDbConnection.Database}';";
|
|
||||||
|
|
||||||
var tables = new List<string>();
|
|
||||||
|
|
||||||
using MySqlCommand cmd = new MySqlCommand(schemaQuery, mySqlDbConnection);
|
|
||||||
using (var reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
if (reader.HasRows)
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
string tableName = reader.GetString("TABLE_NAME");
|
|
||||||
//string columnName = reader.GetString("COLUMN_NAME");
|
|
||||||
//string dataType = reader.GetString("DATA_TYPE");
|
|
||||||
//string isNullable = reader.GetString("IS_NULLABLE");
|
|
||||||
//string columnKey = reader.GetString("COLUMN_KEY");
|
|
||||||
//string extra = reader.GetString("EXTRA");
|
|
||||||
tables.Add(tableName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tables.Distinct().ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<SqlContextOut> WriteExcelDataToDB(IWorkbook workbook)
|
public IEnumerable<SqlContextOut> WriteExcelDataToDB(IWorkbook workbook)
|
||||||
{
|
{
|
||||||
var numTables = workbook.NumberOfSheets;
|
var numTables = workbook.NumberOfSheets;
|
||||||
var commandList = new List<SqlContextOut>();
|
var results = new List<SqlContextOut>();
|
||||||
var state = _services.GetRequiredService<IConversationStateService>();
|
var state = _services.GetRequiredService<IConversationStateService>();
|
||||||
|
|
||||||
for (int sheetIdx = 0; sheetIdx < numTables; sheetIdx++)
|
for (int sheetIdx = 0; sheetIdx < numTables; sheetIdx++)
|
||||||
{
|
{
|
||||||
var commandResult = new SqlContextOut();
|
|
||||||
ISheet sheet = workbook.GetSheetAt(sheetIdx);
|
ISheet sheet = workbook.GetSheetAt(sheetIdx);
|
||||||
|
|
||||||
var (isCreateSuccess, message) = SqlCreateTableFn(sheet);
|
var (isCreateSuccess, message) = SqlCreateTableFn(sheet);
|
||||||
|
|
||||||
if (!isCreateSuccess)
|
if (!isCreateSuccess)
|
||||||
{
|
{
|
||||||
commandResult = new SqlContextOut
|
results.Add(new SqlContextOut
|
||||||
{
|
{
|
||||||
isSuccessful = isCreateSuccess,
|
isSuccessful = isCreateSuccess,
|
||||||
Message = message,
|
Message = message,
|
||||||
FileName = _currentFileName
|
FileName = _currentFileName
|
||||||
};
|
});
|
||||||
commandList.Add(commandResult);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,16 +60,17 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
var (isInsertSuccess, insertMessage) = SqlInsertDataFn(sheet);
|
var (isInsertSuccess, insertMessage) = SqlInsertDataFn(sheet);
|
||||||
string exampleData = GetInsertExample(table);
|
string exampleData = GetInsertExample(table);
|
||||||
|
|
||||||
commandResult = new SqlContextOut
|
results.Add(new SqlContextOut
|
||||||
{
|
{
|
||||||
isSuccessful = isInsertSuccess,
|
isSuccessful = isInsertSuccess,
|
||||||
Message = $"{insertMessage}\r\nExample Data: {exampleData}. \r\n The remaining data contains different values. ",
|
Message = $"{insertMessage}\r\nExample Data: {exampleData}. \r\n The remaining data contains different values. ",
|
||||||
FileName = _currentFileName
|
FileName = _currentFileName
|
||||||
};
|
});
|
||||||
commandList.Add(commandResult);
|
|
||||||
}
|
}
|
||||||
return commandList;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Private methods
|
||||||
private string ProcessInsertSqlQuery(string dataSql)
|
private string ProcessInsertSqlQuery(string dataSql)
|
||||||
{
|
{
|
||||||
var wrapUpCols = _headerColumns.Select(x => $"`{x}`").ToList();
|
var wrapUpCols = _headerColumns.Select(x => $"`{x}`").ToList();
|
||||||
|
|
@ -127,6 +78,7 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
string insertSqlQuery = $"Insert into {_tableName} {transferedCols} Values {dataSql}";
|
string insertSqlQuery = $"Insert into {_tableName} {transferedCols} Values {dataSql}";
|
||||||
return insertSqlQuery;
|
return insertSqlQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
private (bool, string) SqlInsertDataFn(ISheet sheet)
|
private (bool, string) SqlInsertDataFn(ISheet sheet)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -142,6 +94,7 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
return (false, $"{_currentFileName}: Failed to parse excel data into `{_database}`.`{_tableName}` table. ####Error: {ex.Message}");
|
return (false, $"{_currentFileName}: Failed to parse excel data into `{_database}`.`{_tableName}` table. ####Error: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ParseSheetData(ISheet singleSheet)
|
private string ParseSheetData(ISheet singleSheet)
|
||||||
{
|
{
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
|
|
@ -190,8 +143,8 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var routing = _services.GetRequiredService<IRoutingContext>();
|
var conv = _services.GetRequiredService<IConversationService>();
|
||||||
_tableName = $"excel_{routing.ConversationId.Split('-').Last()}_{sheet.SheetName}";
|
_tableName = $"excel_{conv.ConversationId.Split('-').Last()}_{sheet.SheetName}";
|
||||||
_headerColumns = ParseSheetColumn(sheet);
|
_headerColumns = ParseSheetColumn(sheet);
|
||||||
string createTableSql = CreateDBTableSqlString(_tableName, _headerColumns, null ,true);
|
string createTableSql = CreateDBTableSqlString(_tableName, _headerColumns, null ,true);
|
||||||
ExecuteSqlQueryForInsertion(createTableSql);
|
ExecuteSqlQueryForInsertion(createTableSql);
|
||||||
|
|
@ -215,6 +168,7 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
_excelColumnSize = headerColumn.Count;
|
_excelColumnSize = headerColumn.Count;
|
||||||
return headerColumn;
|
return headerColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateDBTableSqlString(string tableName, List<string> headerColumns, List<string>? columnTypes = null, bool isMemory = false)
|
private string CreateDBTableSqlString(string tableName, List<string> headerColumns, List<string>? columnTypes = null, bool isMemory = false)
|
||||||
{
|
{
|
||||||
_columnTypes = columnTypes.IsNullOrEmpty() ? headerColumns.Select(x => "VARCHAR(128)").ToList() : columnTypes;
|
_columnTypes = columnTypes.IsNullOrEmpty() ? headerColumns.Select(x => "VARCHAR(128)").ToList() : columnTypes;
|
||||||
|
|
@ -233,18 +187,19 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
return createTableSql;
|
return createTableSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteSqlQueryForInsertion(string sqlQuery)
|
private void ExecuteSqlQueryForInsertion(string sqlQuery)
|
||||||
{
|
{
|
||||||
using var connection = _mySqlDbHelpers.GetDbConnection();
|
using var connection = GetDbConnection();
|
||||||
_database = connection.Database;
|
_database = connection.Database;
|
||||||
using (MySqlCommand cmd = new MySqlCommand(sqlQuery, connection))
|
using (MySqlCommand cmd = new MySqlCommand(sqlQuery, connection))
|
||||||
{
|
{
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetInsertExample(string tableName)
|
private string GetInsertExample(string tableName)
|
||||||
{
|
{
|
||||||
using var connection = _mySqlDbHelpers.GetDbConnection();
|
using var connection = GetDbConnection();
|
||||||
_database = connection.Database;
|
_database = connection.Database;
|
||||||
var sqlQuery = $"SELECT * FROM {tableName} LIMIT 2;";
|
var sqlQuery = $"SELECT * FROM {tableName} LIMIT 2;";
|
||||||
using var cmd = new MySqlCommand(sqlQuery, connection);
|
using var cmd = new MySqlCommand(sqlQuery, connection);
|
||||||
|
|
@ -255,5 +210,58 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
|
|
||||||
return JsonConvert.SerializeObject(dataExample);
|
return JsonConvert.SerializeObject(dataExample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<string> GetAllTableSchema(MySqlConnection mySqlDbConnection)
|
||||||
|
{
|
||||||
|
string schemaQuery = $@"
|
||||||
|
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = '{mySqlDbConnection.Database}';";
|
||||||
|
|
||||||
|
var tables = new List<string>();
|
||||||
|
|
||||||
|
using MySqlCommand cmd = new MySqlCommand(schemaQuery, mySqlDbConnection);
|
||||||
|
using (var reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
if (reader.HasRows)
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
string tableName = reader.GetString("TABLE_NAME");
|
||||||
|
tables.Add(tableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return tables.Distinct().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Db connection
|
||||||
|
private MySqlConnection GetDbConnection()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_mysqlConnection))
|
||||||
|
{
|
||||||
|
InitializeDatabase();
|
||||||
|
}
|
||||||
|
var dbConnection = new MySqlConnection(_mysqlConnection);
|
||||||
|
dbConnection.Open();
|
||||||
|
return dbConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeDatabase()
|
||||||
|
{
|
||||||
|
var sqlSettings = _services.GetRequiredService<SqlDriverSetting>();
|
||||||
|
_mysqlConnection = sqlSettings.MySqlTempConnectionString;
|
||||||
|
var databaseName = GetDatabaseName(_mysqlConnection);
|
||||||
|
_logger.LogInformation($"Connected to MySQL database {databaseName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetDatabaseName(string connectionString)
|
||||||
|
{
|
||||||
|
string pattern = @"database=([^;]+)";
|
||||||
|
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
|
||||||
|
Match match = regex.Match(connectionString);
|
||||||
|
return match.Success ? match.Groups[1].Value : string.Empty;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
using System;
|
using BotSharp.Plugin.SqlDriver.Settings;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Helpers.Sqlite;
|
|
||||||
using BotSharp.Plugin.ExcelHandler.Models;
|
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using NPOI.SS.UserModel;
|
using NPOI.SS.UserModel;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Services
|
namespace BotSharp.Plugin.ExcelHandler.Services;
|
||||||
{
|
|
||||||
public class SqliteService : ISqliteService
|
|
||||||
{
|
|
||||||
private readonly ISqliteDbHelpers _sqliteDbHelpers;
|
|
||||||
|
|
||||||
|
public class SqliteService : IDbService
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly ILogger<SqliteService> _logger;
|
||||||
|
|
||||||
|
private string _dbFilePath = string.Empty;
|
||||||
|
private SqliteConnection _inMemoryDbConnection = null;
|
||||||
private double _excelRowSize = 0;
|
private double _excelRowSize = 0;
|
||||||
private double _excelColumnSize = 0;
|
private double _excelColumnSize = 0;
|
||||||
private string _tableName = "tempTable";
|
private string _tableName = "tempTable";
|
||||||
|
|
@ -21,95 +18,49 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
private List<string> _headerColumns = new List<string>();
|
private List<string> _headerColumns = new List<string>();
|
||||||
private List<string> _columnTypes = new List<string>();
|
private List<string> _columnTypes = new List<string>();
|
||||||
|
|
||||||
public SqliteService(ISqliteDbHelpers sqliteDbHelpers)
|
public SqliteService(
|
||||||
|
IServiceProvider services,
|
||||||
|
ILogger<SqliteService> logger)
|
||||||
{
|
{
|
||||||
_sqliteDbHelpers = sqliteDbHelpers;
|
_services = services;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Provider => "sqlite";
|
||||||
|
|
||||||
public IEnumerable<SqlContextOut> WriteExcelDataToDB(IWorkbook workbook)
|
public IEnumerable<SqlContextOut> WriteExcelDataToDB(IWorkbook workbook)
|
||||||
{
|
|
||||||
{
|
{
|
||||||
var numTables = workbook.NumberOfSheets;
|
var numTables = workbook.NumberOfSheets;
|
||||||
var commandList = new List<SqlContextOut>();
|
var results = new List<SqlContextOut>();
|
||||||
|
|
||||||
for (int sheetIdx = 0; sheetIdx < numTables; sheetIdx++)
|
for (int sheetIdx = 0; sheetIdx < numTables; sheetIdx++)
|
||||||
{
|
{
|
||||||
var commandResult = new SqlContextOut();
|
|
||||||
ISheet sheet = workbook.GetSheetAt(sheetIdx);
|
ISheet sheet = workbook.GetSheetAt(sheetIdx);
|
||||||
var (isCreateSuccess, message) = SqlCreateTableFn(sheet);
|
var (isCreateSuccess, message) = SqlCreateTableFn(sheet);
|
||||||
|
|
||||||
if (!isCreateSuccess)
|
if (!isCreateSuccess)
|
||||||
{
|
{
|
||||||
commandResult = new SqlContextOut
|
results.Add(new SqlContextOut
|
||||||
{
|
{
|
||||||
isSuccessful = isCreateSuccess,
|
isSuccessful = isCreateSuccess,
|
||||||
Message = message,
|
Message = message,
|
||||||
FileName = _currentFileName
|
FileName = _currentFileName
|
||||||
};
|
});
|
||||||
commandList.Add(commandResult);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var (isInsertSuccess, insertMessage) = SqlInsertDataFn(sheet);
|
var (isInsertSuccess, insertMessage) = SqlInsertDataFn(sheet);
|
||||||
commandResult = new SqlContextOut
|
results.Add(new SqlContextOut
|
||||||
{
|
{
|
||||||
isSuccessful = isInsertSuccess,
|
isSuccessful = isInsertSuccess,
|
||||||
Message = insertMessage,
|
Message = insertMessage,
|
||||||
FileName = _currentFileName
|
FileName = _currentFileName
|
||||||
};
|
|
||||||
commandList.Add(commandResult);
|
|
||||||
}
|
|
||||||
return commandList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void DeleteTableSqlQuery()
|
|
||||||
{
|
|
||||||
string deleteTableSql = @"
|
|
||||||
SELECT
|
|
||||||
name
|
|
||||||
FROM
|
|
||||||
sqlite_schema
|
|
||||||
WHERE
|
|
||||||
type = 'table' AND
|
|
||||||
name NOT LIKE 'sqlite_%'
|
|
||||||
";
|
|
||||||
var physicalDbConnection = _sqliteDbHelpers.GetPhysicalDbConnection();
|
|
||||||
using var selectCmd = new SqliteCommand(deleteTableSql, physicalDbConnection);
|
|
||||||
using var reader = selectCmd.ExecuteReader();
|
|
||||||
if (reader.HasRows)
|
|
||||||
{
|
|
||||||
var dropTableQueries = new List<string>();
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
string tableName = reader.GetString(0);
|
|
||||||
var dropTableSql = $"DROP TABLE IF EXISTS '{tableName}'";
|
|
||||||
dropTableQueries.Add(dropTableSql);
|
|
||||||
}
|
|
||||||
dropTableQueries.ForEach(query =>
|
|
||||||
{
|
|
||||||
using var dropTableCommand = new SqliteCommand(query, physicalDbConnection);
|
|
||||||
dropTableCommand.ExecuteNonQuery();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
physicalDbConnection.Close();
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GenerateTableSchema()
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append($"\nTable Schema for `{_tableName}`:");
|
|
||||||
sb.Append("\n");
|
|
||||||
sb.Append($"cid | name | type ");
|
|
||||||
sb.Append("\n");
|
|
||||||
//sb.Append("----|------------|------------");
|
|
||||||
for (int i = 0; i < _excelColumnSize; i++)
|
|
||||||
{
|
|
||||||
sb.Append($"{i,-4} | {_headerColumns[i],-10} | {_columnTypes[i],-10}");
|
|
||||||
sb.Append("\n");
|
|
||||||
}
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region private methods
|
#region Private methods
|
||||||
private (bool, string) SqlInsertDataFn(ISheet sheet)
|
private (bool, string) SqlInsertDataFn(ISheet sheet)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -219,8 +170,8 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
|
|
||||||
private void ExecuteSqlQueryForInsertion(string query)
|
private void ExecuteSqlQueryForInsertion(string query)
|
||||||
{
|
{
|
||||||
var physicalDbConnection = _sqliteDbHelpers.GetPhysicalDbConnection();
|
var physicalDbConnection = GetPhysicalDbConnection();
|
||||||
var inMemoryDbConnection = _sqliteDbHelpers.GetInMemoryDbConnection();
|
var inMemoryDbConnection = GetInMemoryDbConnection();
|
||||||
|
|
||||||
physicalDbConnection.BackupDatabase(inMemoryDbConnection, "main", "main");
|
physicalDbConnection.BackupDatabase(inMemoryDbConnection, "main", "main");
|
||||||
physicalDbConnection.Close();
|
physicalDbConnection.Close();
|
||||||
|
|
@ -233,6 +184,80 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
||||||
}
|
}
|
||||||
inMemoryDbConnection.BackupDatabase(physicalDbConnection);
|
inMemoryDbConnection.BackupDatabase(physicalDbConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DeleteTableSqlQuery()
|
||||||
|
{
|
||||||
|
string deleteTableSql = @"
|
||||||
|
SELECT
|
||||||
|
name
|
||||||
|
FROM
|
||||||
|
sqlite_schema
|
||||||
|
WHERE
|
||||||
|
type = 'table' AND
|
||||||
|
name NOT LIKE 'sqlite_%'
|
||||||
|
";
|
||||||
|
var physicalDbConnection = GetPhysicalDbConnection();
|
||||||
|
using var selectCmd = new SqliteCommand(deleteTableSql, physicalDbConnection);
|
||||||
|
using var reader = selectCmd.ExecuteReader();
|
||||||
|
if (reader.HasRows)
|
||||||
|
{
|
||||||
|
var dropTableQueries = new List<string>();
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
string tableName = reader.GetString(0);
|
||||||
|
var dropTableSql = $"DROP TABLE IF EXISTS '{tableName}'";
|
||||||
|
dropTableQueries.Add(dropTableSql);
|
||||||
|
}
|
||||||
|
dropTableQueries.ForEach(query =>
|
||||||
|
{
|
||||||
|
using var dropTableCommand = new SqliteCommand(query, physicalDbConnection);
|
||||||
|
dropTableCommand.ExecuteNonQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
physicalDbConnection.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateTableSchema()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append($"\nTable Schema for `{_tableName}`:");
|
||||||
|
sb.Append("\n");
|
||||||
|
sb.Append($"cid | name | type ");
|
||||||
|
sb.Append("\n");
|
||||||
|
//sb.Append("----|------------|------------");
|
||||||
|
for (int i = 0; i < _excelColumnSize; i++)
|
||||||
|
{
|
||||||
|
sb.Append($"{i,-4} | {_headerColumns[i],-10} | {_columnTypes[i],-10}");
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Db connection
|
||||||
|
private SqliteConnection GetInMemoryDbConnection()
|
||||||
|
{
|
||||||
|
if (_inMemoryDbConnection == null)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Init in-memory Sqlite database connection");
|
||||||
|
|
||||||
|
_inMemoryDbConnection = new SqliteConnection("Data Source=:memory:;Mode=ReadWrite");
|
||||||
|
_inMemoryDbConnection.Open();
|
||||||
|
}
|
||||||
|
return _inMemoryDbConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqliteConnection GetPhysicalDbConnection()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_dbFilePath))
|
||||||
|
{
|
||||||
|
var sqlSettings = _services.GetRequiredService<SqlDriverSetting>();
|
||||||
|
_dbFilePath = sqlSettings.SqlLiteConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbConnection = new SqliteConnection($"Data Source={_dbFilePath};Mode=ReadWrite");
|
||||||
|
dbConnection.Open();
|
||||||
|
return dbConnection;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ExcelHandler.Settings;
|
namespace BotSharp.Plugin.ExcelHandler.Settings;
|
||||||
|
|
||||||
public class ExcelHandlerSettings
|
public class ExcelHandlerSettings
|
||||||
{
|
{
|
||||||
|
public string DbProvider { get; set; } = "mysql";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ global using BotSharp.Abstraction.Agents;
|
||||||
global using BotSharp.Abstraction.Conversations;
|
global using BotSharp.Abstraction.Conversations;
|
||||||
global using BotSharp.Abstraction.Conversations.Models;
|
global using BotSharp.Abstraction.Conversations.Models;
|
||||||
global using BotSharp.Abstraction.Files;
|
global using BotSharp.Abstraction.Files;
|
||||||
|
global using BotSharp.Abstraction.Files.Enums;
|
||||||
|
global using BotSharp.Abstraction.Files.Models;
|
||||||
|
global using BotSharp.Abstraction.Files.Utilities;
|
||||||
global using BotSharp.Abstraction.Functions;
|
global using BotSharp.Abstraction.Functions;
|
||||||
global using BotSharp.Abstraction.Options;
|
global using BotSharp.Abstraction.Options;
|
||||||
global using BotSharp.Abstraction.Agents.Enums;
|
global using BotSharp.Abstraction.Agents.Enums;
|
||||||
|
|
@ -17,9 +20,12 @@ global using BotSharp.Abstraction.Agents.Settings;
|
||||||
global using BotSharp.Abstraction.Functions.Models;
|
global using BotSharp.Abstraction.Functions.Models;
|
||||||
global using BotSharp.Abstraction.Repositories;
|
global using BotSharp.Abstraction.Repositories;
|
||||||
global using BotSharp.Abstraction.Utilities;
|
global using BotSharp.Abstraction.Utilities;
|
||||||
|
global using BotSharp.Abstraction.Routing;
|
||||||
|
|
||||||
global using BotSharp.Plugin.ExcelHandler.Enums;
|
global using BotSharp.Plugin.ExcelHandler.Enums;
|
||||||
global using BotSharp.Plugin.ExcelHandler.LlmContexts;
|
global using BotSharp.Plugin.ExcelHandler.LlmContexts;
|
||||||
|
global using BotSharp.Plugin.ExcelHandler.Models;
|
||||||
|
global using BotSharp.Plugin.ExcelHandler.Services;
|
||||||
|
|
||||||
global using Microsoft.Extensions.Logging;
|
global using Microsoft.Extensions.Logging;
|
||||||
global using Microsoft.Extensions.DependencyInjection;
|
global using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ public class ImageSettings
|
||||||
public ImageReadSettings? Reading { get; set; }
|
public ImageReadSettings? Reading { get; set; }
|
||||||
public ImageGenerationSettings? Generation { get; set; }
|
public ImageGenerationSettings? Generation { get; set; }
|
||||||
public ImageEditSettings? Edit { get; set; }
|
public ImageEditSettings? Edit { get; set; }
|
||||||
public ImageVariationSettings? Variation { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImageReadSettings : LlmBase
|
public class ImageReadSettings : LlmBase
|
||||||
|
|
@ -31,11 +30,6 @@ public class ImageEditSettings : LlmBase
|
||||||
{
|
{
|
||||||
public SettingBase? ImageConverter { get; set; }
|
public SettingBase? ImageConverter { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImageVariationSettings : LlmBase
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Pdf
|
#region Pdf
|
||||||
|
|
|
||||||
|
|
@ -33,25 +33,47 @@ public class AudioTranscriptionProvider : IAudioTranscription
|
||||||
|
|
||||||
private AudioTranscriptionOptions PrepareTranscriptionOptions(string? text)
|
private AudioTranscriptionOptions PrepareTranscriptionOptions(string? text)
|
||||||
{
|
{
|
||||||
|
var settingsService = _services.GetRequiredService<ILlmProviderService>();
|
||||||
var state = _services.GetRequiredService<IConversationStateService>();
|
var state = _services.GetRequiredService<IConversationStateService>();
|
||||||
var format = GetTranscriptionResponseFormat(state.GetState("audio_response_format"));
|
|
||||||
var granularity = GetGranularity(state.GetState("audio_granularity"));
|
var settings = settingsService.GetSetting(Provider, _model)?.Audio?.Transcription;
|
||||||
var temperature = GetTemperature(state.GetState("audio_temperature"));
|
|
||||||
|
var temperature = state.GetState("audio_temperature");
|
||||||
|
var responseFormat = state.GetState("audio_response_format");
|
||||||
|
var granularity = state.GetState("audio_granularity");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(temperature) && settings?.Temperature != null)
|
||||||
|
{
|
||||||
|
temperature = $"{settings.Temperature}";
|
||||||
|
}
|
||||||
|
|
||||||
|
responseFormat = settings?.ResponseFormat != null ? VerifyTranscriptionParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
|
||||||
|
granularity = settings?.Granularity != null ? VerifyTranscriptionParameter(granularity, settings.Granularity.Default, settings.Granularity.Options) : null;
|
||||||
|
|
||||||
var options = new AudioTranscriptionOptions
|
var options = new AudioTranscriptionOptions
|
||||||
{
|
{
|
||||||
ResponseFormat = format,
|
|
||||||
TimestampGranularities = granularity,
|
|
||||||
Temperature = temperature,
|
|
||||||
Prompt = text
|
Prompt = text
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(temperature))
|
||||||
|
{
|
||||||
|
options.Temperature = GetTemperature(temperature);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(responseFormat))
|
||||||
|
{
|
||||||
|
options.ResponseFormat = GetTranscriptionResponseFormat(responseFormat);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(granularity))
|
||||||
|
{
|
||||||
|
options.TimestampGranularities = GetGranularity(granularity);
|
||||||
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AudioTranscriptionFormat GetTranscriptionResponseFormat(string input)
|
private AudioTranscriptionFormat GetTranscriptionResponseFormat(string input)
|
||||||
{
|
{
|
||||||
var value = !string.IsNullOrEmpty(input) ? input : "verbose";
|
var value = !string.IsNullOrEmpty(input) ? input : "json";
|
||||||
|
|
||||||
AudioTranscriptionFormat format;
|
AudioTranscriptionFormat format;
|
||||||
switch (value)
|
switch (value)
|
||||||
|
|
@ -109,4 +131,14 @@ public class AudioTranscriptionProvider : IAudioTranscription
|
||||||
|
|
||||||
return temperature;
|
return temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? VerifyTranscriptionParameter(string? curVal, string? defaultVal, IEnumerable<string>? options = null)
|
||||||
|
{
|
||||||
|
if (options.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return curVal.IfNullOrEmptyAs(defaultVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.Contains(curVal) ? curVal : defaultVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
|
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
|
||||||
<ProjectReference Include="..\BotSharp.ServiceDefaults\BotSharp.ServiceDefaults.csproj" />
|
<ProjectReference Include="..\BotSharp.ServiceDefaults\BotSharp.ServiceDefaults.csproj" />
|
||||||
|
<ProjectReference Include="..\Plugins\BotSharp.Plugin.ExcelHandler\BotSharp.Plugin.ExcelHandler.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
||||||
|
|
|
||||||
|
|
@ -319,20 +319,6 @@
|
||||||
"Driver": "Playwright"
|
"Driver": "Playwright"
|
||||||
},
|
},
|
||||||
|
|
||||||
"HttpHandler": {
|
|
||||||
"BaseAddress": "",
|
|
||||||
"Origin": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
"ChartHandler": {
|
|
||||||
"ChartPlot": {
|
|
||||||
"LlmProvider": "openai",
|
|
||||||
"LlmModel": "gpt-5",
|
|
||||||
"MaxOutputTokens": 8192,
|
|
||||||
"ReasoningEffortLevel": "minimal"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"SqlDriver": {
|
"SqlDriver": {
|
||||||
"MySqlConnectionString": "",
|
"MySqlConnectionString": "",
|
||||||
"SqlServerConnectionString": "",
|
"SqlServerConnectionString": "",
|
||||||
|
|
@ -461,10 +447,6 @@
|
||||||
"ImageConverter": {
|
"ImageConverter": {
|
||||||
"Provider": "file-handler"
|
"Provider": "file-handler"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"Variation": {
|
|
||||||
"LlmProvider": "",
|
|
||||||
"LlmModel": ""
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Pdf": {
|
"Pdf": {
|
||||||
|
|
@ -480,6 +462,33 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"AudioHandler": {
|
||||||
|
"Audio": {
|
||||||
|
"Reading": {
|
||||||
|
"LlmProvider": "openai",
|
||||||
|
"LlmModel": "gpt-4o-mini-transcribe"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"ExcelHandler": {
|
||||||
|
"DbProvider": "mysql"
|
||||||
|
},
|
||||||
|
|
||||||
|
"HttpHandler": {
|
||||||
|
"BaseAddress": "",
|
||||||
|
"Origin": ""
|
||||||
|
},
|
||||||
|
|
||||||
|
"ChartHandler": {
|
||||||
|
"ChartPlot": {
|
||||||
|
"LlmProvider": "openai",
|
||||||
|
"LlmModel": "gpt-5",
|
||||||
|
"MaxOutputTokens": 8192,
|
||||||
|
"ReasoningEffortLevel": "minimal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"TencentCos": {
|
"TencentCos": {
|
||||||
"AppId": "",
|
"AppId": "",
|
||||||
"SecretId": "",
|
"SecretId": "",
|
||||||
|
|
@ -591,6 +600,8 @@
|
||||||
"BotSharp.Plugin.EmailHandler",
|
"BotSharp.Plugin.EmailHandler",
|
||||||
"BotSharp.Plugin.AudioHandler",
|
"BotSharp.Plugin.AudioHandler",
|
||||||
"BotSharp.Plugin.ChartHandler",
|
"BotSharp.Plugin.ChartHandler",
|
||||||
|
"BotSharp.Plugin.AudioHandler",
|
||||||
|
"BotSharp.Plugin.ExcelHandler",
|
||||||
"BotSharp.Plugin.SqlDriver",
|
"BotSharp.Plugin.SqlDriver",
|
||||||
"BotSharp.Plugin.TencentCos"
|
"BotSharp.Plugin.TencentCos"
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue