Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import os, html
|
| 2 |
import gradio as gr
|
| 3 |
from openai import OpenAI
|
| 4 |
|
|
@@ -6,28 +6,34 @@ API_KEY = os.getenv("OPENAI_API_KEY")
|
|
| 6 |
MODEL_NAME = "gpt-4o-mini"
|
| 7 |
client = OpenAI(api_key=API_KEY)
|
| 8 |
|
| 9 |
-
#
|
| 10 |
-
SYSTEM_PROMPT = """You are a playful
|
| 11 |
-
Goal: Produce EXACTLY ONE cute,
|
| 12 |
|
| 13 |
Creative balance:
|
| 14 |
-
- Inspiration source (山海经 / 迪士尼 / 哈利波特 / 生活) drives the
|
| 15 |
-
- User inputs (species
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
-
|
| 20 |
-
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
-
|
| 27 |
-
-
|
| 28 |
-
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
Name — short meaning
|
| 32 |
Quote: “...” — Attribution
|
| 33 |
"""
|
|
@@ -35,18 +41,73 @@ Quote: “...” — Attribution
|
|
| 35 |
def build_prompt(species, look, personality, gender, language, inspiration):
|
| 36 |
return f"""
|
| 37 |
Requested language: {language}
|
| 38 |
-
|
| 39 |
-
|
| 40 |
- Species: {species or '(unspecified)'}
|
| 41 |
- Appearance: {look or '(unspecified)'}
|
| 42 |
- Personality: {personality or '(unspecified)'}
|
| 43 |
- Gender: {gender}
|
| 44 |
|
| 45 |
Task:
|
| 46 |
-
1) Create EXACTLY ONE cute pet name (≤12-word meaning).
|
| 47 |
-
2) Then
|
|
|
|
| 48 |
"""
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
def generate_name(species, look, personality, gender, language, inspiration):
|
| 51 |
try:
|
| 52 |
prompt = build_prompt(
|
|
@@ -57,7 +118,7 @@ def generate_name(species, look, personality, gender, language, inspiration):
|
|
| 57 |
)
|
| 58 |
resp = client.chat.completions.create(
|
| 59 |
model=MODEL_NAME,
|
| 60 |
-
temperature=0.
|
| 61 |
top_p=0.95,
|
| 62 |
max_tokens=280,
|
| 63 |
messages=[
|
|
@@ -65,13 +126,15 @@ def generate_name(species, look, personality, gender, language, inspiration):
|
|
| 65 |
{"role": "user", "content": prompt}
|
| 66 |
]
|
| 67 |
)
|
| 68 |
-
|
|
|
|
|
|
|
| 69 |
except Exception as e:
|
| 70 |
return f"⚠️ 出错:{html.escape(str(e))}"
|
| 71 |
|
| 72 |
-
#
|
| 73 |
with gr.Blocks(title="Pawfect Match") as demo:
|
| 74 |
-
gr.Markdown("## 🐾 Pawfect Match|宠物起名机
|
| 75 |
|
| 76 |
species = gr.Textbox(label="宠物种类", placeholder="例:金毛 / 英短 / 仓鼠 / 鹦鹉(可留空)")
|
| 77 |
look = gr.Textbox(label="外表特征", placeholder="例:橘色短毛,大眼睛,白爪(可留空)")
|
|
|
|
| 1 |
+
import os, html, random
|
| 2 |
import gradio as gr
|
| 3 |
from openai import OpenAI
|
| 4 |
|
|
|
|
| 6 |
MODEL_NAME = "gpt-4o-mini"
|
| 7 |
client = OpenAI(api_key=API_KEY)
|
| 8 |
|
| 9 |
+
# ===== 可爱名字 + 真实名言:系统提示 =====
|
| 10 |
+
SYSTEM_PROMPT = """You are a playful, high-creativity pet name generator.
|
| 11 |
+
Goal: Produce EXACTLY ONE cute, kid-pronounceable pet name + one authentic quote line.
|
| 12 |
|
| 13 |
Creative balance:
|
| 14 |
+
- Inspiration source (山海经 / 迪士尼 / 哈利波特 / 生活) drives the concept (~70%).
|
| 15 |
+
- User inputs (species/appearance/personality/gender) refine the vibe (~30%).
|
| 16 |
+
- Keep outputs imaginative; do NOT overfit to traits.
|
| 17 |
+
|
| 18 |
+
NAME rules (must be easy for kids):
|
| 19 |
+
- Keep it cute, round, and easy to call.
|
| 20 |
+
- Length guidance by language:
|
| 21 |
+
• Chinese: 1–2 simple characters (avoid rare characters).
|
| 22 |
+
• English: 1–2 syllables (e.g., “Momo”, “Pip”, “Nori”).
|
| 23 |
+
• Japanese: 2–3 mora, open vowels preferred (e.g., “Momo”, “Koko”).
|
| 24 |
+
• Korean: 2 simple syllables (e.g., “Bori”, “Toto”).
|
| 25 |
+
• French: 1–2 syllables with soft endings (-ou, -i, -ette).
|
| 26 |
+
- You MAY coin a new word if it sounds cute and natural.
|
| 27 |
+
- Output in requested language (Chinese/English/Japanese/Korean/French).
|
| 28 |
+
- Provide ONE short meaning/explanation (≤12 words), theme-first, traits-second.
|
| 29 |
+
- No numbers; no long phrases.
|
| 30 |
+
|
| 31 |
+
QUOTE rules (must be real):
|
| 32 |
+
- After the name line, provide ONE short, warm, authentic quote about animals/love/companionship/playfulness.
|
| 33 |
+
- Use a real, verifiable author/work/proverb; include attribution (e.g., — Anatole France).
|
| 34 |
+
- Translate the quote text into the requested language if needed, attribution kept in Latin script.
|
| 35 |
+
|
| 36 |
+
STRICT OUTPUT (exactly two lines):
|
| 37 |
Name — short meaning
|
| 38 |
Quote: “...” — Attribution
|
| 39 |
"""
|
|
|
|
| 41 |
def build_prompt(species, look, personality, gender, language, inspiration):
|
| 42 |
return f"""
|
| 43 |
Requested language: {language}
|
| 44 |
+
Primary inspiration source: {inspiration}
|
| 45 |
+
Secondary refinements (may be empty):
|
| 46 |
- Species: {species or '(unspecified)'}
|
| 47 |
- Appearance: {look or '(unspecified)'}
|
| 48 |
- Personality: {personality or '(unspecified)'}
|
| 49 |
- Gender: {gender}
|
| 50 |
|
| 51 |
Task:
|
| 52 |
+
1) Create EXACTLY ONE cute, kid-pronounceable pet name (≤12-word meaning).
|
| 53 |
+
2) Then output ONE authentic, warm animal-related quote with attribution.
|
| 54 |
+
Remember: inspiration first (~70%), traits second (~30%); keep both lines in {language}.
|
| 55 |
"""
|
| 56 |
|
| 57 |
+
# ===== 真实名言兜底(多语言) =====
|
| 58 |
+
FALLBACK_QUOTES = {
|
| 59 |
+
"English": [
|
| 60 |
+
('"Until one has loved an animal, a part of one\'s soul remains unawakened."', "Anatole France"),
|
| 61 |
+
('"An animal\'s eyes have the power to speak a great language."', "Martin Buber"),
|
| 62 |
+
('"Animals are such agreeable friends—they ask no questions; they pass no criticisms."', "George Eliot"),
|
| 63 |
+
],
|
| 64 |
+
"中文": [
|
| 65 |
+
('“一个人若未曾爱过动物,他的灵魂尚未苏醒。”', "Anatole France"),
|
| 66 |
+
('“动物的眼睛自有它们的语言。”', "Martin Buber"),
|
| 67 |
+
('“动物是极好的朋友——它们不发问,也不挑剔。”', "George Eliot"),
|
| 68 |
+
],
|
| 69 |
+
"日本語": [
|
| 70 |
+
('「動物を愛したことのない者の魂は、まだ目覚めていない。」', "Anatole France"),
|
| 71 |
+
('「動物の瞳は偉大な言葉を語る力を持つ。」', "Martin Buber"),
|
| 72 |
+
('「動物は実に快い友である——問いも批判もない。」', "George Eliot"),
|
| 73 |
+
],
|
| 74 |
+
"한국어": [
|
| 75 |
+
('“동물을 사랑해 보지 않은 영혼은 아직 깨어나지 않았다.”', "Anatole France"),
|
| 76 |
+
('“동물의 눈에는 위대한 언어가 담겨 있다.”', "Martin Buber"),
|
| 77 |
+
('“동물은 참으로 상냥한 친구다—묻지도 비난하지도 않는다.”', "George Eliot"),
|
| 78 |
+
],
|
| 79 |
+
"Français": [
|
| 80 |
+
('« Jusqu\'à ce qu\'on ait aimé un animal, une partie de notre âme reste endormie. »', "Anatole France"),
|
| 81 |
+
('« Les yeux d’un animal ont le pouvoir de parler un grand langage. »', "Martin Buber"),
|
| 82 |
+
('« Les animaux sont de si agréables amis — ils ne posent aucune question et ne font aucune critique. »', "George Eliot"),
|
| 83 |
+
],
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
def get_fallback_quote(language: str):
|
| 87 |
+
lang = language if language in FALLBACK_QUOTES else "English"
|
| 88 |
+
text, author = random.choice(FALLBACK_QUOTES[lang])
|
| 89 |
+
return f'Quote: {text} — {author}'
|
| 90 |
+
|
| 91 |
+
def ensure_two_lines_and_quote(content: str, language: str):
|
| 92 |
+
"""
|
| 93 |
+
确保严格两行输出;若缺失或格式不当,为第二行注入真实名言兜底。
|
| 94 |
+
"""
|
| 95 |
+
if not content:
|
| 96 |
+
return None
|
| 97 |
+
lines = [ln.strip() for ln in content.splitlines() if ln.strip()]
|
| 98 |
+
# 尽量抓取首行作为名字
|
| 99 |
+
name_line = lines[0] if lines else ""
|
| 100 |
+
# 找到包含 Quote: 的行
|
| 101 |
+
quote_line = None
|
| 102 |
+
for ln in lines[1:]:
|
| 103 |
+
if ln.lower().startswith("quote:"):
|
| 104 |
+
quote_line = ln
|
| 105 |
+
break
|
| 106 |
+
if not quote_line:
|
| 107 |
+
quote_line = get_fallback_quote(language)
|
| 108 |
+
# 只返回两行
|
| 109 |
+
return f"{name_line}\n{quote_line}"
|
| 110 |
+
|
| 111 |
def generate_name(species, look, personality, gender, language, inspiration):
|
| 112 |
try:
|
| 113 |
prompt = build_prompt(
|
|
|
|
| 118 |
)
|
| 119 |
resp = client.chat.completions.create(
|
| 120 |
model=MODEL_NAME,
|
| 121 |
+
temperature=0.95, # 强创意
|
| 122 |
top_p=0.95,
|
| 123 |
max_tokens=280,
|
| 124 |
messages=[
|
|
|
|
| 126 |
{"role": "user", "content": prompt}
|
| 127 |
]
|
| 128 |
)
|
| 129 |
+
raw = (resp.choices[0].message.content or "").strip()
|
| 130 |
+
final_out = ensure_two_lines_and_quote(raw, language)
|
| 131 |
+
return final_out or "(没有生成内容,请稍后再试)"
|
| 132 |
except Exception as e:
|
| 133 |
return f"⚠️ 出错:{html.escape(str(e))}"
|
| 134 |
|
| 135 |
+
# ===== 界面(去掉那句介绍,只留标题) =====
|
| 136 |
with gr.Blocks(title="Pawfect Match") as demo:
|
| 137 |
+
gr.Markdown("## 🐾 Pawfect Match|宠物起名机")
|
| 138 |
|
| 139 |
species = gr.Textbox(label="宠物种类", placeholder="例:金毛 / 英短 / 仓鼠 / 鹦鹉(可留空)")
|
| 140 |
look = gr.Textbox(label="外表特征", placeholder="例:橘色短毛,大眼睛,白爪(可留空)")
|