feat: add resource library and real image workflow
This commit is contained in:
@@ -34,6 +34,7 @@ with workflow.unsafe.imports_passed_through():
|
||||
from app.workers.activities.scene_activities import run_scene_activity
|
||||
from app.workers.activities.texture_activities import run_texture_activity
|
||||
from app.workers.activities.tryon_activities import prepare_model_activity, run_tryon_activity
|
||||
from app.workers.workflows.timeout_policy import DEFAULT_ACTIVITY_TIMEOUT, activity_timeout_for_task_queue
|
||||
from app.workers.workflows.types import (
|
||||
MockActivityResult,
|
||||
PipelineWorkflowInput,
|
||||
@@ -44,8 +45,6 @@ with workflow.unsafe.imports_passed_through():
|
||||
WorkflowFailureActivityInput,
|
||||
)
|
||||
|
||||
|
||||
ACTIVITY_TIMEOUT = timedelta(seconds=30)
|
||||
ACTIVITY_RETRY_POLICY = RetryPolicy(
|
||||
initial_interval=timedelta(seconds=1),
|
||||
backoff_coefficient=2.0,
|
||||
@@ -87,6 +86,8 @@ class MidEndPipelineWorkflow:
|
||||
# current_step 用于失败时记录“最后跑到哪一步”。
|
||||
current_step = WorkflowStepName.PREPARE_MODEL
|
||||
try:
|
||||
# prepare_model / tryon / scene 这三段和低端流程共享同一套 activity,
|
||||
# 区别只在于中端流程后面还会继续进入 texture / face / fusion / review。
|
||||
prepared = await workflow.execute_activity(
|
||||
prepare_model_activity,
|
||||
StepActivityInput(
|
||||
@@ -99,11 +100,12 @@ class MidEndPipelineWorkflow:
|
||||
scene_ref_asset_id=payload.scene_ref_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_CONTROL_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_CONTROL_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
current_step = WorkflowStepName.TRYON
|
||||
# tryon 产出基础换装图,后面的所有增强步骤都以它为起点。
|
||||
tryon_result = await workflow.execute_activity(
|
||||
run_tryon_activity,
|
||||
StepActivityInput(
|
||||
@@ -114,23 +116,37 @@ class MidEndPipelineWorkflow:
|
||||
garment_asset_id=payload.garment_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_IMAGE_GEN_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_IMAGE_GEN_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
current_step = WorkflowStepName.SCENE
|
||||
scene_result = await self._run_scene(payload, tryon_result.asset_id)
|
||||
scene_source_asset_id = tryon_result.asset_id
|
||||
if payload.scene_ref_asset_id is not None:
|
||||
current_step = WorkflowStepName.SCENE
|
||||
# scene 仍然是可选步骤。
|
||||
# 如果存在场景图,就先完成换背景,再把结果交给 texture / fusion;
|
||||
# 如果没有场景图,就直接把 tryon 结果当成“场景基底”继续流程。
|
||||
scene_result = await self._run_scene(payload, tryon_result.asset_id)
|
||||
scene_source_asset_id = scene_result.asset_id
|
||||
else:
|
||||
scene_result = tryon_result
|
||||
|
||||
current_step = WorkflowStepName.TEXTURE
|
||||
texture_result = await self._run_texture(payload, scene_result.asset_id)
|
||||
# texture 是复杂流独有步骤。
|
||||
# 它通常负责衣物纹理、材质细节或局部增强,输入是当前场景基底图。
|
||||
texture_result = await self._run_texture(payload, scene_source_asset_id)
|
||||
|
||||
current_step = WorkflowStepName.FACE
|
||||
# face 也是复杂流独有步骤。
|
||||
# 它在 texture 结果基础上做脸部修复/增强,产出供 fusion 合成的人像版本。
|
||||
face_result = await self._run_face(payload, texture_result.asset_id)
|
||||
|
||||
current_step = WorkflowStepName.FUSION
|
||||
fusion_result = await self._run_fusion(payload, scene_result.asset_id, face_result.asset_id)
|
||||
# fusion 负责把“场景基底”和“脸部增强结果”合成成候选成品。
|
||||
fusion_result = await self._run_fusion(payload, scene_source_asset_id, face_result.asset_id)
|
||||
|
||||
current_step = WorkflowStepName.QC
|
||||
# QC 和低端流程复用同一套 activity,但这里检查的是 fusion 产物。
|
||||
qc_result = await self._run_qc(payload, fusion_result.asset_id)
|
||||
if not qc_result.passed:
|
||||
await self._mark_failed(payload, current_step, qc_result.message)
|
||||
@@ -144,6 +160,8 @@ class MidEndPipelineWorkflow:
|
||||
current_step = WorkflowStepName.REVIEW
|
||||
# 这里通过 activity 把数据库里的订单状态更新成 waiting_review,
|
||||
# 同时创建 review_task,供 API 查询待审核列表。
|
||||
# review 是复杂流真正区别于低端流程的核心:
|
||||
# 在 export 前插入人工决策点,并支持按意见回流重跑。
|
||||
await workflow.execute_activity(
|
||||
mark_waiting_for_review_activity,
|
||||
ReviewWaitActivityInput(
|
||||
@@ -152,7 +170,7 @@ class MidEndPipelineWorkflow:
|
||||
candidate_asset_ids=qc_result.candidate_asset_ids,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_CONTROL_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_CONTROL_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -172,7 +190,7 @@ class MidEndPipelineWorkflow:
|
||||
comment=review_payload.comment,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_CONTROL_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_CONTROL_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -180,6 +198,7 @@ class MidEndPipelineWorkflow:
|
||||
current_step = WorkflowStepName.EXPORT
|
||||
# 如果审核人显式选了资产,就导出该资产;
|
||||
# 否则默认导出 QC 候选资产。
|
||||
# export 本身仍然和低端流程是同一个 activity。
|
||||
export_source_id = review_payload.selected_asset_id
|
||||
if export_source_id is None:
|
||||
export_source_id = (qc_result.candidate_asset_ids or [fusion_result.asset_id])[0]
|
||||
@@ -192,7 +211,7 @@ class MidEndPipelineWorkflow:
|
||||
source_asset_id=export_source_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_EXPORT_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_EXPORT_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
return {
|
||||
@@ -208,22 +227,30 @@ class MidEndPipelineWorkflow:
|
||||
# rerun 的核心思想是:
|
||||
# 把指定节点后的链路重新跑一遍,然后再次进入 QC 和 waiting_review。
|
||||
if review_payload.decision == ReviewDecision.RERUN_SCENE:
|
||||
current_step = WorkflowStepName.SCENE
|
||||
scene_result = await self._run_scene(payload, tryon_result.asset_id)
|
||||
# 从 scene 开始重跑意味着 scene / texture / face / fusion 全部重算。
|
||||
if payload.scene_ref_asset_id is not None:
|
||||
current_step = WorkflowStepName.SCENE
|
||||
scene_result = await self._run_scene(payload, tryon_result.asset_id)
|
||||
scene_source_asset_id = scene_result.asset_id
|
||||
else:
|
||||
scene_result = tryon_result
|
||||
scene_source_asset_id = tryon_result.asset_id
|
||||
current_step = WorkflowStepName.TEXTURE
|
||||
texture_result = await self._run_texture(payload, scene_result.asset_id)
|
||||
texture_result = await self._run_texture(payload, scene_source_asset_id)
|
||||
current_step = WorkflowStepName.FACE
|
||||
face_result = await self._run_face(payload, texture_result.asset_id)
|
||||
current_step = WorkflowStepName.FUSION
|
||||
fusion_result = await self._run_fusion(payload, scene_result.asset_id, face_result.asset_id)
|
||||
fusion_result = await self._run_fusion(payload, scene_source_asset_id, face_result.asset_id)
|
||||
elif review_payload.decision == ReviewDecision.RERUN_FACE:
|
||||
# 从 face 开始重跑时,scene / texture 结果保持不变。
|
||||
current_step = WorkflowStepName.FACE
|
||||
face_result = await self._run_face(payload, texture_result.asset_id)
|
||||
current_step = WorkflowStepName.FUSION
|
||||
fusion_result = await self._run_fusion(payload, scene_result.asset_id, face_result.asset_id)
|
||||
fusion_result = await self._run_fusion(payload, scene_source_asset_id, face_result.asset_id)
|
||||
elif review_payload.decision == ReviewDecision.RERUN_FUSION:
|
||||
# 从 fusion 重跑是最小范围回流,只重做最终合成。
|
||||
current_step = WorkflowStepName.FUSION
|
||||
fusion_result = await self._run_fusion(payload, scene_result.asset_id, face_result.asset_id)
|
||||
fusion_result = await self._run_fusion(payload, scene_source_asset_id, face_result.asset_id)
|
||||
|
||||
current_step = WorkflowStepName.QC
|
||||
qc_result = await self._run_qc(payload, fusion_result.asset_id)
|
||||
@@ -264,7 +291,7 @@ class MidEndPipelineWorkflow:
|
||||
scene_ref_asset_id=payload.scene_ref_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_IMAGE_GEN_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_IMAGE_GEN_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -280,7 +307,7 @@ class MidEndPipelineWorkflow:
|
||||
source_asset_id=source_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_POST_PROCESS_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_POST_PROCESS_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -296,7 +323,7 @@ class MidEndPipelineWorkflow:
|
||||
source_asset_id=source_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_POST_PROCESS_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_POST_PROCESS_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -318,7 +345,7 @@ class MidEndPipelineWorkflow:
|
||||
selected_asset_id=face_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_POST_PROCESS_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_POST_PROCESS_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -334,7 +361,7 @@ class MidEndPipelineWorkflow:
|
||||
source_asset_id=source_asset_id,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_QC_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=activity_timeout_for_task_queue(IMAGE_PIPELINE_QC_TASK_QUEUE),
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
@@ -355,6 +382,6 @@ class MidEndPipelineWorkflow:
|
||||
message=message,
|
||||
),
|
||||
task_queue=IMAGE_PIPELINE_CONTROL_TASK_QUEUE,
|
||||
start_to_close_timeout=ACTIVITY_TIMEOUT,
|
||||
start_to_close_timeout=DEFAULT_ACTIVITY_TIMEOUT,
|
||||
retry_policy=ACTIVITY_RETRY_POLICY,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user