添加艾特角色功能

This commit is contained in:
Azmat@qq.com
2026-09-17 18:31:29 +08:00
parent 5df038c635
commit abccf4393a
18 changed files with 2769 additions and 182 deletions
+51 -7
View File
@@ -38,6 +38,7 @@ from .creation import (
from .creation_agent import (
_ASSET_CARD_LABELS,
_RESTART_CONTINUATION,
apply_cast_relation_choice,
apply_pain_point_direction,
apply_confirm_params,
apply_restart_intent,
@@ -288,6 +289,14 @@ def _store_click_swap_sequence(conversation: CreationConversation, value: str) -
)
def _mark_product_source_resolved(conversation: CreationConversation) -> None:
"""用户选择跳过、自动推荐或直接描述商品后,不重复弹同一个商品闸门。"""
memory = dict(conversation.memory or {})
memory["product_source_resolved"] = True
conversation.memory = memory
conversation.save(update_fields=["memory", "updated_at"])
_STEP_CONTINUE_INSTRUCTIONS = {
"strategy": (
"用户已确认创作策略。现在只调用 write_plan 写方案卡(含完整 video_prompt 存档);"
@@ -1928,6 +1937,7 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
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"]
is_product_gate = "product" in asset_types
# 1. 用户明确在打字说「发列表/发给我/发卡片/打开列表」
if _WANTS_CARD_RE.search(text):
@@ -1981,6 +1991,8 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
payload["answered_via"] = "chat"
pending.payload = payload
pending.save(update_fields=["payload", "updated_at"])
if is_product_gate:
_mark_product_source_resolved(conversation)
force_creative_turn = True
if hits:
@@ -1999,6 +2011,8 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
payload["answered_via"] = "chat"
pending.payload = payload
pending.save(update_fields=["payload", "updated_at"])
if is_product_gate:
_mark_product_source_resolved(conversation)
force_creative_turn = True
continuation_instruction = (
@@ -2037,6 +2051,8 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
payload["answered_via"] = "chat"
pending.payload = payload
pending.save(update_fields=["payload", "updated_at"])
if is_product_gate:
_mark_product_source_resolved(conversation)
force_creative_turn = True
else:
@@ -2212,6 +2228,17 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
sequence = str(answers.get("sku_sequence") or "").strip()
if not sequence:
return JsonResponse({"detail": "请填写要展示的款式和切换顺序"}, status=400)
if payload.get("topic") == "cast_relation":
choice = str(answers.get("cast_relation") or "").strip()
valid_choices = {
str(option.get("value") or "")
for field in (payload.get("fields") or [])
if isinstance(field, dict) and field.get("key") == "cast_relation"
for option in (field.get("options") or [])
if isinstance(option, dict)
}
if not choice or choice not in valid_choices:
return JsonResponse({"detail": "请选择共同出镜或一位主讲角色"}, status=400)
payload["answers"] = answers
payload["submitted"] = True
card.payload = payload
@@ -2278,6 +2305,20 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
record_user_message = False
force_creative_turn = True
continuation_instruction = _store_click_swap_sequence(conversation, sequence)
elif payload.get("topic") == "cast_relation":
relation = apply_cast_relation_choice(
conversation,
str(answers.get("cast_relation") or ""),
)
if not relation:
return JsonResponse({"detail": "这个角色选项已经失效,请重新选择"}, status=400)
text = ""
record_user_message = False
force_creative_turn = True
continuation_instruction = (
f"商家已确认出镜安排:【{relation}】。保留全部已锁定角色,直接继续原任务;"
"后续策略、脚本、分镜和视频分段都严格保持该人物关系,不要再次追问。"
)
elif payload.get("interaction") == "person_source_gate":
source = str(answers.get("person_source") or "").strip()
if source == "platform_generate":
@@ -2322,10 +2363,12 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
)
elif payload.get("phase") == "gate":
choice = str(answers.get("_asset_gate") or "").strip()
pending = payload.get("pending_fields") or []
primary_field = pending[0] if pending else {}
gate_types = [item for item in (primary_field.get("asset_types") or []) if item in TYPE_LABELS] or ["product"]
is_product_gate = "product" in gate_types
if choice == "send":
pending = payload.get("pending_fields") or []
primary_field = pending[0] if pending else {}
types = [t for t in (primary_field.get("asset_types") or []) if t in TYPE_LABELS] or ["product"]
types = gate_types
pick_field = dict(primary_field)
pick_field["label"] = _ASSET_CARD_LABELS.get(
types[0], _ASSET_CARD_LABELS.get("asset", "请选择素材")
@@ -2352,10 +2395,7 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
"messages": [CreationMessageSerializer(pick).data],
}, status=200)
elif choice == "auto":
pending = payload.get("pending_fields") or []
primary_field = pending[0] if pending else {}
types = [item for item in (primary_field.get("asset_types") or []) if item in TYPE_LABELS] or ["product"]
hits = search_mentions(conversation.team, q="", types=types, limit=1)
hits = search_mentions(conversation.team, q="", types=gate_types, limit=1)
if hits:
refs = list(refs)
refs.append(hits[0])
@@ -2369,12 +2409,16 @@ class CreationConversationViewSet(TeamScopedViewSetMixin, ModelViewSet):
text = ""
record_user_message = False
force_creative_turn = True
if is_product_gate:
_mark_product_source_resolved(conversation)
else:
# 卡片本身已经记录了用户的选择。不要再伪造一条黑色用户气泡;
# 继续原任务,并明确告诉模型不要再次追问同一项素材。
text = ""
record_user_message = False
force_creative_turn = True
if is_product_gate:
_mark_product_source_resolved(conversation)
continuation_instruction = (
"用户刚选择暂不添加这项素材。接受这个选择,按会话里已有的需求和合理默认继续原任务。"
"先用一句自然的话承接,随后直接推进创作;不要再次追问同一素材,不要只说收到或有需要再说。"