feat(ai): 实体提取解耦 — 定稿剧本后独立提取角色/场景 + 商品参考图永远带上

根因:实体跟脚本生成耦合,模型不稳(尤其改稿 revise)常丢实体 → 角色提不出、
参考图全空 → 故事板/视频退化纯文生图(用户 demo 全错的真因)。

- 新 skill ecommerce-entity-extract(按 skill-creator 法写):只提角色+场景,
  角色铁律=穿整套衣服/空手/不带与商品同类物/不暴露;商品不提。4 项目实测稳定产出。
- extract_entities_for_project + /extract-entities 端点:读定稿剧本→提实体→
  落库覆盖 metadata + 回填每镜 entity_refs(提取为唯一权威来源,脚本生成完全不动)。
- 商品参考图永远带上:_storyboard_reference_images(视频继承)改为无条件带
  商品三视图→主图兜底,不再依赖 entity_refs 里有没有商品实体。
- 创建商品后端强制要主图(堵兜底洞:无图商品会让下游参考图彻底落空)。

实测:杂鱼煲(原实体0)→6实体,每镜参考图齐(角色+商品+场景),不再文生图。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-19 17:37:18 +08:00
co-authored by Claude Opus 4.8
parent 901d6920f1
commit 827fa7fa54
6 changed files with 502 additions and 17 deletions
+13
View File
@@ -19,6 +19,7 @@ from apps.ai.services import (
DEFAULT_VOICEOVER_VOICE,
VOICEOVER_VOICES,
create_export_job,
extract_entities_for_project,
generate_base_asset,
generate_person_triview,
generate_storyboard_frame,
@@ -238,6 +239,18 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
project.save(update_fields=["current_stage", "status", "updated_at"])
return Response(ScriptVersionSerializer(script).data)
@action(detail=True, methods=["post"], url_path="extract-entities")
def extract_entities_action(self, request, pk=None):
"""从已定稿脚本提取角色 / 场景实体(独立步,进资产阶段时调)。AI 读剧本 → 角色 / 场景 + 每镜 refs,
落库覆盖 project.metadata + 每镜 entity_refs;**商品不提**(参考图层用真实主图 / 三视图无条件带上)。
前端进资产页蒙版上「只提取 / 提取+生成」按钮点的就是它(生成由前端按返回实体循环调 generate-base-asset)。"""
project = self.get_object()
try:
result = extract_entities_for_project(project=project, user=request.user)
except ValueError as exc: # 无脚本 / 无模型 / 额度不足 / 解析失败 等,立即反馈
return Response({"detail": str(exc)}, status=status.HTTP_400_BAD_REQUEST)
return Response(result)
@action(detail=True, methods=["post"], url_path="generate-base-asset")
def generate_base_asset_action(self, request, pk=None):
require_worker()