refactor(core): 脚本收口——只留 agent 出稿,删旧散文路 + 单镜重跑改走 agent
删 /generate-script/ 端点 + generate_project_script + build_script_prompt + 旧单镜 build_segment_rerun_prompt;前端删静默兜底(agent 失败明确报错,不再掉回旧路)+ onGenerateScript prop/api。rerun-script-segment 改用 agent 单镜逻辑(regenerate_segment_via_agent:读全脚本上下文/保留其余镜/落新版本)。根因:旧路不产 script_entities/entity_refs,下游故事板/视频参考图断线→图飘。测试:删 3 个旧 generate 用例 + 重写 rerun 为 agent 版,ai+projects 23 测试除 4 个既有 base-asset 失败外全绿。 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
0695c36f4c
commit
1ecb186ddf
@@ -673,3 +673,68 @@ def _load_base_draft(project, base_version_id: str) -> dict | None:
|
||||
return json.loads(version.content)
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
|
||||
|
||||
def regenerate_segment_via_agent(*, project, user, model_config: ModelConfig, segment, instruction: str = ""):
|
||||
"""非流式·精准改一镜(「场次刷新」按钮复用 agent 单镜逻辑):读全脚本上下文,只重写该镜,落新 ScriptVersion。
|
||||
与 stream_script_agent 的 target_index 分支同源,但同步返回(不走 SSE)。计费 reserve→charge/release 闭环。"""
|
||||
from django.db import transaction
|
||||
|
||||
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("基准脚本无法解析,无法精准改镜")
|
||||
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", []))
|
||||
if not (0 <= target_index < seg_n):
|
||||
raise ValueError(f"镜号越界:第 {target_index + 1} 镜(共 {seg_n} 镜)")
|
||||
|
||||
messages = build_agent_messages(
|
||||
project=project,
|
||||
mode="revise",
|
||||
user_prompt=instruction,
|
||||
selling_point_ids=None,
|
||||
base_draft=base_draft,
|
||||
aspect_ratio=aspect_ratio,
|
||||
total_duration=total_duration,
|
||||
target_index=target_index,
|
||||
)
|
||||
task = create_ai_task(
|
||||
project=project,
|
||||
user=user,
|
||||
task_type=AITask.Type.SCRIPT_OPTIMIZATION,
|
||||
model_config=model_config,
|
||||
request_payload={
|
||||
"model": model_config.name,
|
||||
"endpoint": model_config.endpoint,
|
||||
"mode": "revise",
|
||||
"target_index": target_index,
|
||||
},
|
||||
)
|
||||
reservation = task.credit_reservation
|
||||
try:
|
||||
task.status = AITask.Status.SUBMITTED
|
||||
task.submitted_at = timezone.now()
|
||||
task.save(update_fields=["status", "submitted_at", "updated_at"])
|
||||
provider = build_provider(model_config)
|
||||
response = provider.chat_completion(model=model_config.name, endpoint=model_config.endpoint, messages=messages)
|
||||
raw = provider.extract_text(response)
|
||||
draft = normalize_draft(raw, aspect_ratio=aspect_ratio, total_duration=total_duration)
|
||||
draft = _merge_single_segment(base_draft, draft, target_index, aspect_ratio, total_duration)
|
||||
with transaction.atomic():
|
||||
task.status = AITask.Status.SUCCEEDED
|
||||
task.response_payload = {"raw": raw[:8000]}
|
||||
task.actual_cost = task.estimated_cost
|
||||
task.completed_at = timezone.now()
|
||||
task.save(update_fields=["status", "response_payload", "actual_cost", "completed_at", "updated_at"])
|
||||
charge_reserved_credit(reservation=reservation, actual_amount=task.actual_cost)
|
||||
script = persist_script_draft(project=project, user=user, task=task, draft=draft, source="revise")
|
||||
return script
|
||||
except Exception:
|
||||
_fail_task(task, reservation, "单镜重跑失败")
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user