|
""" |
|
Ultimate Brand Theory Generator |
|
=============================== |
|
2025-05-28 | 15๊ฐ ์ด๋ก ์ ํตํฉํ ์ข
ํฉ ๋ธ๋๋ ์์ฑ๊ธฐ |
|
----------------------------------------------------- |
|
|
|
ํตํฉ๋ ์ด๋ก ๋ค: |
|
1. Square Theory - ์๋ฏธ์ ์ฌ๊ฐํ ๊ตฌ์กฐ |
|
2. Conceptual Blending - ๊ฐ๋
ํผํฉ |
|
3. Sound Symbolism - ์ํฅ ์์ง์ฃผ์ |
|
4. Linguistic Relativity - ์ธ์ด ์๋์ฑ |
|
5. Archetype Theory - ์ํ ์ด๋ก |
|
6. Jobs-to-be-Done - ํ ์ผ ์ด๋ก |
|
7. SCAMPER Method - ์ฐฝ์์ ๋ณํ |
|
8. Design Thinking - ๋์์ธ ์ฌ๊ณ |
|
9. Biomimicry - ์์ฒด๋ชจ๋ฐฉ |
|
10. Cognitive Load - ์ธ์ง ๋ถํ |
|
11. Von Restorff Effect - ๊ณ ๋ฆฝ ํจ๊ณผ |
|
12. Network Effects - ๋คํธ์ํฌ ํจ๊ณผ |
|
13. Memetics - ๋ฐ ์ด๋ก |
|
14. Color Psychology - ์์ ์ฌ๋ฆฌํ |
|
15. Gestalt Principles - ๊ฒ์ํํธ ์์น |
|
""" |
|
|
|
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 |
|
import random |
|
|
|
|
|
if not os.getenv("OPENAI_API_KEY"): |
|
raise EnvironmentError("OPENAI_API_KEY ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ธ์.") |
|
|
|
client = OpenAI() |
|
|
|
|
|
THEORY_DESCRIPTIONS = { |
|
"square": "4๊ฐ์ ๋จ์ด๊ฐ ์๋ฏธ์ ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์ฌ๊ฐํ์ ์ด๋ฃจ๋ ๊ตฌ์กฐ์
๋๋ค. ๋๋ณ์ ์จ๊ฒจ์ง ์ฐ๊ฒฐ์ด '์ํ!' ๋ชจ๋จผํธ๋ฅผ ๋ง๋ญ๋๋ค.", |
|
"blending": "๋ ๊ฐ ์ด์์ ๊ฐ๋
์ ํผํฉํ์ฌ ์๋ก์ด ์๋ฏธ๋ฅผ ์ฐฝ์ถํฉ๋๋ค. Netflix(Net+Flix)์ฒ๋ผ ํ์ ์ ์ธ ๊ฐ๋
์ ํ์์ํต๋๋ค.", |
|
"sound": "์์์ ์๋ฏธ ๊ฐ์ ์ฐ๊ด์ฑ์ ํ์ฉํฉ๋๋ค. 'i,e'๋ ๊ฐ๋ณ๊ณ ๋น ๋ฅธ ๋๋, 'o,u'๋ ๋ฌด๊ฒ๊ณ ๋๋ฆฐ ๋๋์ ์ ๋ฌํฉ๋๋ค.", |
|
"linguistic": "์ธ์ด๋ณ ์ฌ๊ณ ๋ฐฉ์ ์ฐจ์ด๋ฅผ ๊ณ ๋ คํ ๊ธ๋ก๋ฒ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ๋ฌธํ์ ๋์์ค์ ํ์งํ ์ ๋ต์ ๋ฐ์ํฉ๋๋ค.", |
|
"archetype": "Jung์ 12๊ฐ์ง ๋ณดํธ์ ์ํ์ ํ์ฉํฉ๋๋ค. Hero(Nike), Creator(Apple)์ฒ๋ผ ๋ฌด์์์ ๊ฐ์ ์ฐ๊ฒฐ์ ๋ง๋ญ๋๋ค.", |
|
"jobs": "๊ณ ๊ฐ์ด ํด๊ฒฐํ๋ ค๋ '์ผ'์ ์ด์ ์ ๋ง์ถฅ๋๋ค. ๊ธฐ๋ฅ์ , ๊ฐ์ ์ , ์ฌํ์ ์ฐจ์์ ๋์ฆ๋ฅผ ํตํฉ์ ์ผ๋ก ํด๊ฒฐํฉ๋๋ค.", |
|
"scamper": "7๊ฐ์ง ์ฐฝ์์ ๊ธฐ๋ฒ(๋์ฒด, ๊ฒฐํฉ, ์ ์, ์์ , ์ฉ๋๋ณ๊ฒฝ, ์ ๊ฑฐ, ์ญ์ )์ผ๋ก ํ์ ์ ์ธ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค.", |
|
"design": "์ธ๊ฐ ์ค์ฌ ํ์ ์ ์ถ๊ตฌํฉ๋๋ค. ๋ฐ๋์งํจ(์ธ๊ฐ), ์คํ๊ฐ๋ฅ์ฑ(๊ธฐ์ ), ์์กด๊ฐ๋ฅ์ฑ(๋น์ฆ๋์ค)์ ๊ต์งํฉ์ ์ฐพ์ต๋๋ค.", |
|
"biomimicry": "์์ฐ์์ ์๊ฐ์ ๋ฐ์ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. 38์ต๋
์งํ์ ์งํ๋ฅผ ๋ธ๋๋ฉ์ ์ ์ฉํฉ๋๋ค.", |
|
"cognitive": "์ธ์ง ์ฒ๋ฆฌ๋ฅผ ์ต์ํํ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. 1-3์์ ์ ์ฌ์ด ๋ฐ์์ผ๋ก ์ฆ๊ฐ์ ์ธ์๊ณผ ๊ธฐ์ต์ ๋์ต๋๋ค.", |
|
"vonrestorff": "๋
ํนํ๊ณ ๊ธฐ์ต์ ๋จ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ์นดํ
๊ณ ๋ฆฌ ๊ด์ต์ ์๋์ ์ผ๋ก ์๋ฐํ์ฌ 30๋ฐฐ ๋ ์ ๊ธฐ์ต๋๊ฒ ํฉ๋๋ค.", |
|
"network": "๋คํธ์ํฌ ๊ฐ์น๋ฅผ ๊ทน๋ํํ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ์ฌ์ฉ์๊ฐ ๋ง์์๋ก ๊ฐ์น๊ฐ ์ฆ๊ฐํ๋ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํฉ๋๋ค.", |
|
"memetics": "๋ฌธํ์ ์ผ๋ก ๋ณต์ ๋๊ณ ์งํํ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ๋ฐ์ฒ๋ผ ์์ฐ์ค๋ฝ๊ฒ ํผ์ ธ๋๊ฐ๋ ๋ฐ์ด๋ด ์์๋ฅผ ๋ด์ฌํํฉ๋๋ค.", |
|
"color": "์์ ์ฐ์๊ณผ ๊ฐ์ ์ ํ์ฉํ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ๋นจ๊ฐ(์ด์ ), ํ๋(์ ๋ขฐ), ์ด๋ก(์์ฐ) ๋ฑ ์์ ์ฌ๋ฆฌ๋ฅผ ์ ์ฉํฉ๋๋ค.", |
|
"gestalt": "์ง๊ฐ ์๋ฆฌ๋ฅผ ํ์ฉํ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ์ ์ฒด๊ฐ ๋ถ๋ถ์ ํฉ๋ณด๋ค ํฌ๋ค๋ ์์น์ผ๋ก ํตํฉ์ ๋ธ๋๋ ๊ฒฝํ์ ์ค๊ณํฉ๋๋ค." |
|
} |
|
|
|
|
|
SQUARE_THEORY_PROMPT = """ |
|
๋น์ ์ Square Theory ์ ๋ฌธ๊ฐ์
๋๋ค. Square Theory๋ 4๊ฐ์ ๋จ์ด๊ฐ ์๋ฏธ์ ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์ฌ๊ฐํ์ ์ด๋ฃจ๋ ๊ตฌ์กฐ์
๋๋ค. |
|
๋ธ๋๋๋ช
์ด Square๋ฅผ ์์ฑํ๋ฉฐ "์ํ!" ๋ชจ๋จผํธ๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค. |
|
|
|
์ฌ์ฉ์ ์
๋ ฅ(์
์ข
/ํค์๋)์ ๋ฐ์ ๋ค์ JSON ํ์์ ๋ฐฐ์ด์ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"tl": "์ผ์ชฝ์๋จ", "tr": "์ค๋ฅธ์ชฝ์๋จ", "bl": "์ผ์ชฝํ๋จ", "br": "์ค๋ฅธ์ชฝํ๋จ", |
|
"top_edge": "์๋จ ๊ด๊ณ", "bottom_edge": "ํ๋จ ๊ด๊ณ", |
|
"left_edge": "์ผ์ชฝ ๊ด๊ณ", "right_edge": "์ค๋ฅธ์ชฝ ๊ด๊ณ", |
|
"slogan": "์ฌ๋ก๊ฑด", |
|
"explanation": "์ ํจ๊ณผ์ ์ธ์ง" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
CONCEPTUAL_BLENDING_PROMPT = """ |
|
๋น์ ์ Conceptual Blending Theory ์ ๋ฌธ๊ฐ์
๋๋ค. ๋ ๊ฐ ์ด์์ ๊ฐ๋
์ ํผํฉํ์ฌ ์๋ก์ด ์๋ฏธ๋ฅผ ์ฐฝ์ถํฉ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"input_space1": "์ฒซ ๋ฒ์งธ ๊ฐ๋
", |
|
"input_space2": "๋ ๋ฒ์งธ ๊ฐ๋
", |
|
"generic_space": "๊ณตํต ๊ตฌ์กฐ", |
|
"blended_space": "ํผํฉ๋ ์๋ก์ด ์๋ฏธ", |
|
"emergent_properties": "์ฐฝ๋ฐ์ ์์ฑ๋ค", |
|
"slogan": "์ฌ๋ก๊ฑด", |
|
"explanation": "ํผํฉ์ด ํจ๊ณผ์ ์ธ ์ด์ " |
|
} |
|
|
|
์์: Netflix = Net(์ธํฐ๋ท) + Flix(์ํ) โ ์จ๋ผ์ธ ์คํธ๋ฆฌ๋ฐ์ ์๋ก์ด ๊ฐ๋
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
SOUND_SYMBOLISM_PROMPT = """ |
|
๋น์ ์ Sound Symbolism ์ ๋ฌธ๊ฐ์
๋๋ค. ์์์ ์๋ฏธ ๊ฐ์ ์ฐ๊ด์ฑ์ ํ์ฉํฉ๋๋ค. |
|
|
|
์ํฅ ์์น: |
|
- ์ ์ค๋ชจ์(i,e): ์๊ณ , ๋น ๋ฅด๊ณ , ๊ฐ๋ฒผ์ |
|
- ํ์ค๋ชจ์(o,u): ํฌ๊ณ , ๋๋ฆฌ๊ณ , ๋ฌด๊ฑฐ์ |
|
- ์ ์(l,r,m,n): ๋ถ๋๋ฝ๊ณ ์ ์ฐํจ |
|
- ํ์ด์(p,t,k,b,d,g): ๊ฐํ๊ณ ์ญ๋์ |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"phonetic_analysis": "์์ฑ ๋ถ์", |
|
"sound_meaning": "์ํฅ์ด ์ ๋ฌํ๋ ์๋ฏธ", |
|
"target_emotion": "๋ชฉํ ๊ฐ์ ", |
|
"industry_fit": "์
์ข
์ ํฉ์ฑ", |
|
"pronunciation_guide": "๋ฐ์ ๊ฐ์ด๋", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
LINGUISTIC_RELATIVITY_PROMPT = """ |
|
๋น์ ์ Linguistic Relativity ์ ๋ฌธ๊ฐ์
๋๋ค. ์ธ์ด๋ณ ์ฌ๊ณ ๋ฐฉ์ ์ฐจ์ด๋ฅผ ๊ณ ๋ คํฉ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ค์ธ์ด ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๊ธ๋ก๋ฒ ๋ธ๋๋๋ช
", |
|
"korean_adaptation": "ํ๊ตญ์ด ์ ์", |
|
"english_meaning": "์์ด ์๋ฏธ", |
|
"cultural_considerations": "๋ฌธํ์ ๊ณ ๋ ค์ฌํญ", |
|
"avoid_meanings": "ํผํด์ผ ํ ์๋ฏธ๋ค", |
|
"localization_strategy": "ํ์งํ ์ ๋ต", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
ARCHETYPE_THEORY_PROMPT = """ |
|
๋น์ ์ Jung์ Archetype Theory ์ ๋ฌธ๊ฐ์
๋๋ค. 12๊ฐ์ง ์ํ ์ค ํ๋๋ฅผ ์ ํํ์ฌ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
12 ์ํ: Innocent, Hero, Outlaw, Explorer, Creator, Ruler, Magician, Lover, Caregiver, Jester, Sage, Regular Guy |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"archetype": "์ ํ๋ ์ํ", |
|
"archetype_traits": "์ํ์ ํน์ง๋ค", |
|
"brand_personality": "๋ธ๋๋ ์ฑ๊ฒฉ", |
|
"visual_direction": "์๊ฐ์ ๋ฐฉํฅ", |
|
"voice_tone": "๋ชฉ์๋ฆฌ ํค", |
|
"slogan": "์ฌ๋ก๊ฑด", |
|
"mythology_reference": "์ ํ์ ์ฐธ์กฐ" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
JOBS_TO_BE_DONE_PROMPT = """ |
|
๋น์ ์ Jobs-to-be-Done Theory ์ ๋ฌธ๊ฐ์
๋๋ค. ๊ณ ๊ฐ์ด ํด๊ฒฐํ๋ ค๋ '์ผ'์ ์ด์ ์ ๋ง์ถฅ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"functional_job": "๊ธฐ๋ฅ์ ์ผ", |
|
"emotional_job": "๊ฐ์ ์ ์ผ", |
|
"social_job": "์ฌํ์ ์ผ", |
|
"job_statement": "ํต์ฌ Job ๋ฌธ์ฅ", |
|
"outcome_metrics": "์ฑ๊ณผ ์งํ", |
|
"slogan": "์ฌ๋ก๊ฑด", |
|
"value_proposition": "๊ฐ์น ์ ์" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
SCAMPER_PROMPT = """ |
|
๋น์ ์ SCAMPER Method ์ ๋ฌธ๊ฐ์
๋๋ค. 7๊ฐ์ง ์ฐฝ์์ ๊ธฐ๋ฒ์ ์ ์ฉํฉ๋๋ค. |
|
|
|
S - Substitute (๋์ฒด) |
|
C - Combine (๊ฒฐํฉ) |
|
A - Adapt (์ ์) |
|
M - Modify/Magnify (์์ /ํ๋) |
|
P - Put to another use (๋ค๋ฅธ ์ฉ๋) |
|
E - Eliminate (์ ๊ฑฐ) |
|
R - Reverse (์ญ์ ) |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"scamper_technique": "์ฌ์ฉ๋ ๊ธฐ๋ฒ", |
|
"original_concept": "์๋ ๊ฐ๋
", |
|
"transformation": "๋ณํ ๊ณผ์ ", |
|
"innovative_aspect": "ํ์ ์ ์ธก๋ฉด", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
DESIGN_THINKING_PROMPT = """ |
|
๋น์ ์ IDEO์ Design Thinking ์ ๋ฌธ๊ฐ์
๋๋ค. ์ธ๊ฐ ์ค์ฌ ํ์ ์ ์ถ๊ตฌํฉ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"user_insight": "์ฌ์ฉ์ ํต์ฐฐ", |
|
"pain_point": "ํด๊ฒฐํ๋ ๋ฌธ์ ์ ", |
|
"desirability": "๋ฐ๋์งํจ (์ธ๊ฐ)", |
|
"feasibility": "์คํ๊ฐ๋ฅ์ฑ (๊ธฐ์ )", |
|
"viability": "์์กด๊ฐ๋ฅ์ฑ (๋น์ฆ๋์ค)", |
|
"prototype_concept": "ํ๋กํ ํ์
์ปจ์
", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
BIOMIMICRY_PROMPT = """ |
|
๋น์ ์ Biomimicry ์ ๋ฌธ๊ฐ์
๋๋ค. ์์ฐ์์ ์๊ฐ์ ๋ฐ์ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"natural_inspiration": "์์ฐ์ ์๊ฐ์", |
|
"biomimetic_principle": "์์ฒด๋ชจ๋ฐฉ ์๋ฆฌ", |
|
"form_function": "ํํ์ ๊ธฐ๋ฅ", |
|
"sustainability_aspect": "์ง์๊ฐ๋ฅ์ฑ ์ธก๋ฉด", |
|
"adaptation_strategy": "์ ์ ์ ๋ต", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
COGNITIVE_LOAD_PROMPT = """ |
|
๋น์ ์ Cognitive Load Theory ์ ๋ฌธ๊ฐ์
๋๋ค. ์ธ์ง ์ฒ๋ฆฌ๋ฅผ ์ต์ํํ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"syllable_count": "์์ ์", |
|
"processing_ease": "์ฒ๋ฆฌ ์ฉ์ด์ฑ ์ ์", |
|
"memory_hooks": "๊ธฐ์ต ๊ณ ๋ฆฌ", |
|
"pronunciation_simplicity": "๋ฐ์ ๋จ์์ฑ", |
|
"cognitive_fluency": "์ธ์ง์ ์ ์ฐฝ์ฑ", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
VON_RESTORFF_PROMPT = """ |
|
๋น์ ์ Von Restorff Effect ์ ๋ฌธ๊ฐ์
๋๋ค. ๋
ํนํ๊ณ ๊ธฐ์ต์ ๋จ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"category_norm": "์นดํ
๊ณ ๋ฆฌ ํ์ค", |
|
"deviation_strategy": "์ผํ ์ ๋ต", |
|
"uniqueness_factors": "๋
ํน์ฑ ์์๋ค", |
|
"memorability_score": "๊ธฐ์ต์ฑ ์ ์", |
|
"attention_triggers": "์ฃผ์ ํธ๋ฆฌ๊ฑฐ", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
NETWORK_EFFECTS_PROMPT = """ |
|
๋น์ ์ Network Effects ์ ๋ฌธ๊ฐ์
๋๋ค. ๋คํธ์ํฌ ๊ฐ์น๋ฅผ ๊ทน๋ํํ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"network_type": "๋คํธ์ํฌ ์ ํ", |
|
"viral_coefficient": "๋ฐ์ด๋ด ๊ณ์", |
|
"sharing_ease": "๊ณต์ ์ฉ์ด์ฑ", |
|
"community_aspect": "์ปค๋ฎค๋ํฐ ์ธก๋ฉด", |
|
"network_value": "๋คํธ์ํฌ ๊ฐ์น", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
MEMETICS_PROMPT = """ |
|
๋น์ ์ Memetics ์ ๋ฌธ๊ฐ์
๋๋ค. ๋ฌธํ์ ์ผ๋ก ๋ณต์ ๋๊ณ ์งํํ๋ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"meme_structure": "๋ฐ ๊ตฌ์กฐ", |
|
"replication_ease": "๋ณต์ ์ฉ์ด์ฑ", |
|
"mutation_potential": "๋ณ์ด ์ ์ฌ๋ ฅ", |
|
"cultural_fitness": "๋ฌธํ์ ์ ํฉ๋", |
|
"transmission_channels": "์ ๋ฌ ์ฑ๋", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
COLOR_PSYCHOLOGY_PROMPT = """ |
|
๋น์ ์ Color Psychology ์ ๋ฌธ๊ฐ์
๋๋ค. ์์ ์ฐ์๊ณผ ๊ฐ์ ์ ํ์ฉํ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"primary_color": "์ฃผ ์์", |
|
"color_meaning": "์์ ์๋ฏธ", |
|
"emotional_response": "๊ฐ์ ์ ๋ฐ์", |
|
"cultural_associations": "๋ฌธํ์ ์ฐ์", |
|
"industry_alignment": "์
์ข
์ ๋ ฌ", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
GESTALT_PROMPT = """ |
|
๋น์ ์ Gestalt Theory ์ ๋ฌธ๊ฐ์
๋๋ค. ์ง๊ฐ ์๋ฆฌ๋ฅผ ํ์ฉํ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. |
|
|
|
๋ค์ JSON ํ์์ผ๋ก ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์: |
|
{ |
|
"brand_name": "๋ธ๋๋๋ช
", |
|
"gestalt_principle": "ํ์ฉ ์์น", |
|
"visual_structure": "์๊ฐ์ ๊ตฌ์กฐ", |
|
"perceptual_grouping": "์ง๊ฐ์ ๊ทธ๋ฃนํ", |
|
"figure_ground": "์ ๊ฒฝ-๋ฐฐ๊ฒฝ ๊ด๊ณ", |
|
"closure_effect": "ํ์ ํจ๊ณผ", |
|
"slogan": "์ฌ๋ก๊ฑด" |
|
} |
|
|
|
๋ฐ๋์ ์ ํจํ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
""" |
|
|
|
|
|
THEORY_PROMPTS = { |
|
"square": SQUARE_THEORY_PROMPT, |
|
"blending": CONCEPTUAL_BLENDING_PROMPT, |
|
"sound": SOUND_SYMBOLISM_PROMPT, |
|
"linguistic": LINGUISTIC_RELATIVITY_PROMPT, |
|
"archetype": ARCHETYPE_THEORY_PROMPT, |
|
"jobs": JOBS_TO_BE_DONE_PROMPT, |
|
"scamper": SCAMPER_PROMPT, |
|
"design": DESIGN_THINKING_PROMPT, |
|
"biomimicry": BIOMIMICRY_PROMPT, |
|
"cognitive": COGNITIVE_LOAD_PROMPT, |
|
"vonrestorff": VON_RESTORFF_PROMPT, |
|
"network": NETWORK_EFFECTS_PROMPT, |
|
"memetics": MEMETICS_PROMPT, |
|
"color": COLOR_PSYCHOLOGY_PROMPT, |
|
"gestalt": GESTALT_PROMPT |
|
} |
|
|
|
def generate_by_theory(industry: str, keywords: str, theory: str, count: int = 3) -> Tuple[str, str]: |
|
"""ํน์ ์ด๋ก ์ผ๋ก ๋ธ๋๋ ์์ฑ""" |
|
|
|
if not industry or not keywords: |
|
return "โ ๏ธ ์
์ข
๊ณผ ํค์๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.", "" |
|
|
|
prompt = THEORY_PROMPTS.get(theory, SQUARE_THEORY_PROMPT) |
|
user_input = f"""์
์ข
: {industry} |
|
ํค์๋: {keywords} |
|
|
|
์ ์ ๋ณด๋ก {count}๊ฐ์ ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์. |
|
๋ฐ๋์ JSON ํ์์ผ๋ก ์๋ตํ์ธ์. |
|
๊ฒฐ๊ณผ๋ ๋ธ๋๋ ๊ฐ์ฒด๋ค์ JSON ๋ฐฐ์ด์ด์ด์ผ ํฉ๋๋ค.""" |
|
|
|
try: |
|
response = client.chat.completions.create( |
|
model="gpt-4o-mini", |
|
messages=[ |
|
{"role": "system", "content": prompt}, |
|
{"role": "user", "content": user_input} |
|
], |
|
temperature=0.8, |
|
max_tokens=2000, |
|
response_format={"type": "json_object"} |
|
) |
|
|
|
content = response.choices[0].message.content |
|
data = json.loads(content) |
|
|
|
|
|
if isinstance(data, dict): |
|
if "results" in data: |
|
results = data["results"] |
|
elif "brands" in data: |
|
results = data["brands"] |
|
elif "brand_name" in data: |
|
|
|
results = [data] |
|
else: |
|
|
|
results = [] |
|
for key, value in data.items(): |
|
if isinstance(value, list): |
|
results = value |
|
break |
|
elif isinstance(value, dict) and "brand_name" in value: |
|
results = [value] |
|
break |
|
else: |
|
results = data |
|
|
|
if not isinstance(results, list): |
|
results = [results] |
|
|
|
|
|
markdown = generate_theory_markdown(theory, results, industry, keywords) |
|
|
|
|
|
html = generate_theory_visualization(theory, results) |
|
|
|
return markdown, html |
|
|
|
except Exception as e: |
|
error_msg = f"โ {theory} ์ด๋ก ์ค๋ฅ: {str(e)}" |
|
print(error_msg) |
|
return error_msg, "" |
|
|
|
def generate_theory_markdown(theory: str, results: List[Dict], industry: str, keywords: str) -> str: |
|
"""์ด๋ก ๋ณ ๋ง์ถค ๋งํฌ๋ค์ด ์์ฑ""" |
|
|
|
theory_names = { |
|
"square": "Square Theory", |
|
"blending": "Conceptual Blending", |
|
"sound": "Sound Symbolism", |
|
"linguistic": "Linguistic Relativity", |
|
"archetype": "Archetype Theory", |
|
"jobs": "Jobs-to-be-Done", |
|
"scamper": "SCAMPER Method", |
|
"design": "Design Thinking", |
|
"biomimicry": "Biomimicry", |
|
"cognitive": "Cognitive Load Theory", |
|
"vonrestorff": "Von Restorff Effect", |
|
"network": "Network Effects", |
|
"memetics": "Memetics", |
|
"color": "Color Psychology", |
|
"gestalt": "Gestalt Principles" |
|
} |
|
|
|
theory_icons = { |
|
"square": "๐ฆ", |
|
"blending": "๐", |
|
"sound": "๐", |
|
"linguistic": "๐", |
|
"archetype": "๐ญ", |
|
"jobs": "โ
", |
|
"scamper": "๐ง", |
|
"design": "๐ญ", |
|
"biomimicry": "๐ฟ", |
|
"cognitive": "๐ง ", |
|
"vonrestorff": "โก", |
|
"network": "๐", |
|
"memetics": "๐งฌ", |
|
"color": "๐จ", |
|
"gestalt": "๐๏ธ" |
|
} |
|
|
|
markdown = f"""# {theory_icons[theory]} {theory_names[theory]} |
|
|
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 10px; margin-bottom: 20px;"> |
|
<h3 style="margin: 0 0 10px 0;">์ด๋ก ๊ฐ์</h3> |
|
<p style="margin: 0; line-height: 1.6;">{THEORY_DESCRIPTIONS[theory]}</p> |
|
</div> |
|
|
|
**์
์ข
**: {industry} | **ํค์๋**: {keywords} |
|
*์์ฑ ์๊ฐ: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}* |
|
|
|
--- |
|
""" |
|
|
|
for idx, result in enumerate(results, 1): |
|
brand_name = result.get('brand_name', 'N/A') |
|
slogan = result.get('slogan', 'N/A') |
|
|
|
markdown += f"\n## {idx}. {brand_name}\n" |
|
markdown += f"**์ฌ๋ก๊ฑด**: *\"{slogan}\"*\n\n" |
|
|
|
|
|
if theory == "square": |
|
markdown += f""" |
|
### Square ๊ตฌ์กฐ |
|
``` |
|
[{result.get('tl')}] โ({result.get('top_edge')})โ [{result.get('tr')}] |
|
โ โ |
|
({result.get('left_edge')}) ({result.get('right_edge')}) |
|
โ โ |
|
[{result.get('bl')}] โ({result.get('bottom_edge')})โ [{result.get('br')}] |
|
``` |
|
""" |
|
elif theory == "blending": |
|
markdown += f""" |
|
### ๊ฐ๋
ํผํฉ |
|
- **์
๋ ฅ ๊ณต๊ฐ 1**: {result.get('input_space1')} |
|
- **์
๋ ฅ ๊ณต๊ฐ 2**: {result.get('input_space2')} |
|
- **์ผ๋ฐ ๊ณต๊ฐ**: {result.get('generic_space')} |
|
- **ํผํฉ ๊ณต๊ฐ**: {result.get('blended_space')} |
|
- **์ฐฝ๋ฐ์ ์์ฑ**: {result.get('emergent_properties')} |
|
""" |
|
elif theory == "sound": |
|
markdown += f""" |
|
### ์ํฅ ๋ถ์ |
|
- **์์ฑ ๋ถ์**: {result.get('phonetic_analysis')} |
|
- **์ํฅ ์๋ฏธ**: {result.get('sound_meaning')} |
|
- **๋ชฉํ ๊ฐ์ **: {result.get('target_emotion')} |
|
- **๋ฐ์ ๊ฐ์ด๋**: {result.get('pronunciation_guide')} |
|
""" |
|
elif theory == "archetype": |
|
markdown += f""" |
|
### ์ํ ๋ถ์ |
|
- **์ํ**: {result.get('archetype')} |
|
- **์ํ ํน์ง**: {result.get('archetype_traits')} |
|
- **๋ธ๋๋ ์ฑ๊ฒฉ**: {result.get('brand_personality')} |
|
- **๋ชฉ์๋ฆฌ ํค**: {result.get('voice_tone')} |
|
""" |
|
|
|
|
|
explanation = result.get('explanation', result.get('value_proposition', '')) |
|
if explanation: |
|
markdown += f"\n๐ก **ํต์ฌ ๊ฐ์น**: {explanation}\n" |
|
|
|
markdown += "\n---\n" |
|
|
|
return markdown |
|
|
|
def generate_theory_visualization(theory: str, results: List[Dict]) -> str: |
|
"""์ด๋ก ๋ณ ๋ง์ถค ์๊ฐํ ์์ฑ""" |
|
|
|
html_parts = [] |
|
|
|
for idx, result in enumerate(results, 1): |
|
if theory == "square": |
|
html_parts.append(visualize_square_brand(result)) |
|
elif theory == "blending": |
|
html_parts.append(visualize_conceptual_blend(result)) |
|
elif theory == "sound": |
|
html_parts.append(visualize_sound_symbolism(result)) |
|
elif theory == "archetype": |
|
html_parts.append(visualize_archetype(result)) |
|
elif theory == "color": |
|
html_parts.append(visualize_color_psychology(result)) |
|
else: |
|
html_parts.append(visualize_generic_brand(result, theory)) |
|
|
|
return "\n".join(html_parts) |
|
|
|
|
|
def visualize_square_brand(brand: Dict) -> str: |
|
"""Square Theory ์๊ฐํ""" |
|
return f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);"> |
|
<h2 style="text-align: center; color: white; margin-bottom: 10px;">{brand.get('brand_name', 'Brand')}</h2> |
|
<p style="text-align: center; font-style: italic; color: rgba(255,255,255,0.9);">"{brand.get('slogan', '')}"</p> |
|
|
|
<div style="position: relative; width: 100%; height: 300px; background: rgba(255,255,255,0.1); border-radius: 12px; padding: 30px; margin-top: 20px;"> |
|
<!-- Square ๊ตฌ์กฐ ์๊ฐํ --> |
|
<div style="position: absolute; top: 30px; left: 30px; background: rgba(255,255,255,0.9); color: #667eea; padding: 15px 20px; border-radius: 8px; font-weight: bold; box-shadow: 0 4px 15px rgba(0,0,0,0.1);"> |
|
{brand.get('tl', '?')} |
|
</div> |
|
<div style="position: absolute; top: 30px; right: 30px; background: rgba(255,255,255,0.9); color: #e74c3c; padding: 15px 20px; border-radius: 8px; font-weight: bold; box-shadow: 0 4px 15px rgba(0,0,0,0.1);"> |
|
{brand.get('tr', '?')} |
|
</div> |
|
<div style="position: absolute; bottom: 30px; left: 30px; background: rgba(255,255,255,0.9); color: #f39c12; padding: 15px 20px; border-radius: 8px; font-weight: bold; box-shadow: 0 4px 15px rgba(0,0,0,0.1);"> |
|
{brand.get('bl', '?')} |
|
</div> |
|
<div style="position: absolute; bottom: 30px; right: 30px; background: rgba(255,255,255,0.9); color: #27ae60; padding: 15px 20px; border-radius: 8px; font-weight: bold; box-shadow: 0 4px 15px rgba(0,0,0,0.1);"> |
|
{brand.get('br', '?')} |
|
</div> |
|
|
|
<!-- ๋ธ๋๋๋ช
์ค์ --> |
|
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px 40px; border-radius: 12px; box-shadow: 0 8px 25px rgba(0,0,0,0.15);"> |
|
<div style="font-size: 1.8em; font-weight: bold; color: #2c3e50; text-align: center;">{brand.get('brand_name', 'Brand')}</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_conceptual_blend(brand: Dict) -> str: |
|
"""Conceptual Blending ์๊ฐํ""" |
|
brand_name = brand.get('brand_name', 'Brand') |
|
input1 = brand.get('input_space1', 'Concept 1') |
|
input2 = brand.get('input_space2', 'Concept 2') |
|
blended = brand.get('blended_space', 'Blended Concept') |
|
slogan = brand.get('slogan', '') |
|
|
|
return f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: linear-gradient(135deg, #ff6b6b 0%, #4ecdc4 100%); padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);"> |
|
<h2 style="text-align: center; color: white; margin-bottom: 20px;">{brand_name}</h2> |
|
|
|
<div style="display: flex; justify-content: space-around; align-items: center; margin: 30px 0;"> |
|
<div style="text-align: center; padding: 30px; background: rgba(255,255,255,0.9); color: #ff6b6b; border-radius: 50%; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center; box-shadow: 0 5px 20px rgba(0,0,0,0.2);"> |
|
<div> |
|
<strong>Input 1</strong><br> |
|
<span style="font-size: 0.9em;">{input1}</span> |
|
</div> |
|
</div> |
|
|
|
<div style="font-size: 3em; color: white;">+</div> |
|
|
|
<div style="text-align: center; padding: 30px; background: rgba(255,255,255,0.9); color: #4ecdc4; border-radius: 50%; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center; box-shadow: 0 5px 20px rgba(0,0,0,0.2);"> |
|
<div> |
|
<strong>Input 2</strong><br> |
|
<span style="font-size: 0.9em;">{input2}</span> |
|
</div> |
|
</div> |
|
|
|
<div style="font-size: 3em; color: white;">=</div> |
|
|
|
<div style="text-align: center; padding: 30px; background: white; color: #2c3e50; border-radius: 20px; width: 180px; height: 180px; display: flex; align-items: center; justify-content: center; box-shadow: 0 8px 25px rgba(0,0,0,0.3);"> |
|
<div> |
|
<strong style="font-size: 1.2em;">Blend</strong><br> |
|
<span style="font-size: 0.95em;">{blended}</span> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<p style="text-align: center; font-style: italic; color: white; font-size: 1.1em; margin-top: 20px;">"{slogan}"</p> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_sound_symbolism(brand: Dict) -> str: |
|
"""Sound Symbolism ์๊ฐํ""" |
|
return f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);"> |
|
<h2 style="text-align: center; color: white; margin-bottom: 20px;">{brand.get('brand_name', 'Brand')}</h2> |
|
|
|
<div style="text-align: center; margin: 30px 0;"> |
|
<div style="font-size: 4em; letter-spacing: 0.3em; color: white; text-shadow: 2px 2px 4px rgba(0,0,0,0.2); font-weight: bold;"> |
|
{brand.get('brand_name', 'BRAND')} |
|
</div> |
|
</div> |
|
|
|
<div style="background: rgba(255,255,255,0.9); padding: 25px; border-radius: 15px; margin: 20px 0;"> |
|
<div style="text-align: center; margin-bottom: 15px;"> |
|
<strong style="color: #fa709a; font-size: 1.2em;">์์ฑ ๋ถ์</strong><br> |
|
<span style="color: #555;">{brand.get('phonetic_analysis', '')}</span> |
|
</div> |
|
|
|
<div style="text-align: center;"> |
|
<strong style="color: #fee140; font-size: 1.2em;">์ํฅ์ด ์ ๋ฌํ๋ ๊ฐ์ </strong><br> |
|
<span style="color: #555;">{brand.get('sound_meaning', '')}</span> |
|
</div> |
|
</div> |
|
|
|
<div style="text-align: center; color: white; font-style: italic;"> |
|
๋ฐ์: {brand.get('pronunciation_guide', '')} |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_archetype(brand: Dict) -> str: |
|
"""Archetype Theory ์๊ฐํ""" |
|
archetype_colors = { |
|
"Hero": "#e74c3c", |
|
"Creator": "#9b59b6", |
|
"Sage": "#3498db", |
|
"Explorer": "#1abc9c", |
|
"Innocent": "#f1c40f", |
|
"Jester": "#e67e22", |
|
"Lover": "#e91e63", |
|
"Caregiver": "#00bcd4", |
|
"Ruler": "#795548", |
|
"Magician": "#673ab7", |
|
"Outlaw": "#212121", |
|
"Regular Guy": "#607d8b" |
|
} |
|
|
|
archetype = brand.get('archetype', 'Hero') |
|
color = archetype_colors.get(archetype, "#3498db") |
|
|
|
return f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: linear-gradient(135deg, {color} 0%, #2c3e50 100%); padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);"> |
|
<h2 style="text-align: center; color: white; margin-bottom: 30px;">{brand.get('brand_name', 'Brand')}</h2> |
|
|
|
<div style="text-align: center; margin: 30px 0;"> |
|
<div style="display: inline-block; padding: 50px; background: rgba(255,255,255,0.15); color: white; border-radius: 50%; width: 250px; height: 250px; border: 3px solid rgba(255,255,255,0.3);"> |
|
<h3 style="margin: 0 0 15px 0; font-size: 2em;">{archetype}</h3> |
|
<p style="margin: 0; font-size: 1em; line-height: 1.5;">{brand.get('archetype_traits', '')}</p> |
|
</div> |
|
</div> |
|
|
|
<div style="background: rgba(255,255,255,0.9); padding: 25px; border-radius: 15px; margin: 20px 0;"> |
|
<p style="margin: 10px 0;"><strong style="color: {color};">๋ธ๋๋ ์ฑ๊ฒฉ</strong>: {brand.get('brand_personality', '')}</p> |
|
<p style="margin: 10px 0;"><strong style="color: {color};">๋ชฉ์๋ฆฌ ํค</strong>: {brand.get('voice_tone', '')}</p> |
|
</div> |
|
|
|
<p style="text-align: center; font-style: italic; font-size: 1.3em; color: white; margin-top: 30px;">"{brand.get('slogan', '')}"</p> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_color_psychology(brand: Dict) -> str: |
|
"""Color Psychology ์๊ฐํ""" |
|
color = brand.get('primary_color', '#3498db') |
|
|
|
return f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: #f8f9fa; padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);"> |
|
<h2 style="text-align: center; color: #2c3e50; margin-bottom: 30px;">{brand.get('brand_name', 'Brand')}</h2> |
|
|
|
<div style="text-align: center; margin: 30px 0;"> |
|
<div style="display: inline-block; width: 300px; height: 300px; background: {color}; border-radius: 20px; box-shadow: 0 15px 40px rgba(0,0,0,0.3); position: relative; overflow: hidden;"> |
|
<div style="position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); color: white; font-size: 1.5em; font-weight: bold; text-shadow: 2px 2px 4px rgba(0,0,0,0.5);"> |
|
{brand.get('primary_color', '')} |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div style="background: white; padding: 25px; border-radius: 15px; box-shadow: 0 5px 15px rgba(0,0,0,0.1);"> |
|
<p style="margin: 10px 0;"><strong style="color: {color};">์์ ์๋ฏธ</strong>: {brand.get('color_meaning', '')}</p> |
|
<p style="margin: 10px 0;"><strong style="color: {color};">๊ฐ์ ์ ๋ฐ์</strong>: {brand.get('emotional_response', '')}</p> |
|
<p style="margin: 10px 0;"><strong style="color: {color};">๋ฌธํ์ ์ฐ์</strong>: {brand.get('cultural_associations', '')}</p> |
|
</div> |
|
|
|
<p style="text-align: center; font-style: italic; margin-top: 30px; color: #7f8c8d; font-size: 1.2em;">"{brand.get('slogan', '')}"</p> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_generic_brand(brand: Dict, theory: str) -> str: |
|
"""์ผ๋ฐ์ ์ธ ๋ธ๋๋ ์๊ฐํ""" |
|
|
|
json_str = json.dumps(brand, ensure_ascii=False, indent=2) |
|
|
|
theory_gradients = { |
|
"jobs": "linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)", |
|
"scamper": "linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)", |
|
"design": "linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%)", |
|
"biomimicry": "linear-gradient(135deg, #d4fc79 0%, #96e6a1 100%)", |
|
"cognitive": "linear-gradient(135deg, #fa709a 0%, #fee140 100%)", |
|
"vonrestorff": "linear-gradient(135deg, #f093fb 0%, #f5576c 100%)", |
|
"network": "linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)", |
|
"memetics": "linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)", |
|
"gestalt": "linear-gradient(135deg, #fd6585 0%, #0d25b9 100%)" |
|
} |
|
|
|
gradient = theory_gradients.get(theory, "linear-gradient(135deg, #667eea 0%, #764ba2 100%)") |
|
|
|
html = f""" |
|
<div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: {gradient}; padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);"> |
|
<h2 style="text-align: center; color: white; margin-bottom: 10px;">{brand.get('brand_name', 'Brand')}</h2> |
|
<p style="text-align: center; font-style: italic; color: rgba(255,255,255,0.9); margin-bottom: 30px; font-size: 1.2em;">"{brand.get('slogan', '')}"</p> |
|
|
|
<div style="background: rgba(255,255,255,0.95); padding: 25px; border-radius: 15px; font-family: 'Courier New', monospace; font-size: 0.9em;"> |
|
<pre style="margin: 0; white-space: pre-wrap; color: #2c3e50;">{json_str}</pre> |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
return html |
|
|
|
|
|
with gr.Blocks( |
|
title="Ultimate Brand Theory Generator", |
|
theme=gr.themes.Soft(), |
|
css=""" |
|
.gradio-container { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
} |
|
.tab-nav button { |
|
font-size: 0.9em !important; |
|
padding: 10px 15px !important; |
|
} |
|
""" |
|
) as demo: |
|
gr.Markdown(""" |
|
<div style="text-align: center; padding: 30px 0;"> |
|
<h1 style="font-size: 2.5em; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 10px;"> |
|
๐ Ultimate Brand Theory Generator |
|
</h1> |
|
<p style="font-size: 1.2em; color: #7f8c8d;">15๊ฐ ์ด๋ก ์ ํ์ฉํ ์ข
ํฉ ๋ธ๋๋ ์์ฑ๊ธฐ</p> |
|
</div> |
|
""") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1, min_width=300): |
|
gr.Markdown(""" |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 20px;"> |
|
<h3 style="margin-top: 0;">๐ ๋ธ๋๋ ์ ๋ณด ์
๋ ฅ</h3> |
|
</div> |
|
""") |
|
|
|
industry_input = gr.Textbox( |
|
label="๐ญ ์
์ข
", |
|
placeholder="์: ์นดํ, ํผํธ๋์ค, ๊ต์ก, ๋ทฐํฐ...", |
|
value="์นดํ/์ปคํผ์" |
|
) |
|
|
|
keywords_input = gr.Textbox( |
|
label="๐ ํต์ฌ ํค์๋", |
|
placeholder="ํ๋ฆฌ๋ฏธ์, ํธ์ํ, ๋์์ ์ธ, ์นํ๊ฒฝ...", |
|
info="๋ธ๋๋๊ฐ ๋ด์์ผ ํ ํต์ฌ ๊ฐ์น๋ ํน์ง๋ค", |
|
lines=2 |
|
) |
|
|
|
gr.Markdown(""" |
|
<div style="background: #e3f2fd; padding: 15px; border-radius: 8px; margin-top: 20px;"> |
|
<h4 style="margin-top: 0; color: #1976d2;">๐ก ์ฌ์ฉ ๋ฐฉ๋ฒ</h4> |
|
<ol style="margin: 10px 0; padding-left: 20px;"> |
|
<li>์
์ข
๊ณผ ํค์๋๋ฅผ ์
๋ ฅํ์ธ์</li> |
|
<li>์ํ๋ ์ด๋ก ํญ์ ์ ํํ์ธ์</li> |
|
<li>๊ฐ ํญ์ ์์ฑ ๋ฒํผ์ ํด๋ฆญํ์ธ์</li> |
|
</ol> |
|
<p style="margin: 0; font-size: 0.9em; color: #555;"> |
|
๊ฐ ์ด๋ก ์ ๋
๋ฆฝ์ ์ผ๋ก ์๋ํ๋ฏ๋ก ์ํ๋ ๊ฒ๋ง ์ ํํด์ ์์ฑํ ์ ์์ต๋๋ค. |
|
</p> |
|
</div> |
|
""") |
|
|
|
with gr.Column(scale=3): |
|
|
|
with gr.Tabs(): |
|
|
|
with gr.Tab("๐ฆ Square Theory"): |
|
with gr.Row(): |
|
square_btn = gr.Button("Square Theory๋ก ์์ฑ", variant="primary", size="sm") |
|
square_output = gr.Markdown() |
|
square_visual = gr.HTML() |
|
square_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "square"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[square_output, square_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ Conceptual Blending"): |
|
with gr.Row(): |
|
blending_btn = gr.Button("Conceptual Blending์ผ๋ก ์์ฑ", variant="primary", size="sm") |
|
blending_output = gr.Markdown() |
|
blending_visual = gr.HTML() |
|
blending_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "blending"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[blending_output, blending_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ Sound Symbolism"): |
|
with gr.Row(): |
|
sound_btn = gr.Button("Sound Symbolism์ผ๋ก ์์ฑ", variant="primary", size="sm") |
|
sound_output = gr.Markdown() |
|
sound_visual = gr.HTML() |
|
sound_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "sound"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[sound_output, sound_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ Linguistic Relativity"): |
|
with gr.Row(): |
|
linguistic_btn = gr.Button("Linguistic Relativity๋ก ์์ฑ", variant="primary", size="sm") |
|
linguistic_output = gr.Markdown() |
|
linguistic_visual = gr.HTML() |
|
linguistic_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "linguistic"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[linguistic_output, linguistic_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ญ Archetype Theory"): |
|
with gr.Row(): |
|
archetype_btn = gr.Button("Archetype Theory๋ก ์์ฑ", variant="primary", size="sm") |
|
archetype_output = gr.Markdown() |
|
archetype_visual = gr.HTML() |
|
archetype_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "archetype"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[archetype_output, archetype_visual] |
|
) |
|
|
|
|
|
with gr.Tab("โ
Jobs-to-be-Done"): |
|
with gr.Row(): |
|
jobs_btn = gr.Button("Jobs-to-be-Done์ผ๋ก ์์ฑ", variant="primary", size="sm") |
|
jobs_output = gr.Markdown() |
|
jobs_visual = gr.HTML() |
|
jobs_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "jobs"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[jobs_output, jobs_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ง SCAMPER Method"): |
|
with gr.Row(): |
|
scamper_btn = gr.Button("SCAMPER Method๋ก ์์ฑ", variant="primary", size="sm") |
|
scamper_output = gr.Markdown() |
|
scamper_visual = gr.HTML() |
|
scamper_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "scamper"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[scamper_output, scamper_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ญ Design Thinking"): |
|
with gr.Row(): |
|
design_btn = gr.Button("Design Thinking์ผ๋ก ์์ฑ", variant="primary", size="sm") |
|
design_output = gr.Markdown() |
|
design_visual = gr.HTML() |
|
design_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "design"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[design_output, design_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ฟ Biomimicry"): |
|
with gr.Row(): |
|
biomimicry_btn = gr.Button("Biomimicry๋ก ์์ฑ", variant="primary", size="sm") |
|
biomimicry_output = gr.Markdown() |
|
biomimicry_visual = gr.HTML() |
|
biomimicry_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "biomimicry"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[biomimicry_output, biomimicry_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ง Cognitive Load"): |
|
with gr.Row(): |
|
cognitive_btn = gr.Button("Cognitive Load๋ก ์์ฑ", variant="primary", size="sm") |
|
cognitive_output = gr.Markdown() |
|
cognitive_visual = gr.HTML() |
|
cognitive_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "cognitive"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[cognitive_output, cognitive_visual] |
|
) |
|
|
|
|
|
with gr.Tab("โก Von Restorff Effect"): |
|
with gr.Row(): |
|
vonrestorff_btn = gr.Button("Von Restorff Effect๋ก ์์ฑ", variant="primary", size="sm") |
|
vonrestorff_output = gr.Markdown() |
|
vonrestorff_visual = gr.HTML() |
|
vonrestorff_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "vonrestorff"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[vonrestorff_output, vonrestorff_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐ Network Effects"): |
|
with gr.Row(): |
|
network_btn = gr.Button("Network Effects๋ก ์์ฑ", variant="primary", size="sm") |
|
network_output = gr.Markdown() |
|
network_visual = gr.HTML() |
|
network_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "network"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[network_output, network_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐งฌ Memetics"): |
|
with gr.Row(): |
|
memetics_btn = gr.Button("Memetics๋ก ์์ฑ", variant="primary", size="sm") |
|
memetics_output = gr.Markdown() |
|
memetics_visual = gr.HTML() |
|
memetics_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "memetics"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[memetics_output, memetics_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐จ Color Psychology"): |
|
with gr.Row(): |
|
color_btn = gr.Button("Color Psychology๋ก ์์ฑ", variant="primary", size="sm") |
|
color_output = gr.Markdown() |
|
color_visual = gr.HTML() |
|
color_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "color"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[color_output, color_visual] |
|
) |
|
|
|
|
|
with gr.Tab("๐๏ธ Gestalt Principles"): |
|
with gr.Row(): |
|
gestalt_btn = gr.Button("Gestalt Principles๋ก ์์ฑ", variant="primary", size="sm") |
|
gestalt_output = gr.Markdown() |
|
gestalt_visual = gr.HTML() |
|
gestalt_btn.click( |
|
lambda i, k: generate_by_theory(i, k, "gestalt"), |
|
inputs=[industry_input, keywords_input], |
|
outputs=[gestalt_output, gestalt_visual] |
|
) |
|
|
|
gr.Markdown(""" |
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; margin-top: 40px;"> |
|
<h3 style="margin-top: 0;">๐ฏ ํ์ฉ ๊ฐ์ด๋</h3> |
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-top: 20px;"> |
|
<div> |
|
<h4>1. ๋น๊ต ๋ถ์</h4> |
|
<p style="margin: 5px 0;">๊ฐ ์ด๋ก ์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํ์ฌ ๊ฐ์ฅ ์ ํฉํ ๋ธ๋๋ ์ ํ</p> |
|
</div> |
|
<div> |
|
<h4>2. ํ์ด๋ธ๋ฆฌ๋ ์ ๊ทผ</h4> |
|
<p style="margin: 5px 0;">์ฌ๋ฌ ์ด๋ก ์ ์ฅ์ ์ ๊ฒฐํฉํ ์๋ก์ด ๋ธ๋๋ ์ฐฝ์กฐ</p> |
|
</div> |
|
<div> |
|
<h4>3. ํ๊ฒ๋ณ ์ ํ</h4> |
|
<p style="margin: 5px 0;">๋ชฉํ ๊ณ ๊ฐ์ธต์ ๋ฐ๋ผ ๊ฐ์ฅ ํจ๊ณผ์ ์ธ ์ด๋ก ์ ํ</p> |
|
</div> |
|
<div> |
|
<h4>4. A/B ํ
์คํธ</h4> |
|
<p style="margin: 5px 0;">๋ค์ํ ์ด๋ก ๊ธฐ๋ฐ ๋ธ๋๋๋ก ์์ฅ ํ
์คํธ</p> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div style="margin-top: 30px; padding: 20px; background: #f8f9fa; border-radius: 10px;"> |
|
<h3 style="margin-top: 0;">๐ ๊ฐ ์ด๋ก ์ ๊ฐ์ </h3> |
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 15px;"> |
|
<div> |
|
<strong style="color: #3498db;">์ฆ๊ฐ์ ์ดํด</strong>: Cognitive Load, Sound Symbolism |
|
</div> |
|
<div> |
|
<strong style="color: #e74c3c;">๊ฐ์ ์ ์ฐ๊ฒฐ</strong>: Archetype, Color Psychology |
|
</div> |
|
<div> |
|
<strong style="color: #f39c12;">์ฐจ๋ณํ</strong>: Von Restorff, SCAMPER |
|
</div> |
|
<div> |
|
<strong style="color: #27ae60;">๋ฐ์ด๋ด ์ ์ฌ๋ ฅ</strong>: Memetics, Network Effects |
|
</div> |
|
<div> |
|
<strong style="color: #9b59b6;">๋ฌธ์ ํด๊ฒฐ</strong>: Jobs-to-be-Done, Design Thinking |
|
</div> |
|
<div> |
|
<strong style="color: #1abc9c;">ํ์ ์ฑ</strong>: Biomimicry, Conceptual Blending |
|
</div> |
|
<div> |
|
<strong style="color: #34495e;">๊ตฌ์กฐ์ ์์ฑ๋</strong>: Square Theory, Gestalt |
|
</div> |
|
</div> |
|
</div> |
|
""") |
|
|
|
if __name__ == "__main__": |
|
demo.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=False |
|
) |