fix(core): 交叉验证修复 — 单镜改稿按 DB 真实镜数(防截镜误扣)+ 模型框点外关闭选择器
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) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
03e7949307
commit
c3306bcac3
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user