优化全能创作

This commit is contained in:
Azmat@qq.com
2026-09-14 11:47:49 +08:00
parent 02e5dbfb60
commit 463613c0d7
7 changed files with 875 additions and 197 deletions
+148 -6
View File
@@ -37,7 +37,10 @@ from .creation_agent import (
_ASSET_CARD_LABELS,
apply_confirm_params,
apply_session_params,
emit_final_confirm_gate,
emit_prompt_gate,
is_greeting,
set_video_gate_stage,
submit_confirmed_image,
submit_confirmed_video,
)
@@ -144,6 +147,119 @@ def _pending_chat_question(conversation: CreationConversation) -> CreationMessag
return None
_STEP_CONTINUE_INSTRUCTIONS = {
"strategy": (
"用户已确认创作策略。现在只调用 write_plan 写方案卡(含完整 video_prompt 存档);"
"不要再写策略,不要调用 write_prompt,不要出片。"
),
"plan": (
"用户已确认视频方案。若尚未写出 Prompt,调用 write_prompt 展示出片 Prompt;"
"不要重写策略/方案,不要出积分确认卡或直接出片。"
),
"prompt": (
"用户已确认出片 Prompt。不要再写策略/方案/Prompt;"
"平台会出积分确认卡,等用户点开始生成。"
),
}
_STEP_REVISE_INSTRUCTIONS = {
"strategy": (
"用户要求修改创作策略。根据反馈只重新调用 write_strategy 写一版修订策略;"
"写完即停,不要同轮 write_plan / write_prompt。"
),
"plan": (
"用户要求修改视频方案。根据反馈只重新调用 write_plan 写一版修订方案"
"(含完整 video_prompt 存档);写完即停,不要同轮 write_prompt 或出片。"
),
"prompt": (
"用户要求修改出片 Prompt。根据反馈只重新调用 write_prompt 写一版修订 Prompt;"
"写完即停,不要出积分确认卡或直接出片。"
),
}
def _handle_step_confirm_answer(
conversation: CreationConversation,
*,
card: CreationMessage,
answers: dict,
user,
) -> tuple[JsonResponse | None, bool, str]:
"""处理步骤确认卡。返回 (短路径响应|None, force_creative, continuation_instruction)。"""
payload = dict(card.payload or {})
step = str(payload.get("step") or "").strip()
action = str(answers.get("step_action") or answers.get("action") or "").strip().lower()
feedback = str(answers.get("feedback") or "").strip()
# 兼容前端只传 confirm/revise 作为 answers 值
if action not in {"confirm", "revise"}:
raw = " ".join(str(v) for v in answers.values()).lower()
if "revise" in raw or "改" in raw:
action = "revise"
else:
action = "confirm"
payload["answers"] = {
"step_action": action,
**({"feedback": feedback} if feedback else {}),
}
payload["submitted"] = True
card.payload = payload
card.save(update_fields=["payload", "updated_at"])
if action == "revise":
set_video_gate_stage(conversation, step if step in {"strategy", "plan", "prompt"} else "clarify")
instruction = _STEP_REVISE_INSTRUCTIONS.get(
step,
"用户要求修改上一步产出。只重写被指出的那一步,不要跳到后续闸门。",
)
if feedback:
instruction = f"{instruction} 用户反馈:{feedback}"
return None, True, instruction
# confirm
if step == "strategy":
# 仍标 strategy,但打上已确认标记;write_plan 落库时会切到 plan
memory = dict(conversation.memory or {})
memory["stage"] = "strategy"
memory["strategy_confirmed"] = True
conversation.memory = memory
conversation.save(update_fields=["memory", "updated_at"])
return None, True, _STEP_CONTINUE_INSTRUCTIONS["strategy"]
if step == "plan":
emitted = emit_prompt_gate(conversation)
if not emitted:
# 缓存丢了:让 agent 补 write_prompt
return None, True, _STEP_CONTINUE_INSTRUCTIONS["plan"]
conversation.agent_status = CreationConversation.AgentStatus.AWAITING_USER
conversation.save(update_fields=["agent_status", "updated_at"])
return JsonResponse({
"conversation_id": str(conversation.id),
"agent_status": conversation.agent_status,
"messages": [CreationMessageSerializer(m).data for m in emitted],
}, status=200), False, ""
if step == "prompt":
confirm = emit_final_confirm_gate(conversation)
if confirm is None:
return None, True, _STEP_CONTINUE_INSTRUCTIONS["prompt"]
conversation.agent_status = CreationConversation.AgentStatus.AWAITING_USER
conversation.save(update_fields=["agent_status", "updated_at"])
credits = int((confirm.payload or {}).get("estimated_credits") or 0)
body = {
"conversation_id": str(conversation.id),
"agent_status": conversation.agent_status,
"messages": [CreationMessageSerializer(confirm).data],
}
if credits:
body["estimated_credits"] = credits
return JsonResponse(body, status=200), False, ""
# 未知 step:当普通继续
return None, True, "用户已确认上一步。继续推进创作,不要复述确认。"
class GenerateImageView(APIView):
"""独立生图(不绑项目)· 图片创作/模特图/平台套图共用 —— **异步**。
@@ -1560,7 +1676,18 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
pending = _pending_chat_question(conversation)
if pending is not None:
payload = dict(pending.payload or {})
if payload.get("phase") == "gate":
if payload.get("interaction") == "step_confirm":
# 用户对着步骤确认卡直接打字 = 修改意见
short, force_creative_turn, continuation_instruction = _handle_step_confirm_answer(
conversation,
card=pending,
answers={"step_action": "revise", "feedback": text},
user=request.user,
)
if short is not None:
return short
# 用户原文仍落库,方便回看;continuation 已带反馈
elif payload.get("phase") == "gate":
pending_fields = [item for item in (payload.get("pending_fields") or []) if isinstance(item, dict)]
primary_field = pending_fields[0] if pending_fields else {}
asset_types = [t for t in (primary_field.get("asset_types") or []) if t in TYPE_LABELS] or ["product"]
@@ -1779,13 +1906,28 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
# 追问卡是一次性的:重复提交会让同一个问题在上下文里出现两次答案
return JsonResponse({"detail": "这个问题已经回答过了"}, status=409)
payload = dict(card.payload or {})
payload["answers"] = answers
payload["submitted"] = True
card.payload = payload
card.save(update_fields=["payload", "updated_at"])
if payload.get("interaction") == "step_confirm":
short, force_creative_turn, continuation_instruction = _handle_step_confirm_answer(
conversation,
card=card,
answers=answers if isinstance(answers, dict) else {},
user=request.user,
)
if short is not None:
return short
text = ""
record_user_message = False
# force_creative / continuation 已设;跳过后面普通 elicit 逻辑
else:
payload["answers"] = answers
payload["submitted"] = True
card.payload = payload
card.save(update_fields=["payload", "updated_at"])
# 素材选择闸门:用户愿意时再展开列表;跳过则直接沿原任务继续。
if payload.get("phase") == "gate":
if payload.get("interaction") == "step_confirm":
pass # 已在上面处理
elif payload.get("phase") == "gate":
choice = str(answers.get("_asset_gate") or "").strip()
if choice == "send":
pending = payload.get("pending_fields") or []