From 0469b27a974e7bd081351add1334193706082d19 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Wed, 28 May 2025 11:57:25 -0500 Subject: [PATCH] refine form data --- .../Services/ConversationStateService.cs | 6 +- .../Instruct/FileInstructService.Audio.cs | 3 +- .../Instruct/FileInstructService.Image.cs | 8 +- .../Controllers/InstructModeController.cs | 147 ++++++++++-------- .../Instructs/Request/InstructBaseRequest.cs | 3 +- .../Instructs/Request/InstructState.cs | 7 + 6 files changed, 98 insertions(+), 76 deletions(-) create mode 100644 src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructState.cs diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index e4d8f16d..c8665179 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -145,11 +145,7 @@ public class ConversationStateService : IConversationStateService newPair.Values = new List { newValue }; _curStates[name] = newPair; } - else if (isNoChange) - { - // do nothing - } - else + else if (!isNoChange) { _curStates[name].Values.Add(newValue); } diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs index 130baa19..a332028e 100644 --- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs +++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Instructs.Models; -using System.IO; namespace BotSharp.Core.Files.Services; @@ -18,7 +17,7 @@ public partial class FileInstructService using var stream = audioBinary.ToStream(); stream.Position = 0; - var fileName = $"{audio.FileName ?? "audio"}.{audio.FileExtension ?? "wav"}"; + var fileName = $"{audio.FileName.IfNullOrEmptyAs("audio")}.{audio.FileExtension.IfNullOrEmptyAs("wav")}"; var content = await completion.TranscriptTextAsync(stream, fileName, text ?? string.Empty); stream.Close(); return content; diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs index 5d8deaa2..e1b15d81 100644 --- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs +++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs @@ -82,7 +82,7 @@ public partial class FileInstructService using var stream = binary.ToStream(); stream.Position = 0; - var fileName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}"; + var fileName = $"{image.FileName.IfNullOrEmptyAs("image")}.{image.FileExtension.IfNullOrEmptyAs("png")}"; var message = await completion.GetImageVariation(new Agent() { Id = innerAgentId @@ -118,7 +118,7 @@ public partial class FileInstructService using var stream = binary.ToStream(); stream.Position = 0; - var fileName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}"; + var fileName = $"{image.FileName.IfNullOrEmptyAs("image")}.{image.FileExtension.IfNullOrEmptyAs("png")}"; var message = await completion.GetImageEdits(new Agent() { Id = innerAgentId @@ -162,8 +162,8 @@ public partial class FileInstructService using var maskStream = maskBinary.ToStream(); maskStream.Position = 0; - var imageName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}"; - var maskName = $"{mask.FileName ?? "mask"}.{mask.FileExtension ?? "png"}"; + var imageName = $"{image.FileName.IfNullOrEmptyAs("image")}.{image.FileExtension.IfNullOrEmptyAs("png")}"; + var maskName = $"{mask.FileName.IfNullOrEmptyAs("mask")}.{mask.FileExtension.IfNullOrEmptyAs("png")}"; var message = await completion.GetImageEdits(new Agent() { Id = innerAgentId diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs index d12450cd..d25003c2 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs @@ -5,6 +5,7 @@ using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Instructs.Models; using BotSharp.Core.Infrastructures; using BotSharp.OpenAPI.ViewModels.Instructs; +using BotSharp.OpenAPI.ViewModels.Instructs.Request; using static System.Net.Mime.MediaTypeNames; namespace BotSharp.OpenAPI.Controllers; @@ -118,7 +119,7 @@ public class InstructModeController : ControllerBase public async Task MultiModalCompletion([FromBody] MultiModalFileRequest input) { var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); try { @@ -141,11 +142,10 @@ public class InstructModeController : ControllerBase } [HttpPost("/instruct/multi-modal/upload")] - public async Task MultiModalCompletion([FromForm] IEnumerable files, [FromForm] MultiModalRequest request, - [FromForm] List? states = null, [FromForm] List? list = null) + public async Task MultiModalCompletion([FromForm] IEnumerable files, [FromForm] MultiModalRequest request) { var state = _services.GetRequiredService(); - request?.States?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + request?.States?.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var viewModel = new MultiModalViewModel(); try @@ -154,6 +154,7 @@ public class InstructModeController : ControllerBase { FileData = FileUtility.BuildFileDataFromFile(x) }).ToList(); + var fileInstruct = _services.GetRequiredService(); var content = await fileInstruct.ReadImages(request?.Text ?? string.Empty, fileModels, new InstructOptions { @@ -180,7 +181,7 @@ public class InstructModeController : ControllerBase public async Task ImageGeneration([FromBody] ImageGenerationRequest input) { var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try @@ -212,7 +213,7 @@ public class InstructModeController : ControllerBase public async Task ImageVariation([FromBody] ImageVariationRequest input) { var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try @@ -244,23 +245,27 @@ public class InstructModeController : ControllerBase } [HttpPost("/instruct/image-variation/upload")] - public async Task ImageVariation(IFormFile file, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] List? states = null, - [FromForm] string? agentId = null) + public async Task ImageVariation(IFormFile file, [FromForm] MultiModalRequest request) { var state = _services.GetRequiredService(); - states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + request?.States?.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try { var fileInstruct = _services.GetRequiredService(); var fileData = FileUtility.BuildFileDataFromFile(file); - var message = await fileInstruct.VaryImage(new InstructFileModel { FileData = fileData }, new InstructOptions + var message = await fileInstruct.VaryImage(new InstructFileModel { - Provider = provider, - Model = model, - AgentId = agentId + FileData = fileData, + FileName = Path.GetFileNameWithoutExtension(file.FileName), + FileExtension = Path.GetExtension(file.FileName).Substring(1) + }, + new InstructOptions + { + Provider = request?.Provider, + Model = request?.Model, + AgentId = request?.AgentId }); imageViewModel.Content = message.Content; @@ -281,7 +286,7 @@ public class InstructModeController : ControllerBase { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try @@ -311,24 +316,28 @@ public class InstructModeController : ControllerBase } [HttpPost("/instruct/image-edit/upload")] - public async Task ImageEdit(IFormFile file, [FromForm] string text, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] List? states = null, - [FromForm] string? agentId = null, [FromForm] string? templateName = null) + public async Task ImageEdit(IFormFile file, [FromForm] MultiModalRequest request) { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); - states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + request?.States?.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try { var fileData = FileUtility.BuildFileDataFromFile(file); - var message = await fileInstruct.EditImage(text, new InstructFileModel { FileData = fileData }, new InstructOptions + var message = await fileInstruct.EditImage(request?.Text ?? string.Empty, new InstructFileModel { - Provider = provider, - Model = model, - AgentId = agentId, - TemplateName = templateName + FileData = fileData, + FileName = Path.GetFileNameWithoutExtension(file.FileName), + FileExtension = Path.GetExtension(file.FileName).Substring(1) + }, + new InstructOptions + { + Provider = request?.Provider, + Model = request?.Model, + AgentId = request?.AgentId, + TemplateName = request?.TemplateName }); imageViewModel.Content = message.Content; @@ -350,7 +359,7 @@ public class InstructModeController : ControllerBase { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try @@ -382,28 +391,37 @@ public class InstructModeController : ControllerBase } [HttpPost("/instruct/image-mask-edit/upload")] - public async Task ImageMaskEdit(IFormFile image, IFormFile mask, - [FromForm] string text, [FromForm] string? provider = null, [FromForm] string? model = null, - [FromForm] List? states = null, [FromForm] string? agentId = null, [FromForm] string? templateName = null) + public async Task ImageMaskEdit(IFormFile image, IFormFile mask, [FromForm] MultiModalRequest request) { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); - states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + request?.States?.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var imageViewModel = new ImageGenerationViewModel(); try { var imageData = FileUtility.BuildFileDataFromFile(image); var maskData = FileUtility.BuildFileDataFromFile(mask); - var message = await fileInstruct.EditImage(text, - new InstructFileModel { FileData = imageData }, - new InstructFileModel { FileData = maskData }, new InstructOptions - { - Provider = provider, - Model = model, - AgentId = agentId, - TemplateName = templateName - }); + var message = await fileInstruct.EditImage(request?.Text ?? string.Empty, + new InstructFileModel + { + FileData = imageData, + FileName = Path.GetFileNameWithoutExtension(image.FileName), + FileExtension = Path.GetExtension(image.FileName).Substring(1) + }, + new InstructFileModel + { + FileData = maskData, + FileName = Path.GetFileNameWithoutExtension(mask.FileName), + FileExtension = Path.GetExtension(mask.FileName).Substring(1) + }, + new InstructOptions + { + Provider = request?.Provider, + Model = request?.Model, + AgentId = request?.AgentId, + TemplateName = request?.TemplateName + }); imageViewModel.Content = message.Content; imageViewModel.Images = message.GeneratedImages.Select(x => ImageViewModel.ToViewModel(x)).ToList(); @@ -425,7 +443,7 @@ public class InstructModeController : ControllerBase public async Task PdfCompletion([FromBody] MultiModalFileRequest input) { var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var viewModel = new PdfCompletionViewModel(); try @@ -451,29 +469,26 @@ public class InstructModeController : ControllerBase } [HttpPost("/instruct/pdf-completion/upload")] - public async Task PdfCompletion(IFormFile file, [FromForm] string text, - [FromForm] string? provider = null, [FromForm] string? model = null, [FromForm] List? states = null, - [FromForm] string? agentId = null, [FromForm] string? templateName = null) + public async Task PdfCompletion([FromForm] IEnumerable files, [FromForm] MultiModalRequest request) { var state = _services.GetRequiredService(); - states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + request?.States?.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var viewModel = new PdfCompletionViewModel(); try { - var data = FileUtility.BuildFileDataFromFile(file); - var files = new List + var fileModels = files.Select(x => new InstructFileModel { - new InstructFileModel { FileData = data } - }; + FileData = FileUtility.BuildFileDataFromFile(x) + }).ToList(); var fileInstruct = _services.GetRequiredService(); - var content = await fileInstruct.ReadPdf(text, files, new InstructOptions + var content = await fileInstruct.ReadPdf(request?.Text ?? string.Empty, fileModels, new InstructOptions { - Provider = provider, - Model = model, - AgentId = agentId, - TemplateName = templateName + Provider = request?.Provider, + Model = request?.Model, + AgentId = request?.AgentId, + TemplateName = request?.TemplateName }); viewModel.Content = content; return viewModel; @@ -494,7 +509,7 @@ public class InstructModeController : ControllerBase { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var viewModel = new SpeechToTextViewModel(); try @@ -524,25 +539,29 @@ public class InstructModeController : ControllerBase } [HttpPost("/instruct/speech-to-text/upload")] - public async Task SpeechToText(IFormFile file, - [FromForm] string? provider = null, [FromForm] string? model = null, - [FromForm] string? text = null, [FromForm] List? states = null, - [FromForm] string? agentId = null, [FromForm] string? templateName = null) + public async Task SpeechToText(IFormFile file, [FromForm] MultiModalRequest request) { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); - states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + request?.States?.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var viewModel = new SpeechToTextViewModel(); try { var audioData = FileUtility.BuildFileDataFromFile(file); - var content = await fileInstruct.SpeechToText(new InstructFileModel { FileData = audioData }, text, new InstructOptions + var content = await fileInstruct.SpeechToText(new InstructFileModel + { + FileData = audioData, + FileName = Path.GetFileNameWithoutExtension(file.FileName), + FileExtension = Path.GetExtension(file.FileName).Substring(1) + }, + request?.Text ?? string.Empty, + new InstructOptions { - Provider = provider, - Model = model, - AgentId = agentId, - TemplateName = templateName + Provider = request?.Provider, + Model = request?.Model, + AgentId = request?.AgentId, + TemplateName = request?.TemplateName }); viewModel.Content = content; @@ -561,7 +580,7 @@ public class InstructModeController : ControllerBase public async Task TextToSpeech([FromBody] TextToSpeechRequest input) { var state = _services.GetRequiredService(); - input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + input.States.ForEach(x => state.SetState(x.Key, x.Value, source: StateSource.External)); var completion = CompletionProvider.GetAudioSynthesizer(_services, provider: input.Provider, model: input.Model); var binaryData = await completion.GenerateAudioAsync(input.Text); diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructBaseRequest.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructBaseRequest.cs index cc3c11bd..4434da0f 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructBaseRequest.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructBaseRequest.cs @@ -1,3 +1,4 @@ +using BotSharp.OpenAPI.ViewModels.Instructs.Request; using System.Text.Json.Serialization; namespace BotSharp.Abstraction.Instructs.Models; @@ -17,7 +18,7 @@ public class InstructBaseRequest public virtual string? TemplateName { get; set; } [JsonPropertyName("states")] - public List States { get; set; } = []; + public List States { get; set; } = []; } public class MultiModalRequest : InstructBaseRequest diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructState.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructState.cs new file mode 100644 index 00000000..98628025 --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/Request/InstructState.cs @@ -0,0 +1,7 @@ +namespace BotSharp.OpenAPI.ViewModels.Instructs.Request; + +public class InstructState +{ + public string Key { get; set; } + public string Value { get; set; } +}