diff --git a/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs b/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs index 11b597acf..5f68ced17 100644 --- a/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs +++ b/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs @@ -99,7 +99,7 @@ pub async fn create_image_generation_with_model( let request_url = images_generation_url(settings); let normalized_size = normalize_image_size_for_model(requested_model, size); let started_at = std::time::Instant::now(); - let mut upstream_model = preferred_image_upstream_model(requested_model); + let upstream_model = preferred_image_upstream_model(requested_model); let mut recovered_failure_audits = Vec::new(); let mut attempt = 1; loop { @@ -140,51 +140,6 @@ pub async fn create_image_generation_with_model( response.body.as_str(), attempt, ) { - let primary_error = if upstream_model == GPT_IMAGE_2_MODEL { - handle_image_response( - http_client, - request_url.as_str(), - response.status, - response.body.as_str(), - auditable_image_model(upstream_model), - failure_context, - started_at.elapsed().as_millis() as u64, - Some(prompt.chars().count()), - Some(reference_images.len()), - candidate_count, - "vector-engine", - settings.request_deadline, - ) - .await - .err() - } else { - None - }; - if primary_error.as_ref().is_some_and(|error| { - should_fallback_to_gpt_image_2_c( - requested_model, - upstream_model, - attempt, - error, - settings, - ) - }) { - let error = primary_error.expect("primary error checked above"); - record_image_model_fallback( - "generation", - request_url.as_str(), - upstream_model, - GPT_IMAGE_2_C_MODEL, - attempt, - &error, - ); - if let Some(audit) = error.audit().cloned() { - recovered_failure_audits.push(audit); - } - upstream_model = GPT_IMAGE_2_C_MODEL; - attempt += 1; - continue; - } if retry_image_upstream_status_after_delay( "generation", request_url.as_str(), @@ -283,29 +238,6 @@ pub async fn create_image_generation_with_model( .append(&mut recovered_failure_audits); return Ok(generated); } - Err(error) - if should_fallback_to_gpt_image_2_c( - requested_model, - upstream_model, - attempt, - &error, - settings, - ) => - { - record_image_model_fallback( - "generation", - request_url.as_str(), - upstream_model, - GPT_IMAGE_2_C_MODEL, - attempt, - &error, - ); - if let Some(audit) = error.audit().cloned() { - recovered_failure_audits.push(audit); - } - upstream_model = GPT_IMAGE_2_C_MODEL; - attempt += 1; - } Err(error) => { return Err(finish_image_model_fallback_error( error, @@ -577,7 +509,7 @@ pub async fn create_image_edit_with_references_and_model( let reference_image_bytes_total: usize = reference_images.iter().map(|image| image.bytes.len()).sum(); let started_at = std::time::Instant::now(); - let mut upstream_model = preferred_image_upstream_model(requested_model); + let upstream_model = preferred_image_upstream_model(requested_model); let mut recovered_failure_audits = Vec::new(); let mut attempt = 1; loop { @@ -645,51 +577,6 @@ pub async fn create_image_edit_with_references_and_model( response.body.as_str(), attempt, ) { - let primary_error = if upstream_model == GPT_IMAGE_2_MODEL { - handle_image_response( - http_client, - request_url.as_str(), - response.status, - response.body.as_str(), - auditable_image_model(upstream_model), - failure_context, - started_at.elapsed().as_millis() as u64, - Some(prompt.chars().count()), - Some(reference_image_count), - candidate_count, - "vector-engine-edit", - settings.request_deadline, - ) - .await - .err() - } else { - None - }; - if primary_error.as_ref().is_some_and(|error| { - should_fallback_to_gpt_image_2_c( - requested_model, - upstream_model, - attempt, - error, - settings, - ) - }) { - let error = primary_error.expect("primary error checked above"); - record_image_model_fallback( - "edit", - request_url.as_str(), - upstream_model, - GPT_IMAGE_2_C_MODEL, - attempt, - &error, - ); - if let Some(audit) = error.audit().cloned() { - recovered_failure_audits.push(audit); - } - upstream_model = GPT_IMAGE_2_C_MODEL; - attempt += 1; - continue; - } if retry_image_upstream_status_after_delay( "edit", request_url.as_str(), @@ -790,29 +677,6 @@ pub async fn create_image_edit_with_references_and_model( .append(&mut recovered_failure_audits); return Ok(generated); } - Err(error) - if should_fallback_to_gpt_image_2_c( - requested_model, - upstream_model, - attempt, - &error, - settings, - ) => - { - record_image_model_fallback( - "edit", - request_url.as_str(), - upstream_model, - GPT_IMAGE_2_C_MODEL, - attempt, - &error, - ); - if let Some(audit) = error.audit().cloned() { - recovered_failure_audits.push(audit); - } - upstream_model = GPT_IMAGE_2_C_MODEL; - attempt += 1; - } Err(error) => { return Err(finish_image_model_fallback_error( error, @@ -845,19 +709,6 @@ fn auditable_image_model(model: &str) -> Option<&'static str> { } } -fn should_fallback_to_gpt_image_2_c( - requested_model: &str, - upstream_model: &str, - attempt: u32, - error: &PlatformImageError, - settings: &ImageProviderSettings, -) -> bool { - // Compatibility function retained for old call sites/tests. New dispatch - // never crosses models; retries are handled by the same-model loop only. - let _ = (requested_model, upstream_model, attempt, error, settings); - false -} - fn contains_image_provider_content_rejection(message: &str, raw_excerpt: &str) -> bool { let haystack = format!("{message}\n{raw_excerpt}").to_ascii_lowercase(); [ @@ -883,31 +734,6 @@ fn contains_image_provider_content_rejection(message: &str, raw_excerpt: &str) - .any(|marker| haystack.contains(marker)) } -fn record_image_model_fallback( - request_kind: &'static str, - request_url: &str, - from_model: &str, - to_model: &str, - attempt: u32, - error: &PlatformImageError, -) { - let audit = error.audit(); - tracing::warn!( - provider = VECTOR_ENGINE_PROVIDER, - endpoint = %request_url, - request_kind, - fallback_from_model = from_model, - fallback_to_model = to_model, - attempt, - next_attempt = attempt + 1, - max_attempts = VECTOR_ENGINE_SEND_MAX_ATTEMPTS, - failure_stage = audit.map(|audit| audit.failure_stage).unwrap_or("unknown"), - status = audit.and_then(|audit| audit.status_code).unwrap_or_default(), - error = %error.message(), - "ImageProvider 首选图片模型失败,切换兼容模型" - ); -} - fn should_retry_image_curl_send_error( error: &super::curl_transport::ImageProviderCurlError, attempt: u32, @@ -1202,28 +1028,6 @@ mod tests { assert!(!should_retry_image_upstream_response(502, "", 5)); } - #[test] - fn image_provider_never_falls_back_across_image_models() { - let settings = ImageProviderSettings { - provider: ImageProvider::VectorEngine, - base_url: "https://vector.example/v1".to_string(), - api_key: "test-key".to_string(), - request_timeout_ms: 1_000, - request_deadline: None, - }; - let error = PlatformImageError::InvalidRequest { - provider: VECTOR_ENGINE_PROVIDER, - message: "model unavailable".to_string(), - }; - assert!(!should_fallback_to_gpt_image_2_c( - GPT_IMAGE_2_MODEL, - GPT_IMAGE_2_MODEL, - 1, - &error, - &settings, - )); - } - #[test] fn image_provider_send_retry_delay_uses_exponential_backoff_with_bounded_jitter() { assert_eq!(image_provider_send_retry_delay_ms(1, 0), 500);