Naming / app.py
openfree's picture
Update app.py
9db6da0 verified
raw
history blame
5.19 kB
"""
Square Theory Generator (10 best variations)
===========================================
2025โ€‘05โ€‘28ย v3 โ— ํ•œ ์ž…๋ ฅ โ†’ ์šฐ์ˆ˜๋„ ์ˆœ 10๊ฐ€์ง€ ๊ฒฐ๊ณผ
------------------------------------------------
๋ณ€๊ฒฝ ์š”์•ฝ
---------
1. **LLM ํ•œย ํšŒ ํ˜ธ์ถœ๋กœ 10๊ฐœ์˜ ์‚ฌ๊ฐํ˜• ์ œ์•ˆ**
* JSON ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜, ํ’ˆ์งˆ์ด ๋†’์€ ์ˆœ์„œ๋กœ ์ •๋ ฌ (1ย โ€“ย 10)
2. **์ถœ๋ ฅ**
* โ‘  1์œ„ ์ œ์•ˆ์˜ ์‚ฌ๊ฐํ˜• ๋„์‹(Plot)
* โ‘ก 10๊ฐœ ์ œ์•ˆ์„ ๋งˆํฌ๋‹ค์šด ๋ฆฌ์ŠคํŠธ๋กœ ์ •๋ฆฌํ•˜์—ฌ ํ‘œ์‹œ
3. **UI ๊ฐ„์†Œํ™”** : seed ์ž…๋ ฅย +ย ์‹คํ–‰ ๋ฒ„ํŠผ + Plot + Markdown
4. **์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฐ•ํ™”**
์‹คํ–‰๋ฒ•
------
```bash
pip install --upgrade gradio matplotlib openai
export OPENAI_API_KEY="sk-..."
python square_theory_gradio.py
```
"""
import os
import json
import gradio as gr
import matplotlib.pyplot as plt
from matplotlib import patches, font_manager, rcParams
from openai import OpenAI
# -------------------------------------------------
# 0. ํ•œ๊ธ€ ํฐํŠธ ์„ค์ •
# -------------------------------------------------
def _set_korean_font():
for cand in ("Malgun Gothic", "NanumGothic", "AppleGothic", "DejaVu Sans"):
if cand in {f.name for f in font_manager.fontManager.ttflist}:
rcParams["font.family"] = cand
break
rcParams["axes.unicode_minus"] = False
_set_korean_font()
# -------------------------------------------------
# 1. OpenAI ํด๋ผ์ด์–ธํŠธ
# -------------------------------------------------
if not os.getenv("OPENAI_API_KEY"):
raise EnvironmentError("OPENAI_API_KEY ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์„ธ์š”.")
client = OpenAI()
# -------------------------------------------------
# 2. Square Diagram
# -------------------------------------------------
def draw_square(words):
fig, ax = plt.subplots(figsize=(4, 4))
ax.add_patch(patches.Rectangle((0, 0), 1, 1, fill=False, linewidth=2))
ax.text(-0.05, 1.05, words["tl"], ha="right", va="bottom", fontsize=14, fontweight="bold")
ax.text(1.05, 1.05, words["tr"], ha="left", va="bottom", fontsize=14, fontweight="bold")
ax.text(1.05, -0.05, words["br"], ha="left", va="top", fontsize=14, fontweight="bold")
ax.text(-0.05, -0.05, words["bl"], ha="right", va="top", fontsize=14, fontweight="bold")
ax.set_xticks([])
ax.set_yticks([])
ax.set_xlim(-0.2, 1.2)
ax.set_ylim(-0.2, 1.2)
ax.set_aspect("equal")
return fig
# -------------------------------------------------
# 3. LLM Prompt & Call
# -------------------------------------------------
SYSTEM_PROMPT = (
"๋„ˆ๋Š” ํ•œ๊ตญ์–ด ์นดํ”ผยท๋ธŒ๋žœ๋“œ ๋„ค์ด๋ฐ ์ „๋ฌธ๊ฐ€์ด์ž Square Theory ๋„์šฐ๋ฏธ๋‹ค. "
"์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ํ•˜๋‚˜์˜ ๋‹จ์–ด(tl)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ’ˆ์งˆ์ด ๊ฐ€์žฅ ๋›ฐ์–ด๋‚œ ๊ฒƒ๋ถ€ํ„ฐ 10๊ฐœ์˜ ์ œ์•ˆ์„ JSON ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ด๋ผ. "
"๊ฐ ๋ฐฐ์—ด ์›์†Œ๋Š” tl, tr, br, bl, top_phrase, bottom_phrase, slogan, brand ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, "
"์‚ฌ๊ฐํ˜• ๋„ค ๊ผญ์ง“์ (tl>tr>br>bl)๊ณผ ๋‘ ํ‘œํ˜„ยท์Šฌ๋กœ๊ฑดยท๋ธŒ๋žœ๋“œ ๋„ค์ž„์ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์—ฐ๊ฒฐ๋ผ์•ผ ํ•œ๋‹ค. "
"๋ฐฐ์—ด์€ ์ตœ๊ณ ์˜ ์ œ์•ˆ์ด index 0, ๊ทธ๋‹ค์Œ์ด index 1 โ€ฆ 9 ์ˆœ์„œ์—ฌ์•ผ ํ•œ๋‹ค. "
"๊ฒฐ๊ณผ๋Š” JSON ์™ธ ๋‹ค๋ฅธ ํ…์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜๋ฉด ์•ˆ ๋œ๋‹ค."
)
def call_llm(seed: str):
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": seed},
],
temperature=0.9,
max_tokens=1024,
)
raw = resp.choices[0].message.content.strip()
try:
data = json.loads(raw)
if not isinstance(data, list) or len(data) != 10:
raise ValueError("JSON ๋ฐฐ์—ด ๊ธธ์ด๊ฐ€ 10์ด ์•„๋‹˜")
except Exception as exc:
raise ValueError(f"LLM JSON ํŒŒ์‹ฑ ์‹คํŒจ: {exc}\n์›๋ฌธ: {raw[:300]} โ€ฆ")
return data
# -------------------------------------------------
# 4. Gradio callback
# -------------------------------------------------
def generate(seed_word: str):
results = call_llm(seed_word)
# 1์œ„ ๋„์‹
fig = draw_square({k: results[0][k] for k in ("tl", "tr", "br", "bl")})
# ๋ฆฌ์ŠคํŠธ ๋งˆํฌ๋‹ค์šด
md_lines = []
for idx, item in enumerate(results, 1):
md_lines.append(
f"### {idx}. {item['top_phrase']} / {item['bottom_phrase']}\n"
f"- **์Šฌ๋กœ๊ฑด**: {item['slogan']}\n"
f"- **๋ธŒ๋žœ๋“œ ๋„ค์ž„**: {item['brand']}\n"
f"- (tl={item['tl']}, tr={item['tr']}, br={item['br']}, bl={item['bl']})\n"
)
markdown_out = "\n".join(md_lines)
return fig, markdown_out
# -------------------------------------------------
# 5. UI
# -------------------------------------------------
with gr.Blocks(title="Square Theory โ€“ Topย 10 ๐Ÿ‡ฐ๐Ÿ‡ท") as demo:
gr.Markdown("""# ๐Ÿ”Ÿ Square Theory ์ œ์•ˆ Topย 10\n๋‹จ์–ด 1๊ฐœ โ†’ LLM์ด ํ‰๊ฐ€ยท์ •๋ ฌํ•œ 10๊ฐœ ์‚ฌ๊ฐํ˜•/์นดํ”ผ/๋ธŒ๋žœ๋“œ ๋„ค์ž„""")
seed = gr.Textbox(label="์‹œ๋“œ ๋‹จ์–ด(TL)", placeholder="์˜ˆ: ๊ณจ๋“ ")
run = gr.Button("์ƒ์„ฑ")
fig_out = gr.Plot(label="1์œ„ ์‚ฌ๊ฐํ˜•")
md_out = gr.Markdown(label="Topย 10 ์ œ์•ˆ")
run.click(generate, inputs=seed, outputs=[fig_out, md_out])
if __name__ == "__main__":
demo.launch()