Naming / app.py
openfree's picture
Update app.py
e420f43 verified
raw
history blame
7.91 kB
"""
Square Theory Generator (Markdownโ€‘only, up to 20 ideas)
=====================================================
2025โ€‘05โ€‘28ย v7 โ— ๋ฐ•์Šค ๋‹ค์ด์–ด๊ทธ๋žจ ์ œ๊ฑฐ & ์ œ์•ˆย 20๊ฐœ๋กœ ํ™•์žฅ
---------------------------------------------------
๋ณ€๊ฒฝ ์š”์•ฝ
---------
1. **์‚ฌ๊ฐํ˜• ์‹œ๊ฐํ™” ์ œ๊ฑฐ** โ€’ ์ถœ๋ ฅ/์˜์กด์—์„œ `matplotlib` ์ „๋ถ€ ์‚ญ์ œ.
2. **์ œ์•ˆ ๊ฐœ์ˆ˜ ์ƒํ–ฅ** โ€’ LLM์ด ์ตœ๋Œ€ **20๊ฐœ** ์•„์ด๋””์–ด ๋ฐ˜ํ™˜.
3. **์œ ์—ฐ ๊ธธ์ด ํ—ˆ์šฉ** โ€’ 1โ€ฏโ‰คโ€ฏNโ€ฏโ‰คโ€ฏ20 ๋ฆฌ์ŠคํŠธ๋ฉด OK.
4. **UI ๋‹จ์ˆœํ™”** โ€’ ์‹œ๋“œ ์ž…๋ ฅ โ†’ ๋ฒ„ํŠผ โ†’ ๋งˆํฌ๋‹ค์šด ๊ฒฐ๊ณผ.
์‹คํ–‰๋ฒ•
------
```bash
pip install --upgrade gradio openai
export OPENAI_API_KEY="sk-..."
python square_theory_gradio.py
```
"""
import os
import json
import gradio as gr
from openai import OpenAI
# -------------------------------------------------
# 0. OpenAI ํด๋ผ์ด์–ธํŠธ
# -------------------------------------------------
if not os.getenv("OPENAI_API_KEY"):
raise EnvironmentError("OPENAI_API_KEY ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์„ธ์š”.")
client = OpenAI()
# -------------------------------------------------
# 1. LLM Prompt & Utilities
# -------------------------------------------------
SYSTEM_PROMPT = (
"๋„ˆ๋Š” ํ•œ๊ตญ์–ด ์นดํ”ผยท๋ธŒ๋žœ๋“œ ๋„ค์ด๋ฐ ์ „๋ฌธ๊ฐ€์ด์ž Square Theory ๋„์šฐ๋ฏธ๋‹ค. "
"์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ•˜๋‚˜์˜ ๋‹จ์–ด(tl)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ’ˆ์งˆ์ด ๋›ฐ์–ด๋‚œ ์ˆœ์„œ๋Œ€๋กœ ์ตœ๋Œ€ 20๊ฐœ์˜ ์ œ์•ˆ์„ JSON ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ด๋ผ. "
"๊ฐ ์›์†Œ๋Š” tl, tr, br, bl, top_phrase, bottom_phrase, slogan, brand ํ•„๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค. "
"๋ฐฐ์—ด ์ฒซ ๋ฒˆ์งธ ์›์†Œ๊ฐ€ ๊ฐ€์žฅ ์šฐ์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค. JSON ์™ธ ๋ฌธ์ž๋Š” ๊ธˆ์ง€ํ•œ๋‹ค."
)
def clean_json_block(text: str) -> str:
text = text.strip()
if text.startswith("```"):
text = text.split("\n", 1)[1] if "\n" in text else text[3:]
if text.endswith("```"):
text = text[:-3]
return text.strip()
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=2048,
)
raw = resp.choices[0].message.content
cleaned = clean_json_block(raw)
try:
data = json.loads(cleaned)
if isinstance(data, dict):
data = [data]
if not isinstance(data, list):
raise TypeError("LLM ์‘๋‹ต์ด ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹˜")
if not 1 <= len(data) <= 20:
raise ValueError("์‘๋‹ต ๋ฆฌ์ŠคํŠธ ๊ธธ์ด๊ฐ€ 1~20 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚จ")
except Exception as exc:
raise ValueError(f"LLM JSON ํŒŒ์‹ฑ ์‹คํŒจ: {exc}\n์›๋ฌธ ์ผ๋ถ€: {cleaned[:300]} โ€ฆ")
return data
# -------------------------------------------------
# 2. Gradio callback
# -------------------------------------------------
def generate(seed_word: str):
results = call_llm(seed_word)
md_lines = [f"## ์ด {len(results)}๊ฐœ ์ œ์•ˆ\n"]
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"
)
return "\n".join(md_lines)
# -------------------------------------------------
# 3. UI
# -------------------------------------------------
with gr.Blocks(title="Square Theory โ€“ ์ตœ๋Œ€ 20๊ฐœ ๐Ÿ‡ฐ๐Ÿ‡ท") as demo:
gr.Markdown("""# ๐ŸŸง Square Theory ์ œ์•ˆ (์ตœ๋Œ€ 20๊ฐœ)\n๋‹จ์–ด ํ•˜๋‚˜ ์ž…๋ ฅ โ†’ LLM์ด ์ ์ˆ˜ํ™”ยท์ •๋ ฌํ•œ ์‚ฌ๊ฐํ˜•/์นดํ”ผ/๋ธŒ๋žœ๋“œ ๋„ค์ž„""")
seed = gr.Textbox(label="์‹œ๋“œ ๋‹จ์–ด(TL)", placeholder="์˜ˆ: ๊ณจ๋“ ")
run = gr.Button("์ƒ์„ฑ")
md_out = gr.Markdown(label="์ œ์•ˆ ๋ชฉ๋ก")
run.click(generate, inputs=seed, outputs=md_out)
if __name__ == "__main__":
demo.launch()
"""
Square Theory Generator (Markdownโ€‘only, up to 20 ideas)
=====================================================
2025โ€‘05โ€‘28ย v7 โ— ๋ฐ•์Šค ๋‹ค์ด์–ด๊ทธ๋žจ ์ œ๊ฑฐ & ์ œ์•ˆย 20๊ฐœ๋กœ ํ™•์žฅ
---------------------------------------------------
๋ณ€๊ฒฝ ์š”์•ฝ
---------
1. **์‚ฌ๊ฐํ˜• ์‹œ๊ฐํ™” ์ œ๊ฑฐ** โ€’ ์ถœ๋ ฅ/์˜์กด์—์„œ `matplotlib` ์ „๋ถ€ ์‚ญ์ œ.
2. **์ œ์•ˆ ๊ฐœ์ˆ˜ ์ƒํ–ฅ** โ€’ LLM์ด ์ตœ๋Œ€ **20๊ฐœ** ์•„์ด๋””์–ด ๋ฐ˜ํ™˜.
3. **์œ ์—ฐ ๊ธธ์ด ํ—ˆ์šฉ** โ€’ 1โ€ฏโ‰คโ€ฏNโ€ฏโ‰คโ€ฏ20 ๋ฆฌ์ŠคํŠธ๋ฉด OK.
4. **UI ๋‹จ์ˆœํ™”** โ€’ ์‹œ๋“œ ์ž…๋ ฅ โ†’ ๋ฒ„ํŠผ โ†’ ๋งˆํฌ๋‹ค์šด ๊ฒฐ๊ณผ.
์‹คํ–‰๋ฒ•
------
```bash
pip install --upgrade gradio openai
export OPENAI_API_KEY="sk-..."
python square_theory_gradio.py
```
"""
import os
import json
import gradio as gr
from openai import OpenAI
# -------------------------------------------------
# 0. OpenAI ํด๋ผ์ด์–ธํŠธ
# -------------------------------------------------
if not os.getenv("OPENAI_API_KEY"):
raise EnvironmentError("OPENAI_API_KEY ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์„ธ์š”.")
client = OpenAI()
# -------------------------------------------------
# 1. LLM Prompt & Utilities
# -------------------------------------------------
SYSTEM_PROMPT = (
"๋„ˆ๋Š” ํ•œ๊ตญ์–ด ์นดํ”ผยท๋ธŒ๋žœ๋“œ ๋„ค์ด๋ฐ ์ „๋ฌธ๊ฐ€์ด์ž Square Theory ๋„์šฐ๋ฏธ๋‹ค. "
"์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ•˜๋‚˜์˜ ๋‹จ์–ด(tl)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ’ˆ์งˆ์ด ๋›ฐ์–ด๋‚œ ์ˆœ์„œ๋Œ€๋กœ ์ตœ๋Œ€ 20๊ฐœ์˜ ์ œ์•ˆ์„ JSON ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ด๋ผ. "
"๊ฐ ์›์†Œ๋Š” tl, tr, br, bl, top_phrase, bottom_phrase, slogan, brand ํ•„๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค. "
"๋ฐฐ์—ด ์ฒซ ๋ฒˆ์งธ ์›์†Œ๊ฐ€ ๊ฐ€์žฅ ์šฐ์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค. JSON ์™ธ ๋ฌธ์ž๋Š” ๊ธˆ์ง€ํ•œ๋‹ค."
)
def clean_json_block(text: str) -> str:
text = text.strip()
if text.startswith("```"):
text = text.split("\n", 1)[1] if "\n" in text else text[3:]
if text.endswith("```"):
text = text[:-3]
return text.strip()
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=2048,
)
raw = resp.choices[0].message.content
cleaned = clean_json_block(raw)
try:
data = json.loads(cleaned)
if isinstance(data, dict):
data = [data]
if not isinstance(data, list):
raise TypeError("LLM ์‘๋‹ต์ด ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹˜")
if not 1 <= len(data) <= 20:
raise ValueError("์‘๋‹ต ๋ฆฌ์ŠคํŠธ ๊ธธ์ด๊ฐ€ 1~20 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚จ")
except Exception as exc:
raise ValueError(f"LLM JSON ํŒŒ์‹ฑ ์‹คํŒจ: {exc}\n์›๋ฌธ ์ผ๋ถ€: {cleaned[:300]} โ€ฆ")
return data
# -------------------------------------------------
# 2. Gradio callback
# -------------------------------------------------
def generate(seed_word: str):
results = call_llm(seed_word)
md_lines = [f"## ์ด {len(results)}๊ฐœ ์ œ์•ˆ\n"]
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"
)
return "\n".join(md_lines)
# -------------------------------------------------
# 3. UI
# -------------------------------------------------
with gr.Blocks(title="Square Theory โ€“ ์ตœ๋Œ€ 20๊ฐœ ๐Ÿ‡ฐ๐Ÿ‡ท") as demo:
gr.Markdown("""# ๐ŸŸง Square Theory ์ œ์•ˆ (์ตœ๋Œ€ 20๊ฐœ)\n๋‹จ์–ด ํ•˜๋‚˜ ์ž…๋ ฅ โ†’ LLM์ด ์ ์ˆ˜ํ™”ยท์ •๋ ฌํ•œ ์‚ฌ๊ฐํ˜•/์นดํ”ผ/๋ธŒ๋žœ๋“œ ๋„ค์ž„""")
seed = gr.Textbox(label="์‹œ๋“œ ๋‹จ์–ด(TL)", placeholder="์˜ˆ: ๊ณจ๋“ ")
run = gr.Button("์ƒ์„ฑ")
md_out = gr.Markdown(label="์ œ์•ˆ ๋ชฉ๋ก")
run.click(generate, inputs=seed, outputs=md_out)
if __name__ == "__main__":
demo.launch()