diff --git a/src/agent/provider/entity/image.rs b/src/agent/provider/entity/image.rs index 7e7c49a..14efc23 100644 --- a/src/agent/provider/entity/image.rs +++ b/src/agent/provider/entity/image.rs @@ -2,7 +2,7 @@ use mxlink::mime; #[derive(Default)] pub struct ImageGenerationParams { - pub size_override: Option, + pub smallest_size_possible: bool, pub cheaper_model_switching_allowed: bool, @@ -10,8 +10,8 @@ pub struct ImageGenerationParams { } impl ImageGenerationParams { - pub fn with_size_override(mut self, value: Option) -> Self { - self.size_override = value; + pub fn with_smallest_size_possible(mut self, value: bool) -> Self { + self.smallest_size_possible = value; self } diff --git a/src/agent/provider/openai/controller.rs b/src/agent/provider/openai/controller.rs index 8a2ea32..f257b20 100644 --- a/src/agent/provider/openai/controller.rs +++ b/src/agent/provider/openai/controller.rs @@ -31,12 +31,9 @@ use crate::{ use crate::{ agent::{ AgentPurpose, - provider::{ - entity::{ - ImageEditResult, ImageGenerationResult, ImageSource, PingResult, - TextToSpeechParams, TextToSpeechResult, - }, - openai::utils::convert_string_to_enum, + provider::entity::{ + ImageEditResult, ImageGenerationResult, ImageSource, PingResult, + TextToSpeechParams, TextToSpeechResult, }, }, strings, @@ -312,10 +309,11 @@ impl ControllerTrait for Controller { image_generation_config.quality.clone() }; - let size = params - .size_override - .map(|s| convert_string_to_enum::(&s).unwrap()) - .or(image_generation_config.size); + let size = if params.smallest_size_possible { + Some(get_sticker_size(&model)) + } else { + image_generation_config.size + }; let response_format = match model.clone() { ImageModel::DallE2 => Some(ImageResponseFormat::B64Json), @@ -638,3 +636,17 @@ fn audio_mime_type_to_file_name(mime_type: &mxlink::mime::Mime) -> Option async_openai::types::images::ImageSize { + use async_openai::types::images::ImageSize; + + match model { + ImageModel::DallE2 => ImageSize::S256x256, + ImageModel::DallE3 => ImageSize::S1024x1024, + ImageModel::GptImage1 => ImageSize::S1024x1024, + ImageModel::GptImage1Mini => ImageSize::S1024x1024, + ImageModel::GptImage1dot5 => ImageSize::S1024x1024, + ImageModel::Other(_) => ImageSize::S1024x1024, + } +} diff --git a/src/agent/provider/openai/utils.rs b/src/agent/provider/openai/utils.rs index 2baa6ac..03925e3 100644 --- a/src/agent/provider/openai/utils.rs +++ b/src/agent/provider/openai/utils.rs @@ -1,8 +1,6 @@ -use async_openai::types::{ - responses::{ - EasyInputContent, EasyInputMessage, ImageDetail, InputContent, InputImageContent, - InputItem, InputParam, MessageType, Role, - }, +use async_openai::types::responses::{ + EasyInputContent, EasyInputMessage, ImageDetail, InputContent, InputImageContent, InputItem, + InputParam, MessageType, Role, }; use crate::conversation::llm::{ @@ -48,19 +46,3 @@ pub fn convert_llm_messages_to_openai_response_input( InputParam::Items(items) } - -pub(super) fn convert_string_to_enum(value: &str) -> Result -where - T: serde::de::DeserializeOwned, -{ - // This is a hacky way to construct an enum from the string we have. - let enum_result: serde_json::Result = serde_json::from_str(&format!("\"{}\"", value)); - match enum_result { - Ok(enum_result) => Ok(enum_result), - Err(err) => { - tracing::debug!(?err, "Failed to parse into enum"); - - Err(format!("The value ({}) is not supported.", value)) - } - } -} diff --git a/src/agent/provider/openai_compat/controller.rs b/src/agent/provider/openai_compat/controller.rs index 3b3b3fd..871d617 100644 --- a/src/agent/provider/openai_compat/controller.rs +++ b/src/agent/provider/openai_compat/controller.rs @@ -3,6 +3,8 @@ use etke_openai_api_rust::chat::{ChatApi, ChatBody}; use etke_openai_api_rust::images::{ImagesApi, ImagesBody}; use etke_openai_api_rust::{Auth, Message, OpenAI}; +const SMALLEST_IMAGE_SIZE: &str = "256x256"; + use super::super::ControllerTrait; use crate::utils::base64::base64_decode; use crate::{ @@ -303,9 +305,11 @@ impl ControllerTrait for Controller { // when they span multiple lines. let prompt = prompt.replace("\n", " "); - let size: Option = params - .size_override - .or_else(|| image_generation_config.size.clone()); + let size: Option = if params.smallest_size_possible { + Some(SMALLEST_IMAGE_SIZE.to_owned()) + } else { + image_generation_config.size.clone() + }; let request = ImagesBody { model: Some(image_generation_config.model_id.to_owned()), diff --git a/src/controller/image/generation.rs b/src/controller/image/generation.rs index 1f5c38c..420b7d8 100644 --- a/src/controller/image/generation.rs +++ b/src/controller/image/generation.rs @@ -12,9 +12,6 @@ use crate::strings; use crate::utils::mime::get_file_extension; use crate::{Bot, entity::MessageContext}; -// We may make this configurable (per room, etc.) in the future, but for now it's hardcoded. -const STICKER_SIZE: &str = "256x256"; - pub async fn handle_image( bot: &Bot, matrix_link: MatrixLink, @@ -177,7 +174,7 @@ pub async fn handle_sticker( ); let params = ImageGenerationParams::default() - .with_size_override(Some(STICKER_SIZE.to_owned())) + .with_smallest_size_possible(true) .with_cheaper_model_switching_allowed(true) .with_cheaper_quality_switching_allowed(true); diff --git a/src/strings/usage.rs b/src/strings/usage.rs index 31e0de2..ac93c95 100644 --- a/src/strings/usage.rs +++ b/src/strings/usage.rs @@ -64,7 +64,7 @@ To create a sticker, send a command like `%command_prefix% sticker A huge bowl o The difference from **creating images** is that the bot will: -- create a smaller-resolution image (`256x256`) - smaller/quicker, but still good enough for a sticker +- create a smaller-resolution image (as small as the model allows) - smaller/quicker, but still good enough for a sticker - potentially switch to a different (cheaper or otherwise more suitable) model, if available - post the image directly to the room (as a reply to your message), without starting a threaded conversation "#;