Skip to content

Commit 5eb2abf

Browse files
authored
artcraft desktop gpt-image cost estimates + quality arg (#1425)
1 parent 31a9704 commit 5eb2abf

15 files changed

Lines changed: 87 additions & 18 deletions

File tree

_tools/postman/collections/ArtCraft API/generate/cost/Estimate Image Cost.request.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ body:
1515
type: json
1616
content: |
1717
{
18-
"model": "seedream_5_lite",
18+
"model": "gpt_image_2",
1919
"provider": "artcraft",
2020
"generation_mode": {"type": "text_to_image" },
2121
"aspect_ratio": "wide_sixteen_by_nine",
2222
"resolution": "two_k",
23+
"quality": "low",
2324
"image_batch_count": 1
2425
}
2526
order: 2000

crates/api_clients/artcraft/artcraft_api_defs/src/generate/cost_estimate/estimate_image_cost.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use utoipa::ToSchema;
33

44
use enums::common::generation::common_aspect_ratio::CommonAspectRatio;
55
use enums::common::generation::common_image_model::CommonImageModel;
6+
use enums::common::generation::common_quality::CommonQuality;
67
use enums::common::generation::common_resolution::CommonResolution;
78
use enums::common::generation_provider::GenerationProvider;
89

910
pub const ESTIMATE_IMAGE_COST_PATH: &str = "/v1/generate/cost_estimate/image";
1011

1112
/// Request body for the image cost estimate endpoint.
12-
#[derive(Serialize, Deserialize, ToSchema)]
13+
#[derive(Serialize, Deserialize, ToSchema, Debug)]
1314
pub struct EstimateImageCostRequest {
1415
/// The image model to estimate costs for.
1516
pub model: CommonImageModel,
@@ -29,12 +30,15 @@ pub struct EstimateImageCostRequest {
2930
/// Optional resolution.
3031
pub resolution: Option<CommonResolution>,
3132

33+
// Optional quality.
34+
pub quality: Option<CommonQuality>,
35+
3236
/// Number of images to generate in parallel.
3337
pub image_batch_count: Option<u16>,
3438
}
3539

3640
/// Describes the type of image generation being requested.
37-
#[derive(Serialize, Deserialize, ToSchema)]
41+
#[derive(Serialize, Deserialize, ToSchema, Debug)]
3842
#[serde(tag = "type", rename_all = "snake_case")]
3943
pub enum GenerationMode {
4044
/// No input images — generate from prompt only.
@@ -94,6 +98,7 @@ mod tests {
9498
generation_mode: GenerationMode::TextToImage,
9599
aspect_ratio: None,
96100
resolution: None,
101+
quality: None,
97102
image_batch_count: None,
98103
};
99104
let serialized = serde_json::to_string(&request).unwrap();
@@ -108,6 +113,7 @@ mod tests {
108113
generation_mode: GenerationMode::ImageEdit { count: 2 },
109114
aspect_ratio: None,
110115
resolution: None,
116+
quality: None,
111117
image_batch_count: None,
112118
};
113119
let serialized = serde_json::to_string(&request).unwrap();

crates/desktop/artcraft/src/core/commands/cost_estimate/estimate_image_cost_command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub async fn estimate_image_cost_command(
1717
request: EstimateImageCostRequest,
1818
app_env_configs: State<'_, AppEnvConfigs>,
1919
) -> ResponseOrError<EstimateImageCostResponse, EstimateImageCostError> {
20-
debug!("estimate_image_cost_command called");
20+
debug!("estimate_image_cost_command called: {:?}", request);
2121

2222
let result = estimate_image_cost(
2323
&app_env_configs.storyteller_host,

crates/service/web/storyteller_web/src/configs/omni_gen/image_models.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,10 @@ fn build_omni_gen_image_model_providers() -> Vec<OmniGenImageModelProviderDetail
378378
model: CommonImageModel::GptImage1p5,
379379
overrides: None,
380380
},
381+
OmniGenImageProviderModelDetails {
382+
model: CommonImageModel::GptImage2,
383+
overrides: None,
384+
},
381385
OmniGenImageProviderModelDetails {
382386
model: CommonImageModel::Seedream4,
383387
overrides: None,

crates/service/web/storyteller_web/src/http_server/endpoints/generate/cost_estimate/image/estimate_image_cost_handler.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ use artcraft_api_defs::generate::cost_estimate::estimate_image_cost::{
99
};
1010
use artcraft_router::api::common_aspect_ratio::CommonAspectRatio as RouterAspectRatio;
1111
use artcraft_router::api::common_image_model::CommonImageModel as RouterImageModel;
12+
use artcraft_router::api::common_quality::CommonQuality as RouterQuality;
1213
use artcraft_router::api::common_resolution::CommonResolution as RouterResolution;
1314
use artcraft_router::api::provider::Provider as RouterProvider;
1415
use artcraft_router::client::generation_mode_mismatch_strategy::GenerationModeMismatchStrategy;
1516
use artcraft_router::client::request_mismatch_mitigation_strategy::RequestMismatchMitigationStrategy;
1617
use artcraft_router::generate::generate_image::generate_image_request::GenerateImageRequest;
1718
use enums::common::generation::common_aspect_ratio::CommonAspectRatio;
1819
use enums::common::generation::common_image_model::CommonImageModel;
20+
use enums::common::generation::common_quality::CommonQuality;
1921
use enums::common::generation::common_resolution::CommonResolution;
2022
use enums::common::generation_provider::GenerationProvider;
2123

@@ -37,6 +39,7 @@ pub async fn estimate_image_cost_handler(
3739
let router_model = map_image_model(request.model)?;
3840
let router_aspect_ratio = request.aspect_ratio.map(map_aspect_ratio);
3941
let router_resolution = request.resolution.map(map_resolution);
42+
let router_quality = request.quality.map(map_quality);
4043

4144
let router_request = GenerateImageRequest {
4245
model: router_model,
@@ -45,7 +48,7 @@ pub async fn estimate_image_cost_handler(
4548
image_inputs: None, // TODO: Only some models charge for this - we'll need to add later.
4649
resolution: router_resolution,
4750
aspect_ratio: router_aspect_ratio,
48-
quality: None,
51+
quality: router_quality,
4952
image_batch_count: request.image_batch_count,
5053
request_mismatch_mitigation_strategy: RequestMismatchMitigationStrategy::PayLessDowngrade,
5154
generation_mode_mismatch_strategy: Some(GenerationModeMismatchStrategy::GenerateAnyway),
@@ -132,13 +135,13 @@ fn map_image_model(model: CommonImageModel) -> Result<RouterImageModel, HandlerE
132135
CommonImageModel::FluxPro11Ultra => RouterImageModel::FluxPro11Ultra,
133136
CommonImageModel::GptImage1 => RouterImageModel::GptImage1,
134137
CommonImageModel::GptImage1p5 => RouterImageModel::GptImage1p5,
138+
CommonImageModel::GptImage2 => RouterImageModel::GptImage2,
135139
CommonImageModel::NanoBanana => RouterImageModel::NanoBanana,
136140
CommonImageModel::NanoBanana2 => RouterImageModel::NanoBanana2,
137141
CommonImageModel::NanoBananaPro => RouterImageModel::NanoBananaPro,
138142
CommonImageModel::Seedream4 => RouterImageModel::Seedream4,
139143
CommonImageModel::Seedream4p5 => RouterImageModel::Seedream4p5,
140144
CommonImageModel::Seedream5Lite => RouterImageModel::Seedream5Lite,
141-
CommonImageModel::GptImage2 => RouterImageModel::GptImage2,
142145
};
143146
Ok(router_model)
144147
}
@@ -178,3 +181,11 @@ fn map_resolution(res: CommonResolution) -> RouterResolution {
178181
CommonResolution::TenEightyP => RouterResolution::TenEightyP,
179182
}
180183
}
184+
185+
fn map_quality(res: CommonQuality) -> RouterQuality {
186+
match res {
187+
CommonQuality::Low => RouterQuality::Low,
188+
CommonQuality::Medium => RouterQuality::Medium,
189+
CommonQuality::High => RouterQuality::High,
190+
}
191+
}

frontend/libs/api-enums/src/lib/common/generation/CommonImageModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export enum CommonImageModel {
99
FluxPro11Ultra = "flux_pro_1p1_ultra",
1010
GptImage1 = "gpt_image_1",
1111
GptImage1p5 = "gpt_image_1p5",
12+
GptImage2 = "gpt_image_2",
1213
NanaBanana = "nano_banana",
1314
NanaBanana2 = "nano_banana_2",
1415
NanaBananaPro = "nano_banana_pro",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
// NOTE: These are defined in Rust (as the source of truth) and duplicated in the frontend.
3+
// In the future, we should use code gen (protobufs or similar) to keep the two sides in sync.
4+
5+
export enum CommonQuality {
6+
High = "high",
7+
Medium = "medium",
8+
Low = "low",
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from "./CommonImageModel.js";
22
export * from "./CommonVideoModel.js";
33
export * from "./CommonAspectRatio.js";
4+
export * from "./CommonQuality.js";
45
export * from "./CommonVideoResolution.js";
56
export * from "./GenerationMode.js";
67
export * from "./ImageGenerationMode.js";

frontend/libs/components/pricing-modal/src/lib/convert/imageModelToCommonImageModel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ export function imageModelToCommonImageModel(
1414
return CommonImageModel.FluxPro11;
1515
case "flux_pro_11_ultra":
1616
return CommonImageModel.FluxPro11Ultra;
17+
case "gpt_image_1":
18+
return CommonImageModel.GptImage1;
1719
case "gpt_image_1p5":
1820
return CommonImageModel.GptImage1p5;
21+
case "gpt_image_2":
22+
return CommonImageModel.GptImage2;
1923
case "nano_banana":
2024
return CommonImageModel.NanaBanana;
2125
case "nano_banana_2":
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { CommonQuality } from "@storyteller/api-enums";
2+
3+
/**
4+
* Convert a quality value to CommonQuality for the image cost estimate API.
5+
*
6+
* Accepts a CommonQuality string value from @storyteller/model-list ("high", "medium", "low").
7+
*/
8+
export function imageQualityToCommonQuality(
9+
quality: string | undefined,
10+
): CommonQuality | null {
11+
switch (quality) {
12+
case "high":
13+
return CommonQuality.High;
14+
case "medium":
15+
return CommonQuality.Medium;
16+
case "low":
17+
return CommonQuality.Low;
18+
default:
19+
return null;
20+
}
21+
}

0 commit comments

Comments
 (0)