diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Models/InstructFileModel.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Models/InstructFileModel.cs
index cacef5a0..4d04a2fc 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Files/Models/InstructFileModel.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Files/Models/InstructFileModel.cs
@@ -3,7 +3,7 @@ namespace BotSharp.Abstraction.Files.Models;
public class InstructFileModel : FileBase
{
///
- /// File extension without dot
+ /// File extension
///
[JsonPropertyName("file_extension")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@@ -15,4 +15,11 @@ public class InstructFileModel : FileBase
[JsonPropertyName("file_url")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? FileUrl { get; set; } = string.Empty;
+
+ ///
+ /// File url
+ ///
+ [JsonPropertyName("content_type")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string? ContentType { get; set; }
}
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 a332028e..339cb049 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs
@@ -17,7 +17,7 @@ public partial class FileInstructService
using var stream = audioBinary.ToStream();
stream.Position = 0;
- var fileName = $"{audio.FileName.IfNullOrEmptyAs("audio")}.{audio.FileExtension.IfNullOrEmptyAs("wav")}";
+ var fileName = BuildFileName(audio.FileName, audio.FileExtension, "audio", "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 e1b15d81..b2067e63 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs
@@ -22,7 +22,8 @@ public partial class FileInstructService
Files = images?.Select(x => new BotSharpFile
{
FileUrl = x.FileUrl,
- FileData = x.FileData
+ FileData = x.FileData,
+ ContentType = x.ContentType
}).ToList() ?? []
}
});
@@ -82,7 +83,7 @@ public partial class FileInstructService
using var stream = binary.ToStream();
stream.Position = 0;
- var fileName = $"{image.FileName.IfNullOrEmptyAs("image")}.{image.FileExtension.IfNullOrEmptyAs("png")}";
+ var fileName = BuildFileName(image.FileName, image.FileExtension, "image", "png");
var message = await completion.GetImageVariation(new Agent()
{
Id = innerAgentId
@@ -118,7 +119,7 @@ public partial class FileInstructService
using var stream = binary.ToStream();
stream.Position = 0;
- var fileName = $"{image.FileName.IfNullOrEmptyAs("image")}.{image.FileExtension.IfNullOrEmptyAs("png")}";
+ var fileName = BuildFileName(image.FileName, image.FileExtension, "image", "png");
var message = await completion.GetImageEdits(new Agent()
{
Id = innerAgentId
@@ -162,8 +163,8 @@ public partial class FileInstructService
using var maskStream = maskBinary.ToStream();
maskStream.Position = 0;
- var imageName = $"{image.FileName.IfNullOrEmptyAs("image")}.{image.FileExtension.IfNullOrEmptyAs("png")}";
- var maskName = $"{mask.FileName.IfNullOrEmptyAs("mask")}.{mask.FileExtension.IfNullOrEmptyAs("png")}";
+ var imageName = BuildFileName(image.FileName, image.FileExtension, "image", "png");
+ var maskName = BuildFileName(image.FileName, image.FileExtension, "mask", "png");
var message = await completion.GetImageEdits(new Agent()
{
Id = innerAgentId
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs
index 4a0729d0..25deecd0 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs
@@ -1,4 +1,6 @@
+using static System.Net.Mime.MediaTypeNames;
+
namespace BotSharp.Core.Files.Services;
public partial class FileInstructService : IFileInstructService
@@ -76,5 +78,13 @@ public partial class FileInstructService : IFileInstructService
var instruction = agentService.RenderedTemplate(agent, templateName);
return instruction;
}
+
+ private string BuildFileName(string? name, string? extension, string defaultName, string defaultExtension)
+ {
+ var fname = name.IfNullOrEmptyAs(defaultName);
+ var fextension = extension.IfNullOrEmptyAs(defaultExtension);
+ fextension = fextension.StartsWith(".") ? fextension.Substring(1) : fextension;
+ return $"{name}.{fextension}";
+ }
#endregion
}
diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs
index 42e0d2c8..73a4b9ae 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs
@@ -91,7 +91,12 @@ public class InstructModeController : ControllerBase
{
new RoleDialogModel(AgentRole.User, input.Text)
{
- Files = input.Files?.Select(x => new BotSharpFile { FileUrl = x.FileUrl, FileData = x.FileData }).ToList() ?? []
+ Files = input.Files?.Select(x => new BotSharpFile
+ {
+ FileUrl = x.FileUrl,
+ FileData = x.FileData,
+ ContentType = x.ContentType
+ }).ToList() ?? []
}
});
@@ -256,7 +261,7 @@ public class InstructModeController : ControllerBase
{
FileData = fileData,
FileName = Path.GetFileNameWithoutExtension(file.FileName),
- FileExtension = Path.GetExtension(file.FileName).Substring(1)
+ FileExtension = Path.GetExtension(file.FileName)
},
new InstructOptions
{
@@ -327,7 +332,7 @@ public class InstructModeController : ControllerBase
{
FileData = fileData,
FileName = Path.GetFileNameWithoutExtension(file.FileName),
- FileExtension = Path.GetExtension(file.FileName).Substring(1)
+ FileExtension = Path.GetExtension(file.FileName)
},
new InstructOptions
{
@@ -404,13 +409,13 @@ public class InstructModeController : ControllerBase
{
FileData = imageData,
FileName = Path.GetFileNameWithoutExtension(image.FileName),
- FileExtension = Path.GetExtension(image.FileName).Substring(1)
+ FileExtension = Path.GetExtension(image.FileName)
},
new InstructFileModel
{
FileData = maskData,
FileName = Path.GetFileNameWithoutExtension(mask.FileName),
- FileExtension = Path.GetExtension(mask.FileName).Substring(1)
+ FileExtension = Path.GetExtension(mask.FileName)
},
new InstructOptions
{
@@ -550,7 +555,7 @@ public class InstructModeController : ControllerBase
{
FileData = audioData,
FileName = Path.GetFileNameWithoutExtension(file.FileName),
- FileExtension = Path.GetExtension(file.FileName).Substring(1)
+ FileExtension = Path.GetExtension(file.FileName)
},
request?.Text ?? string.Empty,
new InstructOptions
diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs
index b2eaaf46..ab7135ef 100644
--- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs
@@ -308,7 +308,7 @@ public class ChatCompletionProvider : IChatCompletion
ChatToolCall.CreateFunctionToolCall(message.ToolCallId.IfNullOrEmptyAs(message.FunctionName), message.FunctionName, BinaryData.FromString(message.FunctionArgs ?? "{}"))
}));
- messages.Add(new ToolChatMessage(message.ToolCallId ?? message.FunctionName, message.Content));
+ messages.Add(new ToolChatMessage(message.ToolCallId.IfNullOrEmptyAs(message.FunctionName), message.Content));
}
else if (message.Role == AgentRole.User)
{
@@ -323,14 +323,14 @@ public class ChatCompletionProvider : IChatCompletion
if (!string.IsNullOrEmpty(file.FileData))
{
var (contentType, binary) = FileUtility.GetFileInfoFromData(file.FileData);
- var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType, ChatImageDetailLevel.Auto);
+ var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType.IfNullOrEmptyAs(file.ContentType), ChatImageDetailLevel.Auto);
contentParts.Add(contentPart);
}
else if (!string.IsNullOrEmpty(file.FileStorageUrl))
{
var contentType = FileUtility.GetFileContentType(file.FileStorageUrl);
var binary = fileStorage.GetFileBytes(file.FileStorageUrl);
- var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType, ChatImageDetailLevel.Auto);
+ var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType.IfNullOrEmptyAs(file.ContentType), ChatImageDetailLevel.Auto);
contentParts.Add(contentPart);
}
else if (!string.IsNullOrEmpty(file.FileUrl))
diff --git a/src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs
index 85304054..42ce1ac9 100644
--- a/src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs
@@ -270,10 +270,10 @@ public class ChatCompletionProvider : IChatCompletion
{
messages.Add(new AssistantChatMessage(new List
{
- ChatToolCall.CreateFunctionToolCall(message.FunctionName, message.FunctionName, BinaryData.FromString(message.FunctionArgs ?? string.Empty))
+ ChatToolCall.CreateFunctionToolCall(message.ToolCallId.IfNullOrEmptyAs(message.FunctionName), message.FunctionName, BinaryData.FromString(message.FunctionArgs ?? string.Empty))
}));
- messages.Add(new ToolChatMessage(message.FunctionName, message.Content));
+ messages.Add(new ToolChatMessage(message.ToolCallId.IfNullOrEmptyAs(message.FunctionName), message.Content));
}
else if (message.Role == AgentRole.User)
{
diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs
index a0e7cc17..1ead28e6 100644
--- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs
@@ -312,7 +312,7 @@ public class GeminiChatCompletionProvider : IChatCompletion
{
InlineData = new()
{
- MimeType = contentType ?? file.ContentType,
+ MimeType = contentType.IfNullOrEmptyAs(file.ContentType),
Data = Convert.ToBase64String(binary.ToArray())
}
});
@@ -325,7 +325,7 @@ public class GeminiChatCompletionProvider : IChatCompletion
{
InlineData = new()
{
- MimeType = contentType,
+ MimeType = contentType.IfNullOrEmptyAs(file.ContentType),
Data = Convert.ToBase64String(binary.ToArray())
}
});
diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs
index edf51660..17ee1012 100644
--- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs
@@ -274,7 +274,7 @@ public class ChatCompletionProvider : IChatCompletion
ChatToolCall.CreateFunctionToolCall(message.ToolCallId.IfNullOrEmptyAs(message.FunctionName), message.FunctionName, BinaryData.FromString(message.FunctionArgs ?? "{}"))
}));
- messages.Add(new ToolChatMessage(message.ToolCallId ?? message.FunctionName, message.Content));
+ messages.Add(new ToolChatMessage(message.ToolCallId.IfNullOrEmptyAs(message.FunctionName), message.Content));
}
else if (message.Role == AgentRole.User)
{
@@ -289,14 +289,14 @@ public class ChatCompletionProvider : IChatCompletion
if (!string.IsNullOrEmpty(file.FileData))
{
var (contentType, binary) = FileUtility.GetFileInfoFromData(file.FileData);
- var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType, ChatImageDetailLevel.Auto);
+ var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType.IfNullOrEmptyAs(file.ContentType), ChatImageDetailLevel.Auto);
contentParts.Add(contentPart);
}
else if (!string.IsNullOrEmpty(file.FileStorageUrl))
{
var contentType = FileUtility.GetFileContentType(file.FileStorageUrl);
var binary = fileStorage.GetFileBytes(file.FileStorageUrl);
- var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType, ChatImageDetailLevel.Auto);
+ var contentPart = ChatMessageContentPart.CreateImagePart(binary, contentType.IfNullOrEmptyAs(file.ContentType), ChatImageDetailLevel.Auto);
contentParts.Add(contentPart);
}
else if (!string.IsNullOrEmpty(file.FileUrl))