BotSharp/src/Plugins/BotSharp.Plugin.FileHandler/Functions/EditImageFn.cs

114 lines
3.9 KiB
C#
Raw Normal View History

2024-07-19 19:18:22 +00:00
using System.IO;
namespace BotSharp.Plugin.FileHandler.Functions;
public class EditImageFn : IFunctionCallback
{
2024-12-04 22:12:02 +00:00
public string Name => "util-file-edit_image";
2024-07-19 19:18:22 +00:00
public string Indication => "Editing image";
private readonly IServiceProvider _services;
private readonly ILogger<EditImageFn> _logger;
private string _conversationId;
private string _messageId;
public EditImageFn(
IServiceProvider services,
ILogger<EditImageFn> logger)
{
_services = services;
_logger = logger;
}
public async Task<bool> Execute(RoleDialogModel message)
{
var args = JsonSerializer.Deserialize<LlmContextIn>(message.FunctionArgs);
var descrpition = args?.UserRequest ?? string.Empty;
Init(message);
SetImageOptions();
2024-08-07 21:56:57 +00:00
var image = await SelectImage(descrpition);
2024-07-19 19:18:22 +00:00
var response = await GetImageEditGeneration(message, descrpition, image);
message.Content = response;
return true;
}
private void Init(RoleDialogModel message)
{
var convService = _services.GetRequiredService<IConversationService>();
_conversationId = convService.ConversationId;
_messageId = message.MessageId;
}
private void SetImageOptions()
{
var state = _services.GetRequiredService<IConversationStateService>();
2024-08-28 17:06:23 +00:00
state.SetState("image_response_format", "bytes");
2024-07-19 19:18:22 +00:00
state.SetState("image_count", "1");
}
2024-08-07 21:56:57 +00:00
private async Task<MessageFileModel?> SelectImage(string? description)
2024-07-19 19:18:22 +00:00
{
2024-08-07 21:56:57 +00:00
var fileInstruct = _services.GetRequiredService<IFileInstructService>();
2024-08-08 00:26:22 +00:00
var selecteds = await fileInstruct.SelectMessageFiles(_conversationId, new SelectFileOptions
{
Description = description,
ContentTypes = new List<string> { MediaTypeNames.Image.Png }
});
2024-08-07 21:56:57 +00:00
return selecteds?.FirstOrDefault();
2024-07-19 19:18:22 +00:00
}
private async Task<string> GetImageEditGeneration(RoleDialogModel message, string description, MessageFileModel? image)
{
if (image == null)
{
return "Failed to find an image. Please provide an image.";
}
try
{
var completion = CompletionProvider.GetImageCompletion(_services, provider: "openai", model: "dall-e-2");
var text = !string.IsNullOrWhiteSpace(description) ? description : message.Content;
var dialog = RoleDialogModel.From(message, AgentRole.User, text);
var agent = new Agent
{
Id = BuiltInAgentId.UtilityAssistant,
Name = "Utility Assistant"
};
2024-08-08 05:51:15 +00:00
var fileStorage = _services.GetRequiredService<IFileStorageService>();
2025-05-28 00:56:14 +00:00
var fileBinary = fileStorage.GetFileBytes(image.FileStorageUrl);
using var stream = fileBinary.ToStream();
2024-08-08 01:56:29 +00:00
stream.Position = 0;
2024-07-19 19:18:22 +00:00
var result = await completion.GetImageEdits(agent, dialog, stream, image.FileName ?? string.Empty);
stream.Close();
SaveGeneratedImage(result?.GeneratedImages?.FirstOrDefault());
2024-08-08 18:34:50 +00:00
return $"Image \"{image.FileName}.{image.FileExtension}\" is successfylly editted.";
2024-07-19 19:18:22 +00:00
}
catch (Exception ex)
{
var error = $"Error when getting image edit response. {ex.Message}";
2025-05-02 16:31:28 +00:00
_logger.LogWarning(ex, $"{error}");
2024-07-19 19:18:22 +00:00
return error;
}
}
private void SaveGeneratedImage(ImageGeneration? image)
{
if (image == null) return;
2024-09-10 19:02:25 +00:00
var files = new List<FileDataModel>()
2024-07-19 19:18:22 +00:00
{
2024-09-10 19:02:25 +00:00
new FileDataModel
2024-07-19 19:18:22 +00:00
{
FileName = $"{Guid.NewGuid()}.png",
FileData = $"data:{MediaTypeNames.Image.Png};base64,{image.ImageData}"
}
};
2024-08-08 01:56:29 +00:00
var fileStorage = _services.GetRequiredService<IFileStorageService>();
fileStorage.SaveMessageFiles(_conversationId, _messageId, FileSourceType.Bot, files);
2024-07-19 19:18:22 +00:00
}
}