|
""" |
|
Square Theory Generator (Markdownโonly, up to 20 ideas) |
|
===================================================== |
|
2025โ05โ28ย v9 โ ์ถ๋ ฅ ํฌ๋งท ๊ฐ์ & ํ๋ ๊ตฌ๋ถ ๋ช
ํํ |
|
--------------------------------------------------- |
|
๋ณ๊ฒฝ ์์ฝ |
|
--------- |
|
1. **์ฌ๋ก๊ฑด ยท ๋ธ๋๋ ๋ค์ ๊ตฌํ** โ Markdown ํ
ํ๋ฆฟ์ ๋ค์ ๊ตฌ์กฐ๋ก ๊ฐ์ |
|
```md |
|
### 1. ๋ธ๋๋ ๋ค์: ๋ชจ๋์ปคํผ |
|
**๋ฉ์ธ ์นดํผ** |
|
โข ์๋จ: ํ๋ฏธ๋ฅผ ๋ด์ ์ปคํผ |
|
โข ํ๋จ: ๋น์ ์ ํ๋ฃจ๋ฅผ ํน๋ณํ๊ฒ |
|
|
|
**์ฌ๋ก๊ฑด** |
|
> ์ปคํผ ํ์์ ์ฌ์ |
|
|
|
**์ฌ๊ฐํ ํค์๋** |
|
TL: ํ๋ฏธ ยท TR: ์ปคํผ ยท BR: ํฅ๊ธฐ ยท BL: ํ์ |
|
``` |
|
2. **ํ๋กฌํํธ ๋ช
์ธ ์ ์ง** โ JSON ๊ตฌ์กฐ ๋ณ๋์ ์์(ํธํ). |
|
3. **์ถ๊ฐ ๊ฐ์ ์ ์** โ ์ฝ๋ ๋ด ์ฃผ์์ผ๋ก โ์ถ๊ฐ ํ๋ยท๋ญํน ๊ธฐ์คยทCSV ๋ค์ด๋ก๋โ ์์ด๋์ด ์ฝ์
. |
|
|
|
์คํ๋ฒ |
|
------ |
|
```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, error as oai_err |
|
|
|
|
|
|
|
|
|
if not os.getenv("OPENAI_API_KEY"): |
|
raise EnvironmentError("OPENAI_API_KEY ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ธ์.") |
|
|
|
client = OpenAI() |
|
|
|
|
|
|
|
|
|
SYSTEM_PROMPT = ( |
|
"๋๋ ํ๊ตญ์ด ์นดํผยท๋ธ๋๋ ๋ค์ด๋ฐ ์ ๋ฌธ๊ฐ์ด์ Square Theory ๋์ฐ๋ฏธ๋ค. " |
|
"์ฌ์ฉ์๊ฐ ์
๋ ฅํ ํ๋์ ๋จ์ด(tl)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ง์ด ๋ฐ์ด๋ ์์๋๋ก ์ต๋ 20๊ฐ์ ์ ์์ JSON ๋ฐฐ์ด๋ก ๋ฐํํด๋ผ. " |
|
"๊ฐ ์์๋ tl, tr, br, bl, top_phrase, bottom_phrase, slogan, brand ํ๋๋ฅผ ๊ฐ์ง๋ค. " |
|
"๋ฐฐ์ด ์ฒซ ๋ฒ์งธ ์์๊ฐ ๊ฐ์ฅ ์ฐ์ํด์ผ ํ๋ค. JSON ์ธ ๋ฌธ์๋ ๊ธ์งํ๋ค." |
|
) |
|
|
|
FALLBACK_MODELS = ["gpt-4o-mini", "gpt-4o", "gpt-4o-preview", "gpt-4-turbo"] |
|
|
|
|
|
def _clean_json_block(text: str) -> str: |
|
"""Strip ```json fences if present.""" |
|
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): |
|
last_exc = None |
|
for model in FALLBACK_MODELS: |
|
try: |
|
resp = client.chat.completions.create( |
|
model=model, |
|
messages=[ |
|
{"role": "system", "content": SYSTEM_PROMPT}, |
|
{"role": "user", "content": seed}, |
|
], |
|
temperature=0.9, |
|
max_tokens=2048, |
|
) |
|
cleaned = _clean_json_block(resp.choices[0].message.content) |
|
data = json.loads(cleaned) if cleaned else [] |
|
if isinstance(data, dict): |
|
data = [data] |
|
if not isinstance(data, list) or not (1 <= len(data) <= 20): |
|
raise ValueError("LLM ์๋ต์ด ์ฌ๋ฐ๋ฅธ 1โ20๊ฐ ๋ฆฌ์คํธ๊ฐ ์๋") |
|
return data |
|
except (oai_err.OpenAIError, json.JSONDecodeError, ValueError, TypeError) as exc: |
|
last_exc = exc |
|
continue |
|
raise RuntimeError(f"LLM ํธ์ถ ์คํจ: {last_exc}") |
|
|
|
|
|
|
|
|
|
|
|
def generate(seed_word: str): |
|
seed_word = seed_word.strip() |
|
if not seed_word: |
|
return "โ ๏ธ **์๋ ๋จ์ด๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.**" |
|
try: |
|
results = _call_llm(seed_word) |
|
md = [f"## ์ด {len(results)}๊ฐ ์ ์"] |
|
for idx, item in enumerate(results, 1): |
|
md.append( |
|
f"### {idx}. ๋ธ๋๋ ๋ค์: {item['brand']}\n" |
|
f"**๋ฉ์ธ ์นดํผ** \ |
|
โข ์๋จ: {item['top_phrase']} \ |
|
โข ํ๋จ: {item['bottom_phrase']}\n\n" |
|
f"**์ฌ๋ก๊ฑด** \ |
|
> {item['slogan']}\n\n" |
|
f"**์ฌ๊ฐํ ํค์๋** \ |
|
TL: {item['tl']} ยท TR: {item['tr']} ยท BR: {item['br']} ยท BL: {item['bl']}\n" |
|
) |
|
return "\n".join(md) |
|
except Exception as exc: |
|
return f"โ **์ค๋ฅ:** {exc}" |
|
|
|
|
|
|
|
|
|
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() |
|
|
|
run.click(generate, inputs=seed, outputs=md_out) |
|
|
|
|
|
demo.queue().launch() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|