seedream 4.5 fal wrapper

This commit is contained in:
Brandon Thomas committed 2025-12-04 12:57:30 -05:00
1 parent 32cda55005
commit e8ff0c1e28
6 files changed
+286 -12

No files matched your search

@@ -0,0 +1,142 @@
use crate::creds::fal_api_key::FalApiKey;
use crate::error::classify_fal_error::classify_fal_error;
use crate::error::fal_error_plus::FalErrorPlus;
use fal::endpoints::fal_ai::bytedance::seedream::bytedance_seedream_v4p5_edit_image::{bytedance_seedream_v4p5_edit_image, BytedanceSeedreamV4p5EditImageInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueBytedanceSeedreamV4p5EditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub image_urls: Vec<String>,
// Optional args
pub num_images: Option<EnqueueBytedanceSeedreamV4p5EditImageNumImages>,
pub max_images: Option<EnqueueBytedanceSeedreamV4p5EditImageMaxImages>,
pub image_size: Option<EnqueueBytedanceSeedreamV4p5EditImageSize>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5EditImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5EditImageMaxImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5EditImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto2k,
Auto4k,
}
pub async fn enqueue_bytedance_seedream_v4p5_edit_image_webhook<R: IntoUrl>(
args: EnqueueBytedanceSeedreamV4p5EditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = args.num_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5EditImageNumImages::One => 1,
EnqueueBytedanceSeedreamV4p5EditImageNumImages::Two => 2,
EnqueueBytedanceSeedreamV4p5EditImageNumImages::Three => 3,
EnqueueBytedanceSeedreamV4p5EditImageNumImages::Four => 4,
});
let max_images = args.max_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::One => 1,
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Two => 2,
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Three => 3,
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Four => 4,
});
let image_size = args.image_size
.map(|image_size| match image_size {
EnqueueBytedanceSeedreamV4p5EditImageSize::Square => "square",
EnqueueBytedanceSeedreamV4p5EditImageSize::SquareHd => "square_hd",
EnqueueBytedanceSeedreamV4p5EditImageSize::PortraitFourThree => "portrait_4_3",
EnqueueBytedanceSeedreamV4p5EditImageSize::PortraitSixteenNine => "portrait_16_9",
EnqueueBytedanceSeedreamV4p5EditImageSize::LandscapeFourThree => "landscape_4_3",
EnqueueBytedanceSeedreamV4p5EditImageSize::LandscapeSixteenNine => "landscape_16_9",
EnqueueBytedanceSeedreamV4p5EditImageSize::Auto2k => "auto_2K",
EnqueueBytedanceSeedreamV4p5EditImageSize::Auto4k => "auto_4K",
})
.map(|resolution| resolution.to_string());
let request = BytedanceSeedreamV4p5EditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
// Optionals
num_images,
max_images,
image_size,
// Constants
enable_safety_checker: Some(false),
seed: None,
};
let result = bytedance_seedream_v4p5_edit_image(request)
.with_api_key(&args.api_key.0)
.queue_webhook(args.webhook_url)
.await;
result.map_err(|err| classify_fal_error(err))
}
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_bytedance_seedream_v4p5_edit_image_webhook::{enqueue_bytedance_seedream_v4p5_edit_image_webhook, EnqueueBytedanceSeedreamV4p5EditImageArgs, EnqueueBytedanceSeedreamV4p5EditImageMaxImages, EnqueueBytedanceSeedreamV4p5EditImageNumImages, EnqueueBytedanceSeedreamV4p5EditImageSize};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
//let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
let secret = read_to_string("/home/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueBytedanceSeedreamV4p5EditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
],
prompt: "add the ghost to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: Some(EnqueueBytedanceSeedreamV4p5EditImageNumImages::Two),
max_images: Some(EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Two),
image_size: Some(EnqueueBytedanceSeedreamV4p5EditImageSize::Auto2k),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_bytedance_seedream_v4p5_edit_image_webhook(args).await?;
Ok(())
}
}
@@ -1,4 +1,5 @@
pub mod enqueue_bytedance_seedream_v4_edit_image_webhook;
pub mod enqueue_bytedance_seedream_v4p5_edit_image_webhook;
pub mod enqueue_flux_pro_kontext_max_edit_webhook;
pub mod enqueue_gemini_25_flash_edit_webhook;
pub mod enqueue_gpt_image_1_edit_image_webhook;
@@ -0,0 +1,134 @@
use crate::creds::fal_api_key::FalApiKey;
use crate::error::classify_fal_error::classify_fal_error;
use crate::error::fal_error_plus::FalErrorPlus;
use fal::endpoints::fal_ai::bytedance::seedream::bytedance_seedream_v4p5_text_to_image::{bytedance_seedream_v4p5_text_to_image, BytedanceSeedreamV4p5TextToImageInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueBytedanceSeedreamV4p5TextToImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
// Optional args
pub num_images: Option<EnqueueBytedanceSeedreamV4p5TextToImageNumImages>,
pub max_images: Option<EnqueueBytedanceSeedreamV4p5TextToImageMaxImages>,
pub image_size: Option<EnqueueBytedanceSeedreamV4p5TextToImageSize>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5TextToImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5TextToImageMaxImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5TextToImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto2k,
Auto4k,
}
pub async fn enqueue_bytedance_seedream_v4p5_text_to_image_webhook<R: IntoUrl>(
args: EnqueueBytedanceSeedreamV4p5TextToImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = args.num_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::One => 1,
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Two => 2,
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Three => 3,
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Four => 4,
});
let max_images = args.max_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::One => 1,
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Two => 2,
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Three => 3,
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Four => 4,
});
let image_size = args.image_size
.map(|image_size| match image_size {
EnqueueBytedanceSeedreamV4p5TextToImageSize::Square => "square",
EnqueueBytedanceSeedreamV4p5TextToImageSize::SquareHd => "square_hd",
EnqueueBytedanceSeedreamV4p5TextToImageSize::PortraitFourThree => "portrait_4_3",
EnqueueBytedanceSeedreamV4p5TextToImageSize::PortraitSixteenNine => "portrait_16_9",
EnqueueBytedanceSeedreamV4p5TextToImageSize::LandscapeFourThree => "landscape_4_3",
EnqueueBytedanceSeedreamV4p5TextToImageSize::LandscapeSixteenNine => "landscape_16_9",
EnqueueBytedanceSeedreamV4p5TextToImageSize::Auto2k => "auto_2K",
EnqueueBytedanceSeedreamV4p5TextToImageSize::Auto4k => "auto_4K",
})
.map(|resolution| resolution.to_string());
let request = BytedanceSeedreamV4p5TextToImageInput {
prompt: args.prompt.to_string(),
// Optionals
num_images,
max_images,
image_size,
// Constants
enable_safety_checker: Some(false),
seed: None,
};
let result = bytedance_seedream_v4p5_text_to_image(request)
.with_api_key(&args.api_key.0)
.queue_webhook(args.webhook_url)
.await;
result.map_err(|err| classify_fal_error(err))
}
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::text::enqueue_bytedance_seedream_v4p5_text_to_image_webhook::{enqueue_bytedance_seedream_v4p5_text_to_image_webhook, EnqueueBytedanceSeedreamV4p5TextToImageArgs, EnqueueBytedanceSeedreamV4p5TextToImageMaxImages, EnqueueBytedanceSeedreamV4p5TextToImageNumImages, EnqueueBytedanceSeedreamV4p5TextToImageSize};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
let secret = read_to_string("/home/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueBytedanceSeedreamV4p5TextToImageArgs {
prompt: "an anime girl is riding a t-rex in the forest",
num_images: Some(EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Two),
max_images: Some(EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Two),
image_size: Some(EnqueueBytedanceSeedreamV4p5TextToImageSize::LandscapeSixteenNine),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_bytedance_seedream_v4p5_text_to_image_webhook(args).await?;
Ok(())
}
}
@@ -1,2 +1,3 @@
pub mod enqueue_bytedance_seedream_v4_text_to_image_webhook;
pub mod enqueue_bytedance_seedream_v4p5_text_to_image_webhook;
pub mod enqueue_nano_banana_pro_text_to_image_webhook;
@@ -1,7 +1,7 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BytedanceSeedream4p5EditImageInput {
pub struct BytedanceSeedreamV4p5EditImageInput {
pub prompt: String,
pub image_urls: Vec<String>,
@@ -28,17 +28,13 @@ pub struct BytedanceSeedream4p5EditImageInput {
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
/// Possible enum values: standard, fast (default "standard")
#[serde(skip_serializing_if = "Option::is_none")]
pub enhance_prompt_mode: Option<String>,
/// Defaults to true
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BytedanceSeedream4p5EditImageOutput {
pub struct BytedanceSeedreamV4p5EditImageOutput {
pub images: Vec<ImageFile>,
}
@@ -49,7 +45,7 @@ pub struct ImageFile {
}
pub fn bytedance_seedream_v4p5_edit_image(
params: BytedanceSeedream4p5EditImageInput,
) -> FalRequest<BytedanceSeedream4p5EditImageInput, BytedanceSeedream4p5EditImageOutput> {
params: BytedanceSeedreamV4p5EditImageInput,
) -> FalRequest<BytedanceSeedreamV4p5EditImageInput, BytedanceSeedreamV4p5EditImageOutput> {
FalRequest::new("fal-ai/bytedance/seedream/v4.5/edit", params)
}
@@ -1,7 +1,7 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BytedanceSeedream4p5TextToImageInput {
pub struct BytedanceSeedreamV4p5TextToImageInput {
pub prompt: String,
/// Supports a custom height/width (which we didn't implement) OR an enum value -
@@ -32,7 +32,7 @@ pub struct BytedanceSeedream4p5TextToImageInput {
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BytedanceSeedream4p5TextToImageOutput {
pub struct BytedanceSeedreamV4p5TextToImageOutput {
pub images: Vec<ImageFile>,
}
@@ -43,7 +43,7 @@ pub struct ImageFile {
}
pub fn bytedance_seedream_v4p5_text_to_image(
params: BytedanceSeedream4p5TextToImageInput,
) -> FalRequest<BytedanceSeedream4p5TextToImageInput, BytedanceSeedream4p5TextToImageOutput> {
params: BytedanceSeedreamV4p5TextToImageInput,
) -> FalRequest<BytedanceSeedreamV4p5TextToImageInput, BytedanceSeedreamV4p5TextToImageOutput> {
FalRequest::new("fal-ai/bytedance/seedream/v4.5/text-to-image", params)
}