From c3306bcac348d1e09711a30ea6c3922ff2921438 Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Wed, 17 Jun 2026 22:15:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=E4=BA=A4=E5=8F=89=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E4=BF=AE=E5=A4=8D=20=E2=80=94=20=E5=8D=95=E9=95=9C?= =?UTF-8?q?=E6=94=B9=E7=A8=BF=E6=8C=89=20DB=20=E7=9C=9F=E5=AE=9E=E9=95=9C?= =?UTF-8?q?=E6=95=B0(=E9=98=B2=E6=88=AA=E9=95=9C=E8=AF=AF=E6=89=A3)+=20?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E6=A1=86=E7=82=B9=E5=A4=96=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit critical:regenerate_segment_via_agent 改用 _draft_from_version 从 DB ScriptSegment 行重建基准稿(原读 stale content,用户增删镜后 normalize 会按 stale total_duration 截掉真实镜还照扣费)。低危:模型框容器补 chat-model-pick class,点外关闭选择器生效。 Co-Authored-By: Claude Opus 4.8 (1M context) --- core/backend/apps/ai/script_agent.py | 38 ++++++++++++++++++++++----- core/frontend/src/routes/pipeline.tsx | 2 +- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/core/backend/apps/ai/script_agent.py b/core/backend/apps/ai/script_agent.py index f1facb1..4e3447b 100644 --- a/core/backend/apps/ai/script_agent.py +++ b/core/backend/apps/ai/script_agent.py @@ -675,6 +675,35 @@ def _load_base_draft(project, base_version_id: str) -> dict | None: return None +def _draft_from_version(version) -> dict: + """从 ScriptVersion 的 DB 行(segments + metadata)重建 ScriptDraft —— 比解析可能已 stale 的 content 可靠 + (用户增删/改镜后 content 不一定同步)。total_duration 按真实镜数算,避免 normalize 按 stale 值截/补镜。""" + meta = version.metadata or {} + segs = list(version.segments.order_by("sort_order")) + return { + "hook": meta.get("hook", ""), + "tone": meta.get("tone", ""), + "aspect_ratio": meta.get("aspect_ratio", "9:16"), + "total_duration": max(int(meta.get("total_duration") or 0), 15 * len(segs)) or 60, + "segment_count": len(segs), + "entities": meta.get("entities", []), + "segments": [ + { + "index": s.sort_order, + "duration": s.duration_seconds or 15, + "role": s.role or "", + "narration": s.narration or "", + "speaker": s.speaker or None, + "visual": s.visual_prompt or "", + "product_exposure": s.product_exposure or "", + "entity_refs": s.entity_refs or [], + "dialogue": s.dialogue or [], + } + for s in segs + ], + } + + def regenerate_segment_via_agent(*, project, user, model_config: ModelConfig, segment, instruction: str = ""): """非流式·精准改一镜(「场次刷新」按钮复用 agent 单镜逻辑):读全脚本上下文,只重写该镜,落新 ScriptVersion。 与 stream_script_agent 的 target_index 分支同源,但同步返回(不走 SSE)。计费 reserve→charge/release 闭环。""" @@ -683,16 +712,13 @@ def regenerate_segment_via_agent(*, project, user, model_config: ModelConfig, se from apps.ai.services import build_provider, create_ai_task from apps.billing.services.ledger import charge_reserved_credit - base_version = segment.script_version - base_draft = _load_base_draft(project, str(base_version.id)) - if base_draft is None: - raise ValueError("基准脚本无法解析,无法精准改镜") + base_draft = _draft_from_version(segment.script_version) # 用 DB 行重建基准,别用可能 stale 的 content target_index = segment.sort_order aspect_ratio = (base_draft.get("aspect_ratio") or "9:16").strip() - total_duration = base_draft.get("total_duration") or 60 - seg_n = len(base_draft.get("segments", [])) + seg_n = len(base_draft.get("segments") or []) if not (0 <= target_index < seg_n): raise ValueError(f"镜号越界:第 {target_index + 1} 镜(共 {seg_n} 镜)") + total_duration = base_draft["total_duration"] # 已按真实镜数算,normalize 不会截掉用户增删后的镜 messages = build_agent_messages( project=project, diff --git a/core/frontend/src/routes/pipeline.tsx b/core/frontend/src/routes/pipeline.tsx index 5b34f3c..bee0147 100644 --- a/core/frontend/src/routes/pipeline.tsx +++ b/core/frontend/src/routes/pipeline.tsx @@ -2279,7 +2279,7 @@ export function PipelinePage(props: { {/* 模型选择小按钮(输入框下方,对齐 ChatGPT/Lovart)· 复用 restraint chip 下拉,向上展开 */} {textModels && textModels.length > 0 ? ( -
+