mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-10 20:11:49 +00:00
end-to-end 2.5
This commit is contained in:
1 parent
072d892430
commit
e9b3559ead
19 files changed
+329
-1
No files matched your search
+8
@@ -16,6 +16,8 @@ pub enum ApiClientImageModel {
|
||||
GptImage1p5,
|
||||
GptImage2,
|
||||
GrokImagineImage,
|
||||
GptImage2p5Flare,
|
||||
GptImage2p5Sunburst,
|
||||
GrokImagineImageQuality,
|
||||
Midjourney7,
|
||||
Midjourney7Niji,
|
||||
@@ -42,6 +44,8 @@ impl From<String> for ApiClientImageModel {
|
||||
"gpt_image_1" => Self::GptImage1,
|
||||
"gpt_image_1p5" => Self::GptImage1p5,
|
||||
"gpt_image_2" => Self::GptImage2,
|
||||
"gpt_image_2p5_flare" => Self::GptImage2p5Flare,
|
||||
"gpt_image_2p5_sunburst" => Self::GptImage2p5Sunburst,
|
||||
"grok_imagine_image" => Self::GrokImagineImage,
|
||||
"grok_imagine_image_q" => Self::GrokImagineImageQuality,
|
||||
"midjourney_7" => Self::Midjourney7,
|
||||
@@ -70,6 +74,8 @@ impl From<ApiClientImageModel> for String {
|
||||
ApiClientImageModel::GptImage1 => "gpt_image_1".to_string(),
|
||||
ApiClientImageModel::GptImage1p5 => "gpt_image_1p5".to_string(),
|
||||
ApiClientImageModel::GptImage2 => "gpt_image_2".to_string(),
|
||||
ApiClientImageModel::GptImage2p5Flare => "gpt_image_2p5_flare".to_string(),
|
||||
ApiClientImageModel::GptImage2p5Sunburst => "gpt_image_2p5_sunburst".to_string(),
|
||||
ApiClientImageModel::GrokImagineImage => "grok_imagine_image".to_string(),
|
||||
ApiClientImageModel::GrokImagineImageQuality => "grok_imagine_image_q".to_string(),
|
||||
ApiClientImageModel::Midjourney7 => "midjourney_7".to_string(),
|
||||
@@ -116,6 +122,8 @@ mod tests {
|
||||
(ApiClientImageModel::GptImage1, "gpt_image_1"),
|
||||
(ApiClientImageModel::GptImage1p5, "gpt_image_1p5"),
|
||||
(ApiClientImageModel::GptImage2, "gpt_image_2"),
|
||||
(ApiClientImageModel::GptImage2p5Flare, "gpt_image_2p5_flare"),
|
||||
(ApiClientImageModel::GptImage2p5Sunburst, "gpt_image_2p5_sunburst"),
|
||||
(ApiClientImageModel::GrokImagineImage, "grok_imagine_image"),
|
||||
(ApiClientImageModel::GrokImagineImageQuality, "grok_imagine_image_q"),
|
||||
(ApiClientImageModel::Midjourney7, "midjourney_7"),
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ pub fn tauri_image_model_to_common_model_type(model: TauriImageModel) -> CommonM
|
||||
TauriImageModel::GptImage1 => CommonModelType::GptImage1,
|
||||
TauriImageModel::GptImage1p5 => CommonModelType::GptImage1p5,
|
||||
TauriImageModel::GptImage2 => CommonModelType::GptImage2,
|
||||
TauriImageModel::GptImage2p5Flare => CommonModelType::GptImage2p5Flare,
|
||||
TauriImageModel::GptImage2p5Sunburst => CommonModelType::GptImage2p5Sunburst,
|
||||
TauriImageModel::Gemini25Flash => CommonModelType::NanoBanana,
|
||||
TauriImageModel::NanoBanana => CommonModelType::NanoBanana,
|
||||
TauriImageModel::NanoBanana2 => CommonModelType::NanoBanana2,
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ pub fn tauri_image_model_to_enums_model(model: TauriImageModel) -> Option<Common
|
||||
TauriImageModel::GptImage1 => Some(CommonImageModel::GptImage1),
|
||||
TauriImageModel::GptImage1p5 => Some(CommonImageModel::GptImage1p5),
|
||||
TauriImageModel::GptImage2 => Some(CommonImageModel::GptImage2),
|
||||
TauriImageModel::GptImage2p5Flare => Some(CommonImageModel::GptImage2p5Flare),
|
||||
TauriImageModel::GptImage2p5Sunburst => Some(CommonImageModel::GptImage2p5Sunburst),
|
||||
TauriImageModel::NanoBanana => Some(CommonImageModel::NanoBanana),
|
||||
TauriImageModel::NanoBanana2 => Some(CommonImageModel::NanoBanana2),
|
||||
TauriImageModel::NanoBananaPro => Some(CommonImageModel::NanoBananaPro),
|
||||
|
||||
+2
@@ -13,6 +13,8 @@ pub fn tauri_image_model_to_generation_model(model: TauriImageModel) -> Generati
|
||||
TauriImageModel::GptImage1 => GenerationModel::GptImage1,
|
||||
TauriImageModel::GptImage1p5 => GenerationModel::GptImage1p5,
|
||||
TauriImageModel::GptImage2 => GenerationModel::GptImage2,
|
||||
TauriImageModel::GptImage2p5Flare => GenerationModel::GptImage2p5Flare,
|
||||
TauriImageModel::GptImage2p5Sunburst => GenerationModel::GptImage2p5Sunburst,
|
||||
TauriImageModel::Gemini25Flash => GenerationModel::NanoBanana,
|
||||
TauriImageModel::NanoBanana => GenerationModel::NanoBanana,
|
||||
TauriImageModel::NanoBanana2 => GenerationModel::NanoBanana2,
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ pub fn tauri_image_model_to_router_model(model: TauriImageModel) -> Option<Route
|
||||
TauriImageModel::GptImage1 => Some(RouterImageModel::GptImage1), // Text-to-Image
|
||||
TauriImageModel::GptImage1p5 => Some(RouterImageModel::GptImage1p5), // Text-to-Image
|
||||
TauriImageModel::GptImage2 => Some(RouterImageModel::GptImage2), // Text-to-Image
|
||||
TauriImageModel::GptImage2p5Flare => Some(RouterImageModel::GptImage2p5Flare), // Text-to-Image
|
||||
TauriImageModel::GptImage2p5Sunburst => Some(RouterImageModel::GptImage2p5Sunburst), // Text-to-Image
|
||||
TauriImageModel::NanoBanana => Some(RouterImageModel::NanoBanana), // Text-to-Image
|
||||
TauriImageModel::NanoBanana2 => Some(RouterImageModel::NanoBanana2), // Text-to-Image
|
||||
TauriImageModel::NanoBananaPro => Some(RouterImageModel::NanoBananaPro), // Text-to-Image
|
||||
|
||||
@@ -85,6 +85,8 @@ impl TaskEnqueueSuccess{
|
||||
Some(GenerationModel::GptImage1) => Some(TaskModelType::GptImage1),
|
||||
Some(GenerationModel::GptImage1p5) => Some(TaskModelType::GptImage1p5),
|
||||
Some(GenerationModel::GptImage2) => Some(TaskModelType::GptImage2),
|
||||
Some(GenerationModel::GptImage2p5Flare) => Some(TaskModelType::GptImage2p5Flare),
|
||||
Some(GenerationModel::GptImage2p5Sunburst) => Some(TaskModelType::GptImage2p5Sunburst),
|
||||
Some(GenerationModel::Seedream4) => Some(TaskModelType::Seedream4),
|
||||
Some(GenerationModel::Seedream4p5) => Some(TaskModelType::Seedream4p5),
|
||||
Some(GenerationModel::Seedream5Lite) => Some(TaskModelType::Seedream5Lite),
|
||||
|
||||
@@ -32,6 +32,10 @@ pub enum TauriImageModel {
|
||||
GptImage1p5,
|
||||
#[serde(rename = "gpt_image_2")]
|
||||
GptImage2,
|
||||
#[serde(rename = "gpt_image_2p5_flare")]
|
||||
GptImage2p5Flare,
|
||||
#[serde(rename = "gpt_image_2p5_sunburst")]
|
||||
GptImage2p5Sunburst,
|
||||
#[serde(rename = "gemini_25_flash")]
|
||||
Gemini25Flash,
|
||||
#[serde(rename = "nano_banana")]
|
||||
|
||||
@@ -191,6 +191,8 @@ pub enum ListImageModelsImageModel {
|
||||
GptImage1p5,
|
||||
GptImage2,
|
||||
GrokImagineImage,
|
||||
GptImage2p5Flare,
|
||||
GptImage2p5Sunburst,
|
||||
GrokImagineImageQuality,
|
||||
Midjourney7,
|
||||
Midjourney7Niji,
|
||||
@@ -216,6 +218,8 @@ impl From<ApiClientImageModel> for ListImageModelsImageModel {
|
||||
ApiClientImageModel::GptImage1 => Self::GptImage1,
|
||||
ApiClientImageModel::GptImage1p5 => Self::GptImage1p5,
|
||||
ApiClientImageModel::GptImage2 => Self::GptImage2,
|
||||
ApiClientImageModel::GptImage2p5Flare => Self::GptImage2p5Flare,
|
||||
ApiClientImageModel::GptImage2p5Sunburst => Self::GptImage2p5Sunburst,
|
||||
ApiClientImageModel::GrokImagineImage => Self::GrokImagineImage,
|
||||
ApiClientImageModel::GrokImagineImageQuality => Self::GrokImagineImageQuality,
|
||||
ApiClientImageModel::Midjourney7 => Self::Midjourney7,
|
||||
@@ -244,6 +248,8 @@ impl From<ListImageModelsImageModel> for String {
|
||||
ListImageModelsImageModel::GptImage1 => "gpt_image_1".to_string(),
|
||||
ListImageModelsImageModel::GptImage1p5 => "gpt_image_1p5".to_string(),
|
||||
ListImageModelsImageModel::GptImage2 => "gpt_image_2".to_string(),
|
||||
ListImageModelsImageModel::GptImage2p5Flare => "gpt_image_2p5_flare".to_string(),
|
||||
ListImageModelsImageModel::GptImage2p5Sunburst => "gpt_image_2p5_sunburst".to_string(),
|
||||
ListImageModelsImageModel::GrokImagineImage => "grok_imagine_image".to_string(),
|
||||
ListImageModelsImageModel::GrokImagineImageQuality => "grok_imagine_image_q".to_string(),
|
||||
ListImageModelsImageModel::Midjourney7 => "midjourney_7".to_string(),
|
||||
|
||||
@@ -43,6 +43,10 @@ pub enum GenerationModel {
|
||||
GptImage1p5,
|
||||
#[serde(rename = "gpt_image_2")]
|
||||
GptImage2,
|
||||
#[serde(rename = "gpt_image_2p5_flare")]
|
||||
GptImage2p5Flare,
|
||||
#[serde(rename = "gpt_image_2p5_sunburst")]
|
||||
GptImage2p5Sunburst,
|
||||
#[serde(rename = "grok_image")]
|
||||
GrokImage,
|
||||
#[serde(rename = "gemini_25_flash")]
|
||||
|
||||
+2
@@ -298,6 +298,8 @@ fn task_model_type_to_generation_model(model: TaskModelType) -> Option<Generatio
|
||||
TaskModelType::GptImage1 => Some(GenerationModel::GptImage1),
|
||||
TaskModelType::GptImage1p5 => Some(GenerationModel::GptImage1p5),
|
||||
TaskModelType::GptImage2 => Some(GenerationModel::GptImage2),
|
||||
TaskModelType::GptImage2p5Flare => Some(GenerationModel::GptImage2p5Flare),
|
||||
TaskModelType::GptImage2p5Sunburst => Some(GenerationModel::GptImage2p5Sunburst),
|
||||
TaskModelType::NanoBanana => Some(GenerationModel::NanoBanana),
|
||||
TaskModelType::NanoBanana2 => Some(GenerationModel::NanoBanana2),
|
||||
TaskModelType::NanoBananaPro => Some(GenerationModel::NanoBananaPro),
|
||||
|
||||
@@ -41,6 +41,10 @@ pub enum TaskModelType {
|
||||
GptImage1p5,
|
||||
#[serde(rename = "gpt_image_2")]
|
||||
GptImage2,
|
||||
#[serde(rename = "gpt_image_2p5_flare")]
|
||||
GptImage2p5Flare,
|
||||
#[serde(rename = "gpt_image_2p5_sunburst")]
|
||||
GptImage2p5Sunburst,
|
||||
#[serde(rename = "seedream_4")]
|
||||
Seedream4,
|
||||
#[serde(rename = "seedream_4p5")]
|
||||
@@ -149,6 +153,8 @@ impl TaskModelType {
|
||||
Self::GptImage1 => "gpt_image_1",
|
||||
Self::GptImage1p5 => "gpt_image_1p5",
|
||||
Self::GptImage2 => "gpt_image_2",
|
||||
Self::GptImage2p5Flare => "gpt_image_2p5_flare",
|
||||
Self::GptImage2p5Sunburst => "gpt_image_2p5_sunburst",
|
||||
Self::Seedream4 => "seedream_4",
|
||||
Self::Seedream4p5 => "seedream_4p5",
|
||||
Self::Seedream5Lite => "seedream_5_lite",
|
||||
@@ -209,6 +215,8 @@ impl TaskModelType {
|
||||
"gpt_image_1" => Ok(Self::GptImage1),
|
||||
"gpt_image_1p5" => Ok(Self::GptImage1p5),
|
||||
"gpt_image_2" => Ok(Self::GptImage2),
|
||||
"gpt_image_2p5_flare" => Ok(Self::GptImage2p5Flare),
|
||||
"gpt_image_2p5_sunburst" => Ok(Self::GptImage2p5Sunburst),
|
||||
"seedream_4" => Ok(Self::Seedream4),
|
||||
"seedream_4p5" => Ok(Self::Seedream4p5),
|
||||
"seedream_5_lite" => Ok(Self::Seedream5Lite),
|
||||
@@ -272,6 +280,8 @@ impl TaskModelType {
|
||||
Self::GptImage1,
|
||||
Self::GptImage1p5,
|
||||
Self::GptImage2,
|
||||
Self::GptImage2p5Flare,
|
||||
Self::GptImage2p5Sunburst,
|
||||
Self::Seedream4,
|
||||
Self::Seedream4p5,
|
||||
Self::Seedream5Lite,
|
||||
@@ -342,6 +352,8 @@ mod tests {
|
||||
assert_serialization(TaskModelType::GptImage1, "gpt_image_1");
|
||||
assert_serialization(TaskModelType::GptImage1p5, "gpt_image_1p5");
|
||||
assert_serialization(TaskModelType::GptImage2, "gpt_image_2");
|
||||
assert_serialization(TaskModelType::GptImage2p5Flare, "gpt_image_2p5_flare");
|
||||
assert_serialization(TaskModelType::GptImage2p5Sunburst, "gpt_image_2p5_sunburst");
|
||||
assert_serialization(TaskModelType::Seedream4, "seedream_4");
|
||||
assert_serialization(TaskModelType::Seedream4p5, "seedream_4p5");
|
||||
assert_serialization(TaskModelType::Seedream5Lite, "seedream_5_lite");
|
||||
@@ -401,6 +413,8 @@ mod tests {
|
||||
assert_eq!(TaskModelType::GptImage1.to_str(), "gpt_image_1");
|
||||
assert_eq!(TaskModelType::GptImage1p5.to_str(), "gpt_image_1p5");
|
||||
assert_eq!(TaskModelType::GptImage2.to_str(), "gpt_image_2");
|
||||
assert_eq!(TaskModelType::GptImage2p5Flare.to_str(), "gpt_image_2p5_flare");
|
||||
assert_eq!(TaskModelType::GptImage2p5Sunburst.to_str(), "gpt_image_2p5_sunburst");
|
||||
assert_eq!(TaskModelType::Seedream4.to_str(), "seedream_4");
|
||||
assert_eq!(TaskModelType::Seedream4p5.to_str(), "seedream_4p5");
|
||||
assert_eq!(TaskModelType::Seedream5Lite.to_str(), "seedream_5_lite");
|
||||
@@ -457,6 +471,8 @@ mod tests {
|
||||
assert_eq!(TaskModelType::from_str("gpt_image_1").unwrap(), TaskModelType::GptImage1);
|
||||
assert_eq!(TaskModelType::from_str("gpt_image_1p5").unwrap(), TaskModelType::GptImage1p5);
|
||||
assert_eq!(TaskModelType::from_str("gpt_image_2").unwrap(), TaskModelType::GptImage2);
|
||||
assert_eq!(TaskModelType::from_str("gpt_image_2p5_flare").unwrap(), TaskModelType::GptImage2p5Flare);
|
||||
assert_eq!(TaskModelType::from_str("gpt_image_2p5_sunburst").unwrap(), TaskModelType::GptImage2p5Sunburst);
|
||||
assert_eq!(TaskModelType::from_str("seedream_4").unwrap(), TaskModelType::Seedream4);
|
||||
assert_eq!(TaskModelType::from_str("seedream_4p5").unwrap(), TaskModelType::Seedream4p5);
|
||||
assert_eq!(TaskModelType::from_str("seedream_5_lite").unwrap(), TaskModelType::Seedream5Lite);
|
||||
@@ -510,7 +526,7 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = TaskModelType::all_variants();
|
||||
assert_eq!(variants.len(), 52);
|
||||
assert_eq!(variants.len(), 54);
|
||||
// Image models
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::Flux1Dev));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::Flux1Schnell));
|
||||
@@ -526,6 +542,8 @@ mod tests {
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::GptImage1));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::GptImage1p5));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::GptImage2));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::GptImage2p5Flare));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::GptImage2p5Sunburst));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::Seedream4));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::Seedream4p5));
|
||||
assert_eq!(variants.pop_first(), Some(TaskModelType::Seedream5Lite));
|
||||
|
||||
@@ -366,6 +366,82 @@ fn build_omni_gen_image_models() -> Vec<OmniGenImageModelDetails> {
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
models.push(OmniGenImageModelDetails {
|
||||
model: CommonImageModel::GptImage2p5Flare,
|
||||
model_creator: Some(ModelCreator::OpenAi),
|
||||
full_name: Some("GPT Image 2.5 Flare".to_string()),
|
||||
text_prompt_supported: Some(true),
|
||||
image_refs_supported: Some(true),
|
||||
aspect_ratio_options: Some(vec![
|
||||
CommonAspectRatio::Auto,
|
||||
CommonAspectRatio::Square,
|
||||
CommonAspectRatio::SquareHd,
|
||||
CommonAspectRatio::TallThreeByFour,
|
||||
CommonAspectRatio::TallNineBySixteen,
|
||||
CommonAspectRatio::WideFourByThree,
|
||||
CommonAspectRatio::WideSixteenByNine,
|
||||
]),
|
||||
aspect_ratio_default: Some(CommonAspectRatio::Square),
|
||||
aspect_ratio_default_when_editing: Some(CommonAspectRatio::Auto),
|
||||
quality_options: Some(vec![
|
||||
CommonQuality::High,
|
||||
CommonQuality::Medium,
|
||||
CommonQuality::Low,
|
||||
]),
|
||||
default_quality: Some(CommonQuality::High),
|
||||
// NOTE: GPT Image 2.5 does not have "resolution" natively. We're emulating this.
|
||||
resolution_options: Some(vec![
|
||||
CommonResolution::OneK,
|
||||
CommonResolution::TwoK,
|
||||
CommonResolution::ThreeK,
|
||||
CommonResolution::FourK,
|
||||
]),
|
||||
// NOTE: GPT Image 2.5 does not have "resolution" natively. We're emulating this.
|
||||
resolution_default: Some(CommonResolution::OneK),
|
||||
batch_size_min: Some(1),
|
||||
batch_size_max: Some(4),
|
||||
batch_size_default: Some(1),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
models.push(OmniGenImageModelDetails {
|
||||
model: CommonImageModel::GptImage2p5Sunburst,
|
||||
model_creator: Some(ModelCreator::OpenAi),
|
||||
full_name: Some("GPT Image 2.5 Sunburst".to_string()),
|
||||
text_prompt_supported: Some(true),
|
||||
image_refs_supported: Some(true),
|
||||
aspect_ratio_options: Some(vec![
|
||||
CommonAspectRatio::Auto,
|
||||
CommonAspectRatio::Square,
|
||||
CommonAspectRatio::SquareHd,
|
||||
CommonAspectRatio::TallThreeByFour,
|
||||
CommonAspectRatio::TallNineBySixteen,
|
||||
CommonAspectRatio::WideFourByThree,
|
||||
CommonAspectRatio::WideSixteenByNine,
|
||||
]),
|
||||
aspect_ratio_default: Some(CommonAspectRatio::Square),
|
||||
aspect_ratio_default_when_editing: Some(CommonAspectRatio::Auto),
|
||||
quality_options: Some(vec![
|
||||
CommonQuality::High,
|
||||
CommonQuality::Medium,
|
||||
CommonQuality::Low,
|
||||
]),
|
||||
default_quality: Some(CommonQuality::High),
|
||||
// NOTE: GPT Image 2.5 does not have "resolution" natively. We're emulating this.
|
||||
resolution_options: Some(vec![
|
||||
CommonResolution::OneK,
|
||||
CommonResolution::TwoK,
|
||||
CommonResolution::ThreeK,
|
||||
CommonResolution::FourK,
|
||||
]),
|
||||
// NOTE: GPT Image 2.5 does not have "resolution" natively. We're emulating this.
|
||||
resolution_default: Some(CommonResolution::OneK),
|
||||
batch_size_min: Some(1),
|
||||
batch_size_max: Some(4),
|
||||
batch_size_default: Some(1),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
models.push(OmniGenImageModelDetails {
|
||||
model: CommonImageModel::Seedream4,
|
||||
model_creator: Some(ModelCreator::Bytedance),
|
||||
@@ -534,6 +610,14 @@ fn build_omni_gen_image_model_providers() -> Vec<OmniGenImageModelProviderDetail
|
||||
model: CommonImageModel::GptImage2,
|
||||
overrides: None,
|
||||
},
|
||||
OmniGenImageProviderModelDetails {
|
||||
model: CommonImageModel::GptImage2p5Flare,
|
||||
overrides: None,
|
||||
},
|
||||
OmniGenImageProviderModelDetails {
|
||||
model: CommonImageModel::GptImage2p5Sunburst,
|
||||
overrides: None,
|
||||
},
|
||||
OmniGenImageProviderModelDetails {
|
||||
model: CommonImageModel::Seedream4,
|
||||
overrides: None,
|
||||
@@ -571,3 +655,40 @@ fn build_omni_gen_image_model_providers() -> Vec<OmniGenImageModelProviderDetail
|
||||
|
||||
providers
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn gpt_image_2p5_models_are_listed_with_quality_and_resolution_options() {
|
||||
let models = build_omni_gen_image_models();
|
||||
for (model, full_name) in [
|
||||
(CommonImageModel::GptImage2p5Flare, "GPT Image 2.5 Flare"),
|
||||
(CommonImageModel::GptImage2p5Sunburst, "GPT Image 2.5 Sunburst"),
|
||||
] {
|
||||
let details = models.iter().find(|m| m.model == model).unwrap_or_else(|| panic!("{model:?} missing"));
|
||||
assert_eq!(details.full_name.as_deref(), Some(full_name));
|
||||
assert_eq!(details.model_creator, Some(ModelCreator::OpenAi));
|
||||
assert_eq!(details.text_prompt_supported, Some(true));
|
||||
assert_eq!(details.image_refs_supported, Some(true));
|
||||
assert_eq!(details.default_quality, Some(CommonQuality::High));
|
||||
assert_eq!(details.quality_options.as_ref().map(|q| q.len()), Some(3));
|
||||
assert_eq!(details.resolution_default, Some(CommonResolution::OneK));
|
||||
assert_eq!(details.resolution_options.as_ref().map(|r| r.len()), Some(4));
|
||||
assert_eq!(details.aspect_ratio_default_when_editing, Some(CommonAspectRatio::Auto));
|
||||
assert_eq!(details.batch_size_max, Some(4));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gpt_image_2p5_models_are_served_by_the_artcraft_provider() {
|
||||
let providers = build_omni_gen_image_model_providers();
|
||||
let artcraft = providers.iter()
|
||||
.find(|p| p.provider == GenerationProvider::Artcraft)
|
||||
.expect("artcraft provider");
|
||||
for model in [CommonImageModel::GptImage2p5Flare, CommonImageModel::GptImage2p5Sunburst] {
|
||||
assert!(artcraft.models.iter().any(|m| m.model == model), "{model:?} missing from artcraft provider");
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -98,3 +98,42 @@ fn convert_quality(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use artcraft_router::api::router_image_model::RouterImageModel;
|
||||
use enums::common::generation::common_image_model::CommonImageModel as CommonImageModelEnum;
|
||||
|
||||
#[test]
|
||||
fn gpt_image_2p5_models_convert_to_router_models() {
|
||||
assert_eq!(convert_model(&CommonImageModelEnum::GptImage2p5Flare).unwrap(), RouterImageModel::GptImage2p5Flare);
|
||||
assert_eq!(convert_model(&CommonImageModelEnum::GptImage2p5Sunburst).unwrap(), RouterImageModel::GptImage2p5Sunburst);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gpt_image_2p5_request_hydrates_to_artcraft_router_builder() {
|
||||
let request = OmniApiImageGenerateRequest {
|
||||
image_urls: None,
|
||||
idempotency_token: Some("idem".to_string()),
|
||||
model: Some(CommonImageModelEnum::GptImage2p5Sunburst),
|
||||
prompt: Some("a cat in space".to_string()),
|
||||
image_media_tokens: None,
|
||||
resolution: Some(CommonResolutionEnum::TwoK),
|
||||
aspect_ratio: Some(CommonAspectRatioEnum::WideSixteenByNine),
|
||||
quality: Some(CommonQualityEnum::Medium),
|
||||
image_batch_count: Some(2),
|
||||
adjust_horizontal_angle: None,
|
||||
adjust_vertical_angle: None,
|
||||
adjust_zoom: None,
|
||||
};
|
||||
let builder = hydrate_to_router_request(&request).unwrap();
|
||||
assert_eq!(builder.model, RouterImageModel::GptImage2p5Sunburst);
|
||||
assert!(matches!(builder.provider, RouterProvider::Artcraft));
|
||||
assert_eq!(builder.prompt.as_deref(), Some("a cat in space"));
|
||||
assert_eq!(format!("{:?}", builder.resolution), "Some(TwoK)");
|
||||
assert_eq!(format!("{:?}", builder.aspect_ratio), "Some(WideSixteenByNine)");
|
||||
assert_eq!(format!("{:?}", builder.quality), "Some(Medium)");
|
||||
assert_eq!(builder.image_batch_count, Some(2));
|
||||
}
|
||||
}
|
||||
+38
@@ -98,3 +98,41 @@ fn convert_quality(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use artcraft_router::api::router_image_model::RouterImageModel;
|
||||
use enums::common::generation::common_image_model::CommonImageModel as CommonImageModelEnum;
|
||||
|
||||
#[test]
|
||||
fn gpt_image_2p5_models_convert_to_router_models() {
|
||||
assert_eq!(convert_model(&CommonImageModelEnum::GptImage2p5Flare).unwrap(), RouterImageModel::GptImage2p5Flare);
|
||||
assert_eq!(convert_model(&CommonImageModelEnum::GptImage2p5Sunburst).unwrap(), RouterImageModel::GptImage2p5Sunburst);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gpt_image_2p5_request_hydrates_to_artcraft_router_builder() {
|
||||
let request = OmniGenImageCostAndGenerateRequest {
|
||||
idempotency_token: Some("idem".to_string()),
|
||||
model: Some(CommonImageModelEnum::GptImage2p5Sunburst),
|
||||
prompt: Some("a cat in space".to_string()),
|
||||
image_media_tokens: None,
|
||||
resolution: Some(CommonResolutionEnum::TwoK),
|
||||
aspect_ratio: Some(CommonAspectRatioEnum::WideSixteenByNine),
|
||||
quality: Some(CommonQualityEnum::Medium),
|
||||
image_batch_count: Some(2),
|
||||
adjust_horizontal_angle: None,
|
||||
adjust_vertical_angle: None,
|
||||
adjust_zoom: None,
|
||||
};
|
||||
let builder = hydrate_to_router_request(&request).unwrap();
|
||||
assert_eq!(builder.model, RouterImageModel::GptImage2p5Sunburst);
|
||||
assert!(matches!(builder.provider, RouterProvider::Artcraft));
|
||||
assert_eq!(builder.prompt.as_deref(), Some("a cat in space"));
|
||||
assert_eq!(format!("{:?}", builder.resolution), "Some(TwoK)");
|
||||
assert_eq!(format!("{:?}", builder.aspect_ratio), "Some(WideSixteenByNine)");
|
||||
assert_eq!(format!("{:?}", builder.quality), "Some(Medium)");
|
||||
assert_eq!(builder.image_batch_count, Some(2));
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ export enum CommonImageModel {
|
||||
GptImage1 = "gpt_image_1",
|
||||
GptImage1p5 = "gpt_image_1p5",
|
||||
GptImage2 = "gpt_image_2",
|
||||
GptImage2p5Flare = "gpt_image_2p5_flare",
|
||||
GptImage2p5Sunburst = "gpt_image_2p5_sunburst",
|
||||
NanaBanana = "nano_banana",
|
||||
NanaBanana2 = "nano_banana_2",
|
||||
NanaBananaPro = "nano_banana_pro",
|
||||
|
||||
@@ -284,6 +284,8 @@ export function CostBreakdownModal({ activeTabId }: CostBreakdownModalProps) {
|
||||
"flux_pro_1p1_ultra",
|
||||
"gpt_image_1p5",
|
||||
"gpt_image_2",
|
||||
"gpt_image_2p5_flare",
|
||||
"gpt_image_2p5_sunburst",
|
||||
"nano_banana",
|
||||
"nano_banana_2",
|
||||
"nano_banana_pro",
|
||||
|
||||
@@ -9,6 +9,8 @@ const MODEL_DESCRIPTIONS: Record<string, string> = {
|
||||
gpt_image_1: "OpenAI's original image model",
|
||||
gpt_image_1p5: "OpenAI imagery with reliable text",
|
||||
gpt_image_2: "4K images with crisp text rendering",
|
||||
gpt_image_2p5_flare: "Fast, precise edits that keep subjects intact",
|
||||
gpt_image_2p5_sunburst: "Premium detail and fidelity, slower",
|
||||
midjourney_7: "Signature artistic, stylized imagery",
|
||||
midjourney_7_niji: "Anime and illustration styles",
|
||||
midjourney_8: "Midjourney's latest flagship model",
|
||||
|
||||
@@ -64,6 +64,8 @@ export const getModelDisplayName = (
|
||||
gpt_image_1: "GPT Image 1",
|
||||
gpt_image_1p5: "GPT Image 1.5",
|
||||
gpt_image_2: "GPT Image 2",
|
||||
gpt_image_2p5_flare: "GPT Image 2.5 Flare",
|
||||
gpt_image_2p5_sunburst: "GPT Image 2.5 Sunburst",
|
||||
sora_2: "Sora 2",
|
||||
sora_2_pro: "Sora 2 Pro",
|
||||
|
||||
|
||||
@@ -385,6 +385,76 @@ export const IMAGE_MODELS: ImageModel[] = [
|
||||
CommonQuality.Low,
|
||||
],
|
||||
}),
|
||||
new ImageModel({
|
||||
id: "gpt_image_2p5_flare",
|
||||
tauriId: "gpt_image_2p5_flare",
|
||||
fullName: "GPT Image 2.5 Flare",
|
||||
category: "image",
|
||||
creator: ModelCreator.OpenAi,
|
||||
selectorName: "GPT Image 2.5 Flare",
|
||||
selectorDescription: "Precise edits, keeps subjects intact",
|
||||
selectorBadges: ["60 sec."],
|
||||
maxGenerationCount: 4,
|
||||
defaultGenerationCount: 1,
|
||||
tags: [ModelTag.InstructiveEdit],
|
||||
canEditImages: true,
|
||||
canUseImagePrompt: true,
|
||||
maxImagePromptCount: 6,
|
||||
progressBarTime: 60000,
|
||||
maxPromptLength: Infinity,
|
||||
canChangeAspectRatio: true,
|
||||
defaultAspectRatio: CommonAspectRatio.WideSixteenByNine,
|
||||
aspectRatios: [
|
||||
CommonAspectRatio.Auto,
|
||||
CommonAspectRatio.Square,
|
||||
CommonAspectRatio.SquareHd,
|
||||
CommonAspectRatio.TallThreeByFour,
|
||||
CommonAspectRatio.TallNineBySixteen,
|
||||
CommonAspectRatio.WideFourByThree,
|
||||
CommonAspectRatio.WideSixteenByNine,
|
||||
],
|
||||
defaultQuality: CommonQuality.High,
|
||||
qualityOptions: [
|
||||
CommonQuality.High,
|
||||
CommonQuality.Medium,
|
||||
CommonQuality.Low,
|
||||
],
|
||||
}),
|
||||
new ImageModel({
|
||||
id: "gpt_image_2p5_sunburst",
|
||||
tauriId: "gpt_image_2p5_sunburst",
|
||||
fullName: "GPT Image 2.5 Sunburst",
|
||||
category: "image",
|
||||
creator: ModelCreator.OpenAi,
|
||||
selectorName: "GPT Image 2.5 Sunburst",
|
||||
selectorDescription: "Premium detail, slower",
|
||||
selectorBadges: ["2 min."],
|
||||
maxGenerationCount: 4,
|
||||
defaultGenerationCount: 1,
|
||||
tags: [ModelTag.InstructiveEdit],
|
||||
canEditImages: true,
|
||||
canUseImagePrompt: true,
|
||||
maxImagePromptCount: 6,
|
||||
progressBarTime: 120000,
|
||||
maxPromptLength: Infinity,
|
||||
canChangeAspectRatio: true,
|
||||
defaultAspectRatio: CommonAspectRatio.WideSixteenByNine,
|
||||
aspectRatios: [
|
||||
CommonAspectRatio.Auto,
|
||||
CommonAspectRatio.Square,
|
||||
CommonAspectRatio.SquareHd,
|
||||
CommonAspectRatio.TallThreeByFour,
|
||||
CommonAspectRatio.TallNineBySixteen,
|
||||
CommonAspectRatio.WideFourByThree,
|
||||
CommonAspectRatio.WideSixteenByNine,
|
||||
],
|
||||
defaultQuality: CommonQuality.High,
|
||||
qualityOptions: [
|
||||
CommonQuality.High,
|
||||
CommonQuality.Medium,
|
||||
CommonQuality.Low,
|
||||
],
|
||||
}),
|
||||
new ImageModel({
|
||||
id: "seedream_4",
|
||||
tauriId: "seedream_4",
|
||||
|
||||
Reference in new issue
Block a user