Enable Parallel image Gen

This commit is contained in:
2026-06-12 11:15:50 +08:00
parent 3f1dafeee7
commit d648a1cb02

View File

@@ -1186,103 +1186,120 @@ async fn maybe_prepare_puzzle_clear_assets_inner(
let http_client = build_openai_image_http_client(&settings).map_err(|error| { let http_client = build_openai_image_http_client(&settings).map_err(|error| {
puzzle_clear_error_response(request_context, PUZZLE_CLEAR_CREATION_PROVIDER, error) puzzle_clear_error_response(request_context, PUZZLE_CLEAR_CREATION_PROVIDER, error)
})?; })?;
// 中文注释5 张 sheet 并行生成,每张内部最多重试 4 次上游错误
let theme_prompt = payload.theme_prompt.as_deref().unwrap_or_default();
let mut generated_sheets = Vec::with_capacity(sheet_specs.len()); let mut generated_sheets = Vec::with_capacity(sheet_specs.len());
for sheet_spec in sheet_specs { {
let sheet_prompt = build_puzzle_clear_atlas_prompt( let futures: Vec<_> = sheet_specs
payload.theme_prompt.as_deref().unwrap_or_default(), .iter()
&sheet_spec, .map(|sheet_spec| {
); let sheet_prompt = build_puzzle_clear_atlas_prompt(theme_prompt, sheet_spec);
let mut accepted_sheet = None; let client = http_client.clone();
for attempt_index in 0..PUZZLE_CLEAR_SHEET_GENERATION_MAX_ATTEMPTS { let settings = settings.clone();
let failure_context = format!( let debug_run = image_debug_run.clone();
"拼消消素材 {} 生成失败,第 {}", async move {
sheet_spec.sheet_id, for attempt_index in 0..PUZZLE_CLEAR_SHEET_GENERATION_MAX_ATTEMPTS {
attempt_index + 1 let failure_context = format!(
); "拼消消素材 {} 生成失败,第 {}",
if let Some(debug_run) = image_debug_run.as_ref() { sheet_spec.sheet_id,
debug_run.record_sheet_request(&sheet_spec, attempt_index, sheet_prompt.as_str()); attempt_index + 1
} );
let generated = match create_openai_image_generation( if let Some(ref debug_run) = debug_run {
&http_client, debug_run.record_sheet_request(
&settings, sheet_spec,
sheet_prompt.as_str(), attempt_index,
Some(PUZZLE_CLEAR_ATLAS_NEGATIVE_PROMPT), sheet_prompt.as_str(),
PUZZLE_CLEAR_ATLAS_GENERATION_SIZE, );
1, }
&[], let generated = match create_openai_image_generation(
failure_context.as_str(), &client,
) &settings,
.await sheet_prompt.as_str(),
{ Some(PUZZLE_CLEAR_ATLAS_NEGATIVE_PROMPT),
Ok(generated) => generated, PUZZLE_CLEAR_ATLAS_GENERATION_SIZE,
Err(error) 1,
if attempt_index + 1 < PUZZLE_CLEAR_SHEET_GENERATION_MAX_ATTEMPTS &[],
&& is_retryable_puzzle_clear_sheet_generation_error(&error) => failure_context.as_str(),
{ )
if let Some(debug_run) = image_debug_run.as_ref() { .await
debug_run.record_sheet_generation_error(&sheet_spec, attempt_index, &error); {
Ok(generated) => generated,
Err(error)
if attempt_index + 1
< PUZZLE_CLEAR_SHEET_GENERATION_MAX_ATTEMPTS
&& is_retryable_puzzle_clear_sheet_generation_error(&error) =>
{
if let Some(ref debug_run) = debug_run {
debug_run.record_sheet_generation_error(
sheet_spec,
attempt_index,
&error,
);
}
tracing::warn!(
provider = PUZZLE_CLEAR_CREATION_PROVIDER,
sheet_id = sheet_spec.sheet_id,
attempt = attempt_index + 1,
generation_error = %error.body_text(),
"拼消消素材 sheet 生成遇到可重试上游错误,准备重试"
);
continue;
}
Err(error) => {
return Err(error);
}
};
let task_id = generated.task_id;
let actual_prompt = generated.actual_prompt;
let image = generated.images.into_iter().next().ok_or_else(|| {
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
"provider": "vector-engine",
"message": format!("拼消消素材 {} 生成成功但未返回图片。", sheet_spec.sheet_id),
}))
})?;
if let Some(ref debug_run) = debug_run {
debug_run.record_sheet_attempt_image(
sheet_spec,
attempt_index,
task_id.as_str(),
actual_prompt.as_deref(),
&image,
);
debug_run.record_sheet_accepted(
sheet_spec,
task_id.as_str(),
&image,
);
}
return Ok(PuzzleClearGeneratedSheet {
spec: *sheet_spec,
prompt: sheet_prompt.clone(),
task_id,
image,
});
} }
tracing::warn!( Err(AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
provider = PUZZLE_CLEAR_CREATION_PROVIDER, "provider": PUZZLE_CLEAR_CREATION_PROVIDER,
sheet_id = sheet_spec.sheet_id, "message": format!("拼消消素材 {} 多次生成后仍未得到可切图集。", sheet_spec.sheet_id),
attempt = attempt_index + 1, })))
generation_error = %error.body_text(),
"拼消消素材 sheet 生成遇到可重试上游错误,准备重试"
);
continue;
} }
})
.collect();
let results = futures_util::future::join_all(futures).await;
for result in results {
match result {
Ok(sheet) => generated_sheets.push(sheet),
Err(error) => { Err(error) => {
if let Some(debug_run) = image_debug_run.as_ref() {
debug_run.record_sheet_generation_error(&sheet_spec, attempt_index, &error);
}
return Err(puzzle_clear_error_response( return Err(puzzle_clear_error_response(
request_context, request_context,
PUZZLE_CLEAR_CREATION_PROVIDER, PUZZLE_CLEAR_CREATION_PROVIDER,
error, error,
)); ));
} }
};
let task_id = generated.task_id;
let actual_prompt = generated.actual_prompt;
let image = generated.images.into_iter().next().ok_or_else(|| {
puzzle_clear_error_response(
request_context,
PUZZLE_CLEAR_CREATION_PROVIDER,
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
"provider": "vector-engine",
"message": format!("拼消消素材 {} 生成成功但未返回图片。", sheet_spec.sheet_id),
})),
)
})?;
if let Some(debug_run) = image_debug_run.as_ref() {
debug_run.record_sheet_attempt_image(
&sheet_spec,
attempt_index,
task_id.as_str(),
actual_prompt.as_deref(),
&image,
);
debug_run.record_sheet_accepted(&sheet_spec, task_id.as_str(), &image);
} }
accepted_sheet = Some(PuzzleClearGeneratedSheet {
spec: sheet_spec,
prompt: sheet_prompt.clone(),
task_id,
image,
});
break;
} }
let Some(accepted_sheet) = accepted_sheet else {
return Err(puzzle_clear_error_response(
request_context,
PUZZLE_CLEAR_CREATION_PROVIDER,
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
"provider": PUZZLE_CLEAR_CREATION_PROVIDER,
"message": format!("拼消消素材 {} 多次生成后仍未得到可切图集。", sheet_spec.sheet_id),
})),
));
};
generated_sheets.push(accepted_sheet);
} }
let mut slices = Vec::new(); let mut slices = Vec::new();