fix: gate AI character safety words

This commit is contained in:
2026-05-26 10:23:00 +08:00
parent a3a9ed90e2
commit daec523dec
2 changed files with 75 additions and 8 deletions

View File

@@ -5308,7 +5308,7 @@ def _translate_text_sync(text: str, target: Literal["en", "zh"] = "en", *, max_t
return text
target_label = "English" if target == "en" else "Simplified Chinese"
prompt = (
f"Translate the following TikTok ad planning text into concise natural {target_label}. "
f"Translate the following creative generation planning text into concise natural {target_label}. "
"Preserve concrete product, camera, subject, timing, and structure details. "
"Do not add commentary, markdown, quotes, or explanations.\n\n"
f"Input:\n{text}"
@@ -5412,21 +5412,75 @@ def _parse_creative_copy_response(raw: str, req: CreativeCopyReq) -> CreativeCop
return CreativeCopyResp(model=REWRITE_MODEL if LLM_API_KEY else "fallback", variants=variants)
_NO_PERSON_INTENT_RE = re.compile(
r"("
r"无人|无人物|没有人|没有人物|不要人|不要人物|不出现人|不出现人物|无行人|无路人|空无一人|"
r"no\s+(?:people|person|human|humans|faces?|characters?|crowd|bystanders)|"
r"without\s+(?:people|person|human|humans|faces?|characters?|crowd|bystanders)|"
r"empty\s+(?:scene|street|room|space)"
r")",
re.I,
)
_PERSON_INTENT_RE = re.compile(
r"("
r"人物|人像|真人|模特|男生|女生|男人|女人|男士|女士|女孩|男孩|少年|少女|青年|"
r"主播|演员|艺人|角色|数字人|虚拟人|博主|网红|行人|路人|人群|背影|侧脸|正脸|"
r"面部|脸部|脸|表情|肖像|全身|半身|"
r"\b(?:person|people|human|humans|model|woman|man|girl|boy|male|female|actor|actress|"
r"presenter|host|influencer|character|avatar|portrait|face|facial|full[- ]body|crowd|"
r"pedestrian|bystander|passerby)\b"
r")",
re.I,
)
def _prompt_has_person_intent(*parts: str) -> bool:
text = "\n".join(part for part in parts if part).strip()
if not text or _NO_PERSON_INTENT_RE.search(text):
return False
return bool(_PERSON_INTENT_RE.search(text))
def _prompt_person_guard(req: PromptPolishReq) -> str:
if req.mode not in {"image", "video", "general"}:
return ""
if _prompt_has_person_intent(req.text, req.system_prompt):
return (
"The user requested a person, portrait, model, or character subject. "
"Describe any such subject as a fully fictional synthetic AI character or virtual avatar, "
"not based on any real person, celebrity, public figure, or identifiable private individual. "
"Avoid real-person likeness, biometric identity, endorsement, or impersonation.\n"
)
return (
"The user did not request a person or character subject. Preserve the original object-only, "
"scene-only, or product-only composition. Do not introduce people, faces, bodies, hands, "
"avatars, characters, crowds, bystanders, or human silhouettes.\n"
)
def _prompt_polish_fallback(req: PromptPolishReq) -> PromptPolishResp:
text = req.text.strip()
base = _ensure_english(text) if req.target_language == "en" else text
base = re.sub(r"\s+", " ", base).strip()
base = re.sub(r"[。.!?]+$", "", base).strip()
person_intent = _prompt_has_person_intent(req.text, req.system_prompt)
person_guard = (
" Use a fully fictional synthetic AI character, not based on any real person, celebrity, public figure, or identifiable private individual."
if person_intent
else " Preserve the original object-only, scene-only, or product-only composition; do not introduce people, faces, bodies, hands, avatars, characters, crowds, bystanders, or human silhouettes."
)
if req.mode == "video":
polished = (
f"{base}. Smooth camera movement, clear subject continuity, stable composition, "
"natural motion, coherent lighting, no subtitles, no watermark."
f"natural motion, coherent lighting, no subtitles, no watermark.{person_guard}"
)
elif req.mode in {"general", "chat"}:
polished = base
else:
polished = (
f"{base}. Detailed visual prompt, clear main subject, coherent composition, "
"natural lighting, refined color palette, high-quality details."
f"natural lighting, refined color palette, high-quality details.{person_guard}"
)
return PromptPolishResp(model="fallback", text=polished[:1800])
@@ -5458,6 +5512,7 @@ def polish_prompt(req: PromptPolishReq) -> PromptPolishResp:
"Do not add medical, wellness, or advertising claims unless the user asked for them.\n"
"Improve concrete visual details, composition, lighting, camera language, materials, mood, and quality.\n"
"Return only the rewritten prompt. No markdown, labels, JSON, quotes, explanation, or alternatives.\n"
f"{_prompt_person_guard(req)}"
)
if req.mode == "chat":
prompt = (
@@ -5470,7 +5525,7 @@ def polish_prompt(req: PromptPolishReq) -> PromptPolishResp:
if req.mode == "video":
prompt += (
"For video, describe motion, timing, camera movement, continuity, and what changes over time. "
"If people are not essential, prefer no recognizable faces or distant/turned-away background people to reduce video safety risk.\n"
"Do not add people for scale, atmosphere, lifestyle context, or background decoration unless the input explicitly asked for people.\n"
)
if user_system:
prompt += f"\nUser-selected polishing guidance:\n{user_system[:1000]}\n"