Enable Parallel image Gen
This commit is contained in:
@@ -1186,103 +1186,120 @@ async fn maybe_prepare_puzzle_clear_assets_inner(
|
||||
let http_client = build_openai_image_http_client(&settings).map_err(|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());
|
||||
for sheet_spec in sheet_specs {
|
||||
let sheet_prompt = build_puzzle_clear_atlas_prompt(
|
||||
payload.theme_prompt.as_deref().unwrap_or_default(),
|
||||
&sheet_spec,
|
||||
);
|
||||
let mut accepted_sheet = None;
|
||||
for attempt_index in 0..PUZZLE_CLEAR_SHEET_GENERATION_MAX_ATTEMPTS {
|
||||
let failure_context = format!(
|
||||
"拼消消素材 {} 生成失败,第 {} 次",
|
||||
sheet_spec.sheet_id,
|
||||
attempt_index + 1
|
||||
);
|
||||
if let Some(debug_run) = image_debug_run.as_ref() {
|
||||
debug_run.record_sheet_request(&sheet_spec, attempt_index, sheet_prompt.as_str());
|
||||
}
|
||||
let generated = match create_openai_image_generation(
|
||||
&http_client,
|
||||
&settings,
|
||||
sheet_prompt.as_str(),
|
||||
Some(PUZZLE_CLEAR_ATLAS_NEGATIVE_PROMPT),
|
||||
PUZZLE_CLEAR_ATLAS_GENERATION_SIZE,
|
||||
1,
|
||||
&[],
|
||||
failure_context.as_str(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
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(debug_run) = image_debug_run.as_ref() {
|
||||
debug_run.record_sheet_generation_error(&sheet_spec, attempt_index, &error);
|
||||
{
|
||||
let futures: Vec<_> = sheet_specs
|
||||
.iter()
|
||||
.map(|sheet_spec| {
|
||||
let sheet_prompt = build_puzzle_clear_atlas_prompt(theme_prompt, sheet_spec);
|
||||
let client = http_client.clone();
|
||||
let settings = settings.clone();
|
||||
let debug_run = image_debug_run.clone();
|
||||
async move {
|
||||
for attempt_index in 0..PUZZLE_CLEAR_SHEET_GENERATION_MAX_ATTEMPTS {
|
||||
let failure_context = format!(
|
||||
"拼消消素材 {} 生成失败,第 {} 次",
|
||||
sheet_spec.sheet_id,
|
||||
attempt_index + 1
|
||||
);
|
||||
if let Some(ref debug_run) = debug_run {
|
||||
debug_run.record_sheet_request(
|
||||
sheet_spec,
|
||||
attempt_index,
|
||||
sheet_prompt.as_str(),
|
||||
);
|
||||
}
|
||||
let generated = match create_openai_image_generation(
|
||||
&client,
|
||||
&settings,
|
||||
sheet_prompt.as_str(),
|
||||
Some(PUZZLE_CLEAR_ATLAS_NEGATIVE_PROMPT),
|
||||
PUZZLE_CLEAR_ATLAS_GENERATION_SIZE,
|
||||
1,
|
||||
&[],
|
||||
failure_context.as_str(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
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!(
|
||||
provider = PUZZLE_CLEAR_CREATION_PROVIDER,
|
||||
sheet_id = sheet_spec.sheet_id,
|
||||
attempt = attempt_index + 1,
|
||||
generation_error = %error.body_text(),
|
||||
"拼消消素材 sheet 生成遇到可重试上游错误,准备重试"
|
||||
);
|
||||
continue;
|
||||
Err(AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
|
||||
"provider": PUZZLE_CLEAR_CREATION_PROVIDER,
|
||||
"message": format!("拼消消素材 {} 多次生成后仍未得到可切图集。", sheet_spec.sheet_id),
|
||||
})))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let results = futures_util::future::join_all(futures).await;
|
||||
for result in results {
|
||||
match result {
|
||||
Ok(sheet) => generated_sheets.push(sheet),
|
||||
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(
|
||||
request_context,
|
||||
PUZZLE_CLEAR_CREATION_PROVIDER,
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user