fix: gate AI character safety words
This commit is contained in:
63
api/main.py
63
api/main.py
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user