|
""" |
|
Square Theory Brand Generator |
|
============================= |
|
2025-05-28 | Square Theory๋ฅผ ํ์ฉํ ๋ธ๋๋ ๋ค์ด๋ฐ & ์ฌ๋ก๊ฑด ์์ฑ๊ธฐ |
|
---------------------------------------------------------- |
|
|
|
Square Theory๋ฅผ ๋ธ๋๋ฉ์ ์ ์ฉ: ๋ธ๋๋๋ช
์ด Square๋ฅผ ์์ฑํ๋ ๊ตฌ์กฐ |
|
์: GRUBHUB = GRUB(์์) + HUB(์ค์ฌ) โ ์์ ๋ฐฐ๋ฌ์ ์ค์ฌ |
|
""" |
|
|
|
import os |
|
import json |
|
import gradio as gr |
|
import openai |
|
from openai import OpenAI |
|
from datetime import datetime |
|
from typing import List, Dict, Tuple, Optional |
|
|
|
|
|
if not os.getenv("OPENAI_API_KEY"): |
|
raise EnvironmentError("OPENAI_API_KEY ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ธ์.") |
|
|
|
client = OpenAI() |
|
|
|
|
|
BRANDING_SQUARE_PROMPT = """ |
|
๋น์ ์ Square Theory๋ฅผ ํ์ฉํ ๋ธ๋๋ ๋ค์ด๋ฐ ์ ๋ฌธ๊ฐ์
๋๋ค. |
|
|
|
Square Theory๋ 4๊ฐ์ ๋จ์ด๊ฐ ์๋ฏธ์ ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์ฌ๊ฐํ์ ์ด๋ฃจ๋ ๊ตฌ์กฐ์
๋๋ค. |
|
์ด๋ฅผ ๋ธ๋๋ฉ์ ์ ์ฉํ๋ฉด, ๋ธ๋๋๋ช
์ด Square๋ฅผ ์์ฑํ๋ฉฐ "์ํ!" ๋ชจ๋จผํธ๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
์ฑ๊ณต์ ์ธ ๋ธ๋๋ Square ์์: |
|
1. GRUBHUB: GRUB(์์) + HUB(์ค์ฌ) = ์์ ๋ฐฐ๋ฌ์ ์ค์ฌ์ง |
|
2. Brand New (๋ฆฌ๋ธ๋๋ฉ ๋ธ๋ก๊ทธ): BRAND + NEW = ์๋ก์ด ๋ธ๋๋ = ์
๋ฐ์ดํธ๋ ๋ธ๋๋ |
|
3. Crosscord: CROSSWORD + DISCORD = ํฌ๋ก์ค์๋ ์ปค๋ฎค๋ํฐ ์๋ฒ |
|
|
|
๋ธ๋๋ Square ์์ฑ ์์น: |
|
1. ๋ธ๋๋๋ช
์ ๋ ๋จ์ด์ ์กฐํฉ (ํฉ์ฑ์ด, ํฌํธ๋งจํ , ๋๋ ๊ตฌ๋ฌธ) |
|
2. ๊ฐ ๋จ์ด๋ ๋น์ฆ๋์ค์ ํต์ฌ ์์ฑ๊ณผ ์ฐ๊ฒฐ |
|
3. ์ ์ฒด Square๊ฐ ๋ธ๋๋์ ์ ์ฒด์ฑ์ ๊ฐํ |
|
4. ์ฌ๋ก๊ฑด์ Square์ ์๋ฏธ๋ฅผ ํ์ฅ |
|
|
|
์ฌ์ฉ์ ์
๋ ฅ(์
์ข
/ํค์๋)์ ๋ฐ์ ๋ค์ ํ์์ JSON ๋ฐฐ์ด์ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"brand_type": "compound/portmanteau/phrase", |
|
"tl": "์ผ์ชฝ์๋จ ๋จ์ด", |
|
"tr": "์ค๋ฅธ์ชฝ์๋จ ๋จ์ด", |
|
"bl": "์ผ์ชฝํ๋จ ๋จ์ด", |
|
"br": "์ค๋ฅธ์ชฝํ๋จ ๋จ์ด", |
|
"top_edge": "์๋จ ๊ด๊ณ", |
|
"bottom_edge": "ํ๋จ ๊ด๊ณ", |
|
"left_edge": "์ผ์ชฝ ๊ด๊ณ", |
|
"right_edge": "์ค๋ฅธ์ชฝ ๊ด๊ณ", |
|
"slogan": "๋ธ๋๋ ์ฌ๋ก๊ฑด", |
|
"tagline": "์งง์ ํ๊ทธ๋ผ์ธ", |
|
"business_description": "๋น์ฆ๋์ค ์ค๋ช
", |
|
"why_it_works": "์ ์ด Square๊ฐ ํจ๊ณผ์ ์ธ์ง", |
|
"target_audience": "ํ๊ฒ ๊ณ ๊ฐ", |
|
"brand_personality": "๋ธ๋๋ ๊ฐ์ฑ", |
|
"impact_score": 1-10 |
|
} |
|
|
|
์ฐฝ์์ ์ด๋ฉด์๋ ๊ธฐ์ตํ๊ธฐ ์ฝ๊ณ , ๋น์ฆ๋์ค ๋ณธ์ง์ ๋ด์ ๋ธ๋๋๋ฅผ ๋ง๋์ธ์. |
|
""" |
|
|
|
|
|
INDUSTRY_EXAMPLES = [ |
|
"์นดํ/์ปคํผ์", |
|
"ํผํธ๋์ค/ํฌ์ค์ฅ", |
|
"๊ต์ก/์๋ํ
ํฌ", |
|
"๋ทฐํฐ/ํ์ฅํ", |
|
"์์ ๋ฐฐ๋ฌ", |
|
"์ฌํ/๊ด๊ด", |
|
"๊ธ์ต/ํํ
ํฌ", |
|
"ํจ์
/์๋ฅ", |
|
"๋ฐ๋ ค๋๋ฌผ", |
|
"์นํ๊ฒฝ/์ง์๊ฐ๋ฅ" |
|
] |
|
|
|
def generate_brand_squares(industry: str, keywords: str, count: int = 5) -> List[Dict]: |
|
"""Square Theory ๊ธฐ๋ฐ ๋ธ๋๋ ์์ฑ""" |
|
|
|
user_prompt = f""" |
|
์
์ข
: {industry} |
|
ํค์๋: {keywords} |
|
|
|
์ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก Square Theory๋ฅผ ํ์ฉํ ๋ธ๋๋ {count}๊ฐ๋ฅผ ์์ฑํ์ธ์. |
|
๊ฐ ๋ธ๋๋๋ ์์ ํ Square๋ฅผ ํ์ฑํด์ผ ํ๋ฉฐ, ๋ธ๋๋๋ช
์ด Square์ ํต์ฌ์ด ๋์ด์ผ ํฉ๋๋ค. |
|
""" |
|
|
|
try: |
|
response = client.chat.completions.create( |
|
model="gpt-4o", |
|
messages=[ |
|
{"role": "system", "content": BRANDING_SQUARE_PROMPT}, |
|
{"role": "user", "content": user_prompt} |
|
], |
|
temperature=0.85, |
|
max_tokens=4000, |
|
response_format={"type": "json_object"} |
|
) |
|
|
|
content = response.choices[0].message.content |
|
data = json.loads(content) |
|
|
|
|
|
if isinstance(data, dict): |
|
if "brands" in data: |
|
results = data["brands"] |
|
elif "results" in data: |
|
results = data["results"] |
|
else: |
|
results = [data] |
|
else: |
|
results = data |
|
|
|
|
|
results.sort(key=lambda x: x.get("impact_score", 0), reverse=True) |
|
|
|
return results[:count] |
|
|
|
except Exception as e: |
|
raise RuntimeError(f"๋ธ๋๋ ์์ฑ ์คํจ: {e}") |
|
|
|
def visualize_brand_square(brand: Dict) -> str: |
|
"""๋ธ๋๋ Square ์๊ฐํ""" |
|
|
|
brand_name = brand.get('brand_name', 'BRAND') |
|
tl, tr = brand.get('tl', '?'), brand.get('tr', '?') |
|
bl, br = brand.get('bl', '?'), brand.get('br', '?') |
|
|
|
|
|
if brand.get('brand_type') == 'compound': |
|
parts = brand_name.split() |
|
brand_part1 = parts[0] if len(parts) > 0 else brand_name[:len(brand_name)//2] |
|
brand_part2 = parts[1] if len(parts) > 1 else brand_name[len(brand_name)//2:] |
|
else: |
|
|
|
mid = len(brand_name) // 2 |
|
brand_part1 = brand_name[:mid+1] |
|
brand_part2 = brand_name[mid-1:] |
|
|
|
return f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;"> |
|
|
|
<!-- ๋ธ๋๋๋ช
ํค๋ --> |
|
<div style="text-align: center; margin-bottom: 30px;"> |
|
<h2 style="font-size: 2.5em; margin: 0; color: #2c3e50; letter-spacing: -1px;">{brand_name}</h2> |
|
<p style="font-size: 1.2em; color: #7f8c8d; margin: 10px 0; font-style: italic;">"{brand.get('slogan', '')}"</p> |
|
<p style="font-size: 0.9em; color: #95a5a6; margin: 5px 0;">{brand.get('tagline', '')}</p> |
|
</div> |
|
|
|
<!-- Square ๋ค์ด์ด๊ทธ๋จ --> |
|
<div style="position: relative; width: 100%; height: 350px; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); border-radius: 12px; padding: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> |
|
|
|
<!-- ์ค์ ๋ธ๋๋๋ช
--> |
|
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px 40px; border-radius: 12px; box-shadow: 0 5px 20px rgba(0,0,0,0.15); z-index: 10;"> |
|
<div style="font-size: 1.8em; font-weight: bold; color: #2c3e50; text-align: center;">{brand_name}</div> |
|
<div style="font-size: 0.9em; color: #7f8c8d; text-align: center; margin-top: 5px;">{brand.get('brand_type', 'compound')}</div> |
|
</div> |
|
|
|
<!-- ๊ผญ์ง์ --> |
|
<div style="position: absolute; top: 30px; left: 30px; background: #3498db; color: white; padding: 12px 20px; border-radius: 8px; font-weight: 600; box-shadow: 0 3px 10px rgba(52, 152, 219, 0.3);"> |
|
{tl} |
|
</div> |
|
<div style="position: absolute; top: 30px; right: 30px; background: #e74c3c; color: white; padding: 12px 20px; border-radius: 8px; font-weight: 600; box-shadow: 0 3px 10px rgba(231, 76, 60, 0.3);"> |
|
{tr} |
|
</div> |
|
<div style="position: absolute; bottom: 30px; left: 30px; background: #f39c12; color: white; padding: 12px 20px; border-radius: 8px; font-weight: 600; box-shadow: 0 3px 10px rgba(243, 156, 18, 0.3);"> |
|
{bl} |
|
</div> |
|
<div style="position: absolute; bottom: 30px; right: 30px; background: #27ae60; color: white; padding: 12px 20px; border-radius: 8px; font-weight: 600; box-shadow: 0 3px 10px rgba(39, 174, 96, 0.3);"> |
|
{br} |
|
</div> |
|
|
|
<!-- ๊ด๊ณ ๋ ์ด๋ธ --> |
|
<div style="position: absolute; top: 45px; left: 50%; transform: translateX(-50%); background: rgba(44, 62, 80, 0.9); color: white; padding: 4px 12px; border-radius: 4px; font-size: 0.8em;"> |
|
{brand.get('top_edge', '๊ด๊ณ')} |
|
</div> |
|
<div style="position: absolute; bottom: 45px; left: 50%; transform: translateX(-50%); background: rgba(44, 62, 80, 0.9); color: white; padding: 4px 12px; border-radius: 4px; font-size: 0.8em;"> |
|
{brand.get('bottom_edge', '๊ด๊ณ')} |
|
</div> |
|
<div style="position: absolute; top: 50%; left: 45px; transform: translateY(-50%) rotate(-90deg); background: rgba(44, 62, 80, 0.9); color: white; padding: 4px 12px; border-radius: 4px; font-size: 0.8em;"> |
|
{brand.get('left_edge', '๊ด๊ณ')} |
|
</div> |
|
<div style="position: absolute; top: 50%; right: 45px; transform: translateY(-50%) rotate(90deg); background: rgba(44, 62, 80, 0.9); color: white; padding: 4px 12px; border-radius: 4px; font-size: 0.8em;"> |
|
{brand.get('right_edge', '๊ด๊ณ')} |
|
</div> |
|
|
|
<!-- ์ฐ๊ฒฐ์ --> |
|
<svg style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;"> |
|
<defs> |
|
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"> |
|
<stop offset="0%" style="stop-color:#3498db;stop-opacity:0.5" /> |
|
<stop offset="100%" style="stop-color:#e74c3c;stop-opacity:0.5" /> |
|
</linearGradient> |
|
<linearGradient id="grad2" x1="0%" y1="0%" x2="100%" y2="0%"> |
|
<stop offset="0%" style="stop-color:#f39c12;stop-opacity:0.5" /> |
|
<stop offset="100%" style="stop-color:#27ae60;stop-opacity:0.5" /> |
|
</linearGradient> |
|
</defs> |
|
<!-- ์๋จ --> |
|
<line x1="100" y1="45" x2="600" y2="45" stroke="url(#grad1)" stroke-width="3"/> |
|
<!-- ํ๋จ --> |
|
<line x1="100" y1="305" x2="600" y2="305" stroke="url(#grad2)" stroke-width="3"/> |
|
<!-- ์ผ์ชฝ --> |
|
<line x1="50" y1="80" x2="50" y2="270" stroke="#7f8c8d" stroke-width="3" opacity="0.5"/> |
|
<!-- ์ค๋ฅธ์ชฝ --> |
|
<line x1="650" y1="80" x2="650" y2="270" stroke="#7f8c8d" stroke-width="3" opacity="0.5"/> |
|
</svg> |
|
</div> |
|
|
|
<!-- ๋ธ๋๋ ์ ๋ณด --> |
|
<div style="margin-top: 30px; display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> |
|
<div style="background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05);"> |
|
<h4 style="margin: 0 0 10px 0; color: #2c3e50;">๐ฏ ํ๊ฒ ๊ณ ๊ฐ</h4> |
|
<p style="margin: 0; color: #7f8c8d;">{brand.get('target_audience', 'N/A')}</p> |
|
</div> |
|
<div style="background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05);"> |
|
<h4 style="margin: 0 0 10px 0; color: #2c3e50;">โจ ๋ธ๋๋ ๊ฐ์ฑ</h4> |
|
<p style="margin: 0; color: #7f8c8d;">{brand.get('brand_personality', 'N/A')}</p> |
|
</div> |
|
</div> |
|
|
|
<div style="margin-top: 20px; background: #ecf0f1; padding: 20px; border-radius: 8px;"> |
|
<h4 style="margin: 0 0 10px 0; color: #2c3e50;">๐ก ์ ํจ๊ณผ์ ์ธ๊ฐ?</h4> |
|
<p style="margin: 0; color: #34495e;">{brand.get('why_it_works', '')}</p> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def generate_brands(industry: str, keywords: str, count: int) -> Tuple[str, str, List[Dict]]: |
|
"""๋ธ๋๋ ์์ฑ ๋ฐ ํ์""" |
|
|
|
if not industry or not keywords: |
|
return "โ ๏ธ ์
์ข
๊ณผ ํค์๋๋ฅผ ๋ชจ๋ ์
๋ ฅํด์ฃผ์ธ์.", "", [] |
|
|
|
try: |
|
brands = generate_brand_squares(industry, keywords, count) |
|
|
|
|
|
markdown_parts = [ |
|
f"# ๐ข Square Theory ๋ธ๋๋ ์ ์", |
|
f"**์
์ข
**: {industry} | **ํค์๋**: {keywords}", |
|
f"*์์ฑ ์๊ฐ: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n" |
|
] |
|
|
|
|
|
html_parts = [] |
|
|
|
for idx, brand in enumerate(brands, 1): |
|
score = brand.get('impact_score', 0) |
|
|
|
markdown_parts.append(f""" |
|
## {idx}. {brand.get('brand_name', 'N/A')} {'โญ' * min(score, 5)} |
|
|
|
**์ฌ๋ก๊ฑด**: *"{brand.get('slogan', 'N/A')}"* |
|
**ํ๊ทธ๋ผ์ธ**: {brand.get('tagline', 'N/A')} |
|
|
|
### ๐ Square ๊ตฌ์กฐ |
|
``` |
|
[{brand.get('tl', '?')}] โ({brand.get('top_edge', '?')})โ [{brand.get('tr', '?')}] |
|
โ โ |
|
({brand.get('left_edge', '?')}) ({brand.get('right_edge', '?')}) |
|
โ โ |
|
[{brand.get('bl', '?')}] โ({brand.get('bottom_edge', '?')})โ [{brand.get('br', '?')}] |
|
``` |
|
|
|
**๋น์ฆ๋์ค**: {brand.get('business_description', 'N/A')} |
|
**ํ๊ฒ**: {brand.get('target_audience', 'N/A')} |
|
**๊ฐ์ฑ**: {brand.get('brand_personality', 'N/A')} |
|
|
|
๐ก **ํจ๊ณผ**: {brand.get('why_it_works', 'N/A')} |
|
|
|
--- |
|
""") |
|
|
|
|
|
html_parts.append(f"<h3 style='text-align: center; color: #7f8c8d; margin: 40px 0 20px 0;'>#{idx}</h3>") |
|
html_parts.append(visualize_brand_square(brand)) |
|
|
|
return "\n".join(markdown_parts), "\n".join(html_parts), brands |
|
|
|
except Exception as e: |
|
return f"โ ์ค๋ฅ: {str(e)}", "", [] |
|
|
|
def export_brands(brands: List[Dict]) -> str: |
|
"""๋ธ๋๋ ์ ๋ณด JSON ๋ด๋ณด๋ด๊ธฐ""" |
|
if not brands: |
|
return None |
|
|
|
export_data = { |
|
"generated_at": datetime.now().isoformat(), |
|
"total_brands": len(brands), |
|
"brands": brands |
|
} |
|
|
|
return json.dumps(export_data, ensure_ascii=False, indent=2) |
|
|
|
|
|
with gr.Blocks(title="Square Theory Brand Generator", theme=gr.themes.Soft()) as demo: |
|
gr.Markdown(""" |
|
# ๐ข Square Theory Brand Generator |
|
### ์๋ฏธ์ Square๋ฅผ ์์ฑํ๋ ๋ธ๋๋ ๋ค์ด๋ฐ & ์ฌ๋ก๊ฑด ์์ฑ๊ธฐ |
|
|
|
Square Theory๋ฅผ ํ์ฉํด ๋ธ๋๋๋ช
์ด ์๋ฏธ์ ์ฌ๊ฐํ์ ์์ฑํ๋ ๊ฐ๋ ฅํ ๋ธ๋๋๋ฅผ ๋ง๋ค์ด๋ณด์ธ์. |
|
์ข์ ๋ธ๋๋๋ช
์ ๋จ์ํ ์ด๋ฆ์ด ์๋, ๋น์ฆ๋์ค์ ๋ณธ์ง์ ๋ด์ Square๋ฅผ ํ์ฑํฉ๋๋ค. |
|
|
|
**์ฑ๊ณต ์ฌ๋ก**: GRUBHUB (GRUB+HUB), Brand New, Crosscord |
|
""") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
industry_input = gr.Dropdown( |
|
choices=INDUSTRY_EXAMPLES, |
|
label="๐ญ ์
์ข
", |
|
allow_custom_value=True, |
|
value="์นดํ/์ปคํผ์" |
|
) |
|
|
|
keywords_input = gr.Textbox( |
|
label="๐ ํต์ฌ ํค์๋", |
|
placeholder="ํ๋ฆฌ๋ฏธ์, ํธ์ํ, ๋์์ ์ธ, ์นํ๊ฒฝ...", |
|
info="๋ธ๋๋๊ฐ ๋ด์์ผ ํ ํต์ฌ ๊ฐ์น๋ ํน์ง๋ค" |
|
) |
|
|
|
count_slider = gr.Slider( |
|
minimum=3, |
|
maximum=10, |
|
value=5, |
|
step=1, |
|
label="์์ฑ ๊ฐ์" |
|
) |
|
|
|
generate_btn = gr.Button("๐ ๋ธ๋๋ Square ์์ฑ", variant="primary", size="lg") |
|
|
|
with gr.Column(scale=1): |
|
gr.Markdown(""" |
|
### ๐ก Square Theory ๋ธ๋๋ฉ |
|
|
|
**์ข์ ๋ธ๋๋ Square์ ์กฐ๊ฑด:** |
|
1. ๋ธ๋๋๋ช
์ ๊ฐ ๋ถ๋ถ์ด ์๋ฏธ๋ฅผ ๊ฐ์ง |
|
2. ๋น์ฆ๋์ค ๋ณธ์ง๊ณผ ์ฐ๊ฒฐ |
|
3. ๊ธฐ์ตํ๊ธฐ ์ฝ๊ณ ๋ฐ์ ๊ฐ๋ฅ |
|
4. Square๊ฐ "์ํ!" ๋ชจ๋จผํธ ์์ฑ |
|
|
|
**Square ๊ตฌ์กฐ ์์:** |
|
``` |
|
GRUB โ(์์)โ FOOD |
|
โ โ |
|
(์ค์ฌ) (๋ฐฐ๋ฌ) |
|
โ โ |
|
HUB โ(์๋น์ค)โ DELIVERY |
|
``` |
|
""") |
|
|
|
|
|
current_brands = gr.State([]) |
|
|
|
with gr.Tabs(): |
|
with gr.Tab("๐ ๊ฒฐ๊ณผ ๋ฆฌ์คํธ"): |
|
output_markdown = gr.Markdown() |
|
|
|
with gr.Tab("๐จ ๋ธ๋๋ ์๊ฐํ"): |
|
output_visual = gr.HTML() |
|
|
|
with gr.Tab("๐พ ๋ด๋ณด๋ด๊ธฐ"): |
|
export_btn = gr.Button("JSON ํ์ผ ์์ฑ") |
|
download_file = gr.File(label="๋ค์ด๋ก๋", visible=False) |
|
|
|
|
|
gr.Examples( |
|
examples=[ |
|
["์นดํ/์ปคํผ์", "ํ๋ฆฌ๋ฏธ์, ์๋ํ, ๋์"], |
|
["ํผํธ๋์ค/ํฌ์ค์ฅ", "๊ฐ๋ ฅํ, ์ปค๋ฎค๋ํฐ, ๋ณํ"], |
|
["๊ต์ก/์๋ํ
ํฌ", "์ค๋งํธ, ์ฌ๋ฏธ์๋, ์ฑ์ฅ"], |
|
["์์ ๋ฐฐ๋ฌ", "๋น ๋ฅธ, ์ ์ ํ, ๋ค์ํ"], |
|
["์นํ๊ฒฝ/์ง์๊ฐ๋ฅ", "์์ฐ, ๋ฏธ๋, ์ํ"] |
|
], |
|
inputs=[industry_input, keywords_input] |
|
) |
|
|
|
|
|
def generate_and_store(industry, keywords, count): |
|
markdown, html, brands = generate_brands(industry, keywords, count) |
|
return markdown, html, brands |
|
|
|
generate_btn.click( |
|
fn=generate_and_store, |
|
inputs=[industry_input, keywords_input, count_slider], |
|
outputs=[output_markdown, output_visual, current_brands] |
|
) |
|
|
|
def create_export_file(brands): |
|
if not brands: |
|
return None |
|
|
|
content = export_brands(brands) |
|
filename = f"square_theory_brands_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" |
|
|
|
with open(filename, 'w', encoding='utf-8') as f: |
|
f.write(content) |
|
|
|
return gr.File(value=filename, visible=True) |
|
|
|
export_btn.click( |
|
fn=create_export_file, |
|
inputs=[current_brands], |
|
outputs=[download_file] |
|
) |
|
|
|
gr.Markdown(""" |
|
--- |
|
### ๐ฏ ํ์ฉ ๋ฐฉ๋ฒ |
|
|
|
1. **๋ธ๋๋ ๊ฐ๋ฐ**: ์์ฑ๋ Square ์ค ๊ฐ์ฅ ๊ฐ๋ ฅํ ๊ฒ ์ ํ |
|
2. **๋ง์ผํ
์ ๋ต**: Square์ ๊ฐ ์์๋ฅผ ์บ ํ์ธ์ ํ์ฉ |
|
3. **์คํ ๋ฆฌํ
๋ง**: Square๊ฐ ๋ง๋๋ ๋ด๋ฌํฐ๋ธ ํ์ฉ |
|
4. **ํ์ฅ ๊ฐ๋ฅ์ฑ**: Square์ ๊ฐ ๋ชจ์๋ฆฌ์์ ์๋ธ๋ธ๋๋ ํ์ |
|
|
|
### ๐ Square Theory ๋ธ๋๋ฉ์ ํ |
|
|
|
Square๋ฅผ ์์ฑํ๋ ๋ธ๋๋๋: |
|
- **๊ธฐ์ตํ๊ธฐ ์ฌ์**: ์๋ฏธ์ ์ฐ๊ฒฐ์ด ๊ธฐ์ต์ ๊ฐํ |
|
- **์คํ ๋ฆฌ๊ฐ ์์**: Square ์์ฒด๊ฐ ๋ธ๋๋ ์คํ ๋ฆฌ |
|
- **ํ์ฅ ๊ฐ๋ฅ**: ๊ฐ ์์์์ ์๋ก์ด ์๋ฏธ ํ์ |
|
- **์ฐจ๋ณํ๋จ**: ๋
ํนํ ์๋ฏธ ๊ตฌ์กฐ๋ก ๊ฒฝ์์ฌ์ ๊ตฌ๋ณ |
|
""") |
|
|
|
if __name__ == "__main__": |
|
demo.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=False |
|
) |