优化全能创作
This commit is contained in:
@@ -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 []
|
||||
|
||||
Reference in New Issue
Block a user