openfree commited on
Commit
bc9d1cb
ยท
verified ยท
1 Parent(s): 3454e01

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +474 -825
app.py CHANGED
@@ -1,25 +1,8 @@
1
  """
2
- Ultimate Brand Theory Generator
3
- ===============================
4
- 2025-05-28 | 15๊ฐœ ์ด๋ก ์„ ํ†ตํ•ฉํ•œ ์ข…ํ•ฉ ๋ธŒ๋žœ๋“œ ์ƒ์„ฑ๊ธฐ
5
- -----------------------------------------------------
6
-
7
- ํ†ตํ•ฉ๋œ ์ด๋ก ๋“ค:
8
- 1. Square Theory - ์˜๋ฏธ์  ์‚ฌ๊ฐํ˜• ๊ตฌ์กฐ
9
- 2. Conceptual Blending - ๊ฐœ๋… ํ˜ผํ•ฉ
10
- 3. Sound Symbolism - ์Œํ–ฅ ์ƒ์ง•์ฃผ์˜
11
- 4. Linguistic Relativity - ์–ธ์–ด ์ƒ๋Œ€์„ฑ
12
- 5. Archetype Theory - ์›ํ˜• ์ด๋ก 
13
- 6. Jobs-to-be-Done - ํ•  ์ผ ์ด๋ก 
14
- 7. SCAMPER Method - ์ฐฝ์˜์  ๋ณ€ํ˜•
15
- 8. Design Thinking - ๋””์ž์ธ ์‚ฌ๊ณ 
16
- 9. Biomimicry - ์ƒ์ฒด๋ชจ๋ฐฉ
17
- 10. Cognitive Load - ์ธ์ง€ ๋ถ€ํ•˜
18
- 11. Von Restorff Effect - ๊ณ ๋ฆฝ ํšจ๊ณผ
19
- 12. Network Effects - ๋„คํŠธ์›Œํฌ ํšจ๊ณผ
20
- 13. Memetics - ๋ฐˆ ์ด๋ก 
21
- 14. Color Psychology - ์ƒ‰์ƒ ์‹ฌ๋ฆฌํ•™
22
- 15. Gestalt Principles - ๊ฒŒ์ŠˆํƒˆํŠธ ์›์น™
23
  """
24
 
25
  import os
@@ -56,314 +39,210 @@ THEORY_DESCRIPTIONS = {
56
  "gestalt": "์ง€๊ฐ ์›๋ฆฌ๋ฅผ ํ™œ์šฉํ•œ ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ „์ฒด๊ฐ€ ๋ถ€๋ถ„์˜ ํ•ฉ๋ณด๋‹ค ํฌ๋‹ค๋Š” ์›์น™์œผ๋กœ ํ†ตํ•ฉ์  ๋ธŒ๋žœ๋“œ ๊ฒฝํ—˜์„ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค."
57
  }
58
 
59
- # ===== 1. SQUARE THEORY =====
60
- SQUARE_THEORY_PROMPT = """
61
- ๋‹น์‹ ์€ Square Theory ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. Square Theory๋Š” 4๊ฐœ์˜ ๋‹จ์–ด๊ฐ€ ์˜๋ฏธ์  ๊ด€๊ณ„๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์‚ฌ๊ฐํ˜•์„ ์ด๋ฃจ๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
62
- ๋ธŒ๋žœ๋“œ๋ช…์ด Square๋ฅผ ์™„์„ฑํ•˜๋ฉฐ "์•„ํ•˜!" ๋ชจ๋จผํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
63
-
64
- ์‚ฌ์šฉ์ž ์ž…๋ ฅ(์—…์ข…/ํ‚ค์›Œ๋“œ)์„ ๋ฐ›์•„ ๋‹ค์Œ JSON ํ˜•์‹์˜ ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜์„ธ์š”:
65
- {
66
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
67
- "tl": "์™ผ์ชฝ์ƒ๋‹จ", "tr": "์˜ค๋ฅธ์ชฝ์ƒ๋‹จ", "bl": "์™ผ์ชฝํ•˜๋‹จ", "br": "์˜ค๋ฅธ์ชฝํ•˜๋‹จ",
68
- "top_edge": "์ƒ๋‹จ ๊ด€๊ณ„", "bottom_edge": "ํ•˜๋‹จ ๊ด€๊ณ„",
69
- "left_edge": "์™ผ์ชฝ ๊ด€๊ณ„", "right_edge": "์˜ค๋ฅธ์ชฝ ๊ด€๊ณ„",
70
- "slogan": "์Šฌ๋กœ๊ฑด",
71
- "explanation": "์™œ ํšจ๊ณผ์ ์ธ์ง€"
72
- }
73
-
74
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
75
- """
76
-
77
- # ===== 2. CONCEPTUAL BLENDING =====
78
- CONCEPTUAL_BLENDING_PROMPT = """
79
- ๋‹น์‹ ์€ Conceptual Blending Theory ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ๋‘ ๊ฐœ ์ด์ƒ์˜ ๊ฐœ๋…์„ ํ˜ผํ•ฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ์˜๋ฏธ๋ฅผ ์ฐฝ์ถœํ•ฉ๋‹ˆ๋‹ค.
80
-
81
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
82
- {
83
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
84
- "input_space1": "์ฒซ ๋ฒˆ์งธ ๊ฐœ๋…",
85
- "input_space2": "๋‘ ๋ฒˆ์งธ ๊ฐœ๋…",
86
- "generic_space": "๊ณตํ†ต ๊ตฌ์กฐ",
87
- "blended_space": "ํ˜ผํ•ฉ๋œ ์ƒˆ๋กœ์šด ์˜๋ฏธ",
88
- "emergent_properties": "์ฐฝ๋ฐœ์  ์†์„ฑ๋“ค",
89
- "slogan": "์Šฌ๋กœ๊ฑด",
90
- "explanation": "ํ˜ผํ•ฉ์ด ํšจ๊ณผ์ ์ธ ์ด์œ "
91
- }
92
-
93
- ์˜ˆ์‹œ: Netflix = Net(์ธํ„ฐ๋„ท) + Flix(์˜ํ™”) โ†’ ์˜จ๋ผ์ธ ์ŠคํŠธ๋ฆฌ๋ฐ์˜ ์ƒˆ๋กœ์šด ๊ฐœ๋…
94
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
95
- """
96
-
97
- # ===== 3. SOUND SYMBOLISM =====
98
- SOUND_SYMBOLISM_PROMPT = """
99
- ๋‹น์‹ ์€ Sound Symbolism ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์Œ์†Œ์™€ ์˜๋ฏธ ๊ฐ„์˜ ์—ฐ๊ด€์„ฑ์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.
100
-
101
- ์Œํ–ฅ ์›์น™:
102
- - ์ „์„ค๋ชจ์Œ(i,e): ์ž‘๊ณ , ๋น ๋ฅด๊ณ , ๊ฐ€๋ฒผ์›€
103
- - ํ›„์„ค๋ชจ์Œ(o,u): ํฌ๊ณ , ๋А๋ฆฌ๊ณ , ๋ฌด๊ฑฐ์›€
104
- - ์œ ์Œ(l,r,m,n): ๋ถ€๋“œ๋Ÿฝ๊ณ  ์œ ์—ฐํ•จ
105
- - ํŒŒ์—ด์Œ(p,t,k,b,d,g): ๊ฐ•ํ•˜๊ณ  ์—ญ๋™์ 
106
-
107
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
108
- {
109
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
110
- "phonetic_analysis": "์Œ์„ฑ ๋ถ„์„",
111
- "sound_meaning": "์Œํ–ฅ์ด ์ „๋‹ฌํ•˜๋Š” ์˜๋ฏธ",
112
- "target_emotion": "๋ชฉํ‘œ ๊ฐ์ •",
113
- "industry_fit": "์—…์ข… ์ ํ•ฉ์„ฑ",
114
- "pronunciation_guide": "๋ฐœ์Œ ๊ฐ€์ด๋“œ",
115
- "slogan": "์Šฌ๋กœ๊ฑด"
116
- }
117
-
118
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
119
- """
120
-
121
- # ===== 4. LINGUISTIC RELATIVITY =====
122
- LINGUISTIC_RELATIVITY_PROMPT = """
123
- ๋‹น์‹ ์€ Linguistic Relativity ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์–ธ์–ด๋ณ„ ์‚ฌ๊ณ ๋ฐฉ์‹ ์ฐจ์ด๋ฅผ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.
124
-
125
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋‹ค์–ธ์–ด ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
126
- {
127
- "brand_name": "๊ธ€๋กœ๋ฒŒ ๋ธŒ๋žœ๋“œ๋ช…",
128
- "korean_adaptation": "ํ•œ๊ตญ์–ด ์ ์‘",
129
- "english_meaning": "์˜์–ด ์˜๋ฏธ",
130
- "cultural_considerations": "๋ฌธํ™”์  ๊ณ ๋ ค์‚ฌํ•ญ",
131
- "avoid_meanings": "ํ”ผํ•ด์•ผ ํ•  ์˜๋ฏธ๋“ค",
132
- "localization_strategy": "ํ˜„์ง€ํ™” ์ „๋žต",
133
- "slogan": "์Šฌ๋กœ๊ฑด"
134
- }
135
-
136
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
137
- """
138
-
139
- # ===== 5. ARCHETYPE THEORY =====
140
- ARCHETYPE_THEORY_PROMPT = """
141
- ๋‹น์‹ ์€ Jung์˜ Archetype Theory ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. 12๊ฐ€์ง€ ์›ํ˜• ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
142
-
143
- 12 ์›ํ˜•: Innocent, Hero, Outlaw, Explorer, Creator, Ruler, Magician, Lover, Caregiver, Jester, Sage, Regular Guy
144
-
145
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
146
- {
147
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
148
- "archetype": "์„ ํƒ๋œ ์›ํ˜•",
149
- "archetype_traits": "์›ํ˜•์˜ ํŠน์ง•๋“ค",
150
- "brand_personality": "๋ธŒ๋žœ๋“œ ์„ฑ๊ฒฉ",
151
- "visual_direction": "์‹œ๊ฐ์  ๋ฐฉํ–ฅ",
152
- "voice_tone": "๋ชฉ์†Œ๋ฆฌ ํ†ค",
153
- "slogan": "์Šฌ๋กœ๊ฑด",
154
- "mythology_reference": "์‹ ํ™”์  ์ฐธ์กฐ"
155
- }
156
-
157
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
158
- """
159
-
160
- # ===== 6. JOBS-TO-BE-DONE =====
161
- JOBS_TO_BE_DONE_PROMPT = """
162
- ๋‹น์‹ ์€ Jobs-to-be-Done Theory ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ๊ณ ๊ฐ์ด ํ•ด๊ฒฐํ•˜๋ ค๋Š” '์ผ'์— ์ดˆ์ ์„ ๋งž์ถฅ๋‹ˆ๋‹ค.
163
-
164
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
165
- {
166
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
167
- "functional_job": "๊ธฐ๋Šฅ์  ์ผ",
168
- "emotional_job": "๊ฐ์ •์  ์ผ",
169
- "social_job": "์‚ฌํšŒ์  ์ผ",
170
- "job_statement": "ํ•ต์‹ฌ Job ๋ฌธ์žฅ",
171
- "outcome_metrics": "์„ฑ๊ณผ ์ง€ํ‘œ",
172
- "slogan": "์Šฌ๋กœ๊ฑด",
173
- "value_proposition": "๊ฐ€์น˜ ์ œ์•ˆ"
174
- }
175
-
176
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
177
- """
178
-
179
- # ===== 7. SCAMPER METHOD =====
180
- SCAMPER_PROMPT = """
181
- ๋‹น์‹ ์€ SCAMPER Method ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. 7๊ฐ€์ง€ ์ฐฝ์˜์  ๊ธฐ๋ฒ•์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
182
-
183
- S - Substitute (๋Œ€์ฒด)
184
- C - Combine (๊ฒฐํ•ฉ)
185
- A - Adapt (์ ์‘)
186
- M - Modify/Magnify (์ˆ˜์ •/ํ™•๋Œ€)
187
- P - Put to another use (๋‹ค๋ฅธ ์šฉ๋„)
188
- E - Eliminate (์ œ๊ฑฐ)
189
- R - Reverse (์—ญ์ „)
190
-
191
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
192
- {
193
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
194
- "scamper_technique": "์‚ฌ์šฉ๋œ ๊ธฐ๋ฒ•",
195
- "original_concept": "์›๋ž˜ ๊ฐœ๋…",
196
- "transformation": "๋ณ€ํ˜• ๊ณผ์ •",
197
- "innovative_aspect": "ํ˜์‹ ์  ์ธก๋ฉด",
198
- "slogan": "์Šฌ๋กœ๊ฑด"
199
- }
200
-
201
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
202
- """
203
-
204
- # ===== 8. DESIGN THINKING =====
205
- DESIGN_THINKING_PROMPT = """
206
- ๋‹น์‹ ์€ IDEO์˜ Design Thinking ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ธ๊ฐ„ ์ค‘์‹ฌ ํ˜์‹ ์„ ์ถ”๊ตฌํ•ฉ๋‹ˆ๋‹ค.
207
-
208
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
209
- {
210
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
211
- "user_insight": "์‚ฌ์šฉ์ž ํ†ต์ฐฐ",
212
- "pain_point": "ํ•ด๊ฒฐํ•˜๋Š” ๋ฌธ์ œ์ ",
213
- "desirability": "๋ฐ”๋žŒ์งํ•จ (์ธ๊ฐ„)",
214
- "feasibility": "์‹คํ˜„๊ฐ€๋Šฅ์„ฑ (๊ธฐ์ˆ )",
215
- "viability": "์ƒ์กด๊ฐ€๋Šฅ์„ฑ (๋น„์ฆˆ๋‹ˆ์Šค)",
216
- "prototype_concept": "ํ”„๋กœํ† ํƒ€์ž… ์ปจ์…‰",
217
- "slogan": "์Šฌ๋กœ๊ฑด"
218
- }
219
-
220
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
221
- """
222
-
223
- # ===== 9. BIOMIMICRY =====
224
- BIOMIMICRY_PROMPT = """
225
- ๋‹น์‹ ์€ Biomimicry ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ž์—ฐ์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
226
-
227
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
228
- {
229
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
230
- "natural_inspiration": "์ž์—ฐ์  ์˜๊ฐ์›",
231
- "biomimetic_principle": "์ƒ์ฒด๋ชจ๋ฐฉ ์›๋ฆฌ",
232
- "form_function": "ํ˜•ํƒœ์™€ ๊ธฐ๋Šฅ",
233
- "sustainability_aspect": "์ง€์†๊ฐ€๋Šฅ์„ฑ ์ธก๋ฉด",
234
- "adaptation_strategy": "์ ์‘ ์ „๋žต",
235
- "slogan": "์Šฌ๋กœ๊ฑด"
236
- }
237
-
238
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
239
- """
240
-
241
- # ===== 10. COGNITIVE LOAD =====
242
- COGNITIVE_LOAD_PROMPT = """
243
- ๋‹น์‹ ์€ Cognitive Load Theory ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ธ์ง€ ์ฒ˜๋ฆฌ๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
244
-
245
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
246
- {
247
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
248
- "syllable_count": "์Œ์ ˆ ์ˆ˜",
249
- "processing_ease": "์ฒ˜๋ฆฌ ์šฉ์ด์„ฑ ์ ์ˆ˜",
250
- "memory_hooks": "๊ธฐ์–ต ๊ณ ๋ฆฌ",
251
- "pronunciation_simplicity": "๋ฐœ์Œ ๋‹จ์ˆœ์„ฑ",
252
- "cognitive_fluency": "์ธ์ง€์  ์œ ์ฐฝ์„ฑ",
253
- "slogan": "์Šฌ๋กœ๊ฑด"
254
- }
255
-
256
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
257
- """
258
-
259
- # ===== 11. VON RESTORFF EFFECT =====
260
- VON_RESTORFF_PROMPT = """
261
- ๋‹น์‹ ์€ Von Restorff Effect ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ๋…ํŠนํ•˜๊ณ  ๊ธฐ์–ต์— ๋‚จ๋Š” ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
262
-
263
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
264
- {
265
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
266
- "category_norm": "์นดํ…Œ๊ณ ๋ฆฌ ํ‘œ์ค€",
267
- "deviation_strategy": "์ผํƒˆ ์ „๋žต",
268
- "uniqueness_factors": "๋…ํŠน์„ฑ ์š”์†Œ๋“ค",
269
- "memorability_score": "๊ธฐ์–ต์„ฑ ์ ์ˆ˜",
270
- "attention_triggers": "์ฃผ์˜ ํŠธ๋ฆฌ๊ฑฐ",
271
- "slogan": "์Šฌ๋กœ๊ฑด"
272
- }
273
-
274
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
275
  """
276
 
277
- # ===== 12. NETWORK EFFECTS =====
278
- NETWORK_EFFECTS_PROMPT = """
279
- ๋‹น์‹ ์€ Network Effects ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ๊ฐ€์น˜๋ฅผ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
280
-
281
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
282
- {
283
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
284
- "network_type": "๋„คํŠธ์›Œํฌ ์œ ํ˜•",
285
- "viral_coefficient": "๋ฐ”์ด๋Ÿด ๊ณ„์ˆ˜",
286
- "sharing_ease": "๊ณต์œ  ์šฉ์ด์„ฑ",
287
- "community_aspect": "์ปค๋ฎค๋‹ˆํ‹ฐ ์ธก๋ฉด",
288
- "network_value": "๋„คํŠธ์›Œํฌ ๊ฐ€์น˜",
289
- "slogan": "์Šฌ๋กœ๊ฑด"
290
- }
291
-
292
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
293
- """
294
-
295
- # ===== 13. MEMETICS =====
296
- MEMETICS_PROMPT = """
297
- ๋‹น์‹ ์€ Memetics ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ๋ฌธํ™”์ ์œผ๋กœ ๋ณต์ œ๋˜๊ณ  ์ง„ํ™”ํ•˜๋Š” ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
298
-
299
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
300
- {
301
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
302
- "meme_structure": "๋ฐˆ ๊ตฌ์กฐ",
303
- "replication_ease": "๋ณต์ œ ์šฉ์ด์„ฑ",
304
- "mutation_potential": "๋ณ€์ด ์ž ์žฌ๋ ฅ",
305
- "cultural_fitness": "๋ฌธํ™”์  ์ ํ•ฉ๋„",
306
- "transmission_channels": "์ „๋‹ฌ ์ฑ„๋„",
307
- "slogan": "์Šฌ๋กœ๊ฑด"
308
- }
309
-
310
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
311
- """
312
-
313
- # ===== 14. COLOR PSYCHOLOGY =====
314
- COLOR_PSYCHOLOGY_PROMPT = """
315
- ๋‹น์‹ ์€ Color Psychology ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ƒ‰์ƒ ์—ฐ์ƒ๊ณผ ๊ฐ์ •์„ ํ™œ์šฉํ•œ ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
316
-
317
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
318
- {
319
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
320
- "primary_color": "์ฃผ ์ƒ‰์ƒ",
321
- "color_meaning": "์ƒ‰์ƒ ์˜๋ฏธ",
322
- "emotional_response": "๊ฐ์ •์  ๋ฐ˜์‘",
323
- "cultural_associations": "๋ฌธํ™”์  ์—ฐ์ƒ",
324
- "industry_alignment": "์—…์ข… ์ •๋ ฌ",
325
- "slogan": "์Šฌ๋กœ๊ฑด"
326
- }
327
-
328
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
329
- """
330
-
331
- # ===== 15. GESTALT PRINCIPLES =====
332
- GESTALT_PROMPT = """
333
- ๋‹น์‹ ์€ Gestalt Theory ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ง€๊ฐ ์›๋ฆฌ๋ฅผ ํ™œ์šฉํ•œ ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
334
-
335
- ๋‹ค์Œ JSON ํ˜•์‹์œผ๋กœ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
336
- {
337
- "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
338
- "gestalt_principle": "ํ™œ์šฉ ์›์น™",
339
- "visual_structure": "์‹œ๊ฐ์  ๊ตฌ์กฐ",
340
- "perceptual_grouping": "์ง€๊ฐ์  ๊ทธ๋ฃนํ™”",
341
- "figure_ground": "์ „๊ฒฝ-๋ฐฐ๊ฒฝ ๊ด€๊ณ„",
342
- "closure_effect": "ํ์‡„ ํšจ๊ณผ",
343
- "slogan": "์Šฌ๋กœ๊ฑด"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  }
345
 
346
- ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
347
- """
348
-
349
- # ์ด๋ก ๋ณ„ ํ”„๋กฌํ”„ํŠธ ๋งคํ•‘
350
- THEORY_PROMPTS = {
351
- "square": SQUARE_THEORY_PROMPT,
352
- "blending": CONCEPTUAL_BLENDING_PROMPT,
353
- "sound": SOUND_SYMBOLISM_PROMPT,
354
- "linguistic": LINGUISTIC_RELATIVITY_PROMPT,
355
- "archetype": ARCHETYPE_THEORY_PROMPT,
356
- "jobs": JOBS_TO_BE_DONE_PROMPT,
357
- "scamper": SCAMPER_PROMPT,
358
- "design": DESIGN_THINKING_PROMPT,
359
- "biomimicry": BIOMIMICRY_PROMPT,
360
- "cognitive": COGNITIVE_LOAD_PROMPT,
361
- "vonrestorff": VON_RESTORFF_PROMPT,
362
- "network": NETWORK_EFFECTS_PROMPT,
363
- "memetics": MEMETICS_PROMPT,
364
- "color": COLOR_PSYCHOLOGY_PROMPT,
365
- "gestalt": GESTALT_PROMPT
366
- }
 
 
 
 
367
 
368
  def generate_by_theory(industry: str, keywords: str, theory: str, count: int = 3) -> Tuple[str, str]:
369
  """ํŠน์ • ์ด๋ก ์œผ๋กœ ๋ธŒ๋žœ๋“œ ์ƒ์„ฑ"""
@@ -371,17 +250,16 @@ def generate_by_theory(industry: str, keywords: str, theory: str, count: int = 3
371
  if not industry or not keywords:
372
  return "โš ๏ธ ์—…์ข…๊ณผ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.", ""
373
 
374
- prompt = THEORY_PROMPTS.get(theory, SQUARE_THEORY_PROMPT)
375
  user_input = f"""์—…์ข…: {industry}
376
  ํ‚ค์›Œ๋“œ: {keywords}
377
 
378
  ์œ„ ์ •๋ณด๋กœ {count}๊ฐœ์˜ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”.
379
- ๋ฐ˜๋“œ์‹œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
380
- ๊ฒฐ๊ณผ๋Š” ๋ธŒ๋žœ๋“œ ๊ฐ์ฒด๋“ค์˜ JSON ๋ฐฐ์—ด์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."""
381
 
382
  try:
383
  response = client.chat.completions.create(
384
- model="gpt-4o-mini", # ๊ฒฝ์ œ์ ์ธ ๋ชจ๋ธ
385
  messages=[
386
  {"role": "system", "content": prompt},
387
  {"role": "user", "content": user_input}
@@ -395,45 +273,29 @@ def generate_by_theory(industry: str, keywords: str, theory: str, count: int = 3
395
  data = json.loads(content)
396
 
397
  # ์‘๋‹ต ์ •๊ทœํ™”
398
- if isinstance(data, dict):
399
- if "results" in data:
400
- results = data["results"]
401
- elif "brands" in data:
402
- results = data["brands"]
403
- elif "brand_name" in data:
404
- # ๋‹จ์ผ ๋ธŒ๋žœ๋“œ๋ฅผ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜
405
- results = [data]
406
- else:
407
- # ๋ž˜ํ•‘๋œ ์‘๋‹ต ์ฒ˜๋ฆฌ
408
- results = []
409
- for key, value in data.items():
410
- if isinstance(value, list):
411
- results = value
412
- break
413
- elif isinstance(value, dict) and "brand_name" in value:
414
- results = [value]
415
- break
416
  else:
417
- results = data
418
 
419
  if not isinstance(results, list):
420
  results = [results]
421
 
422
  # ๋งˆํฌ๋‹ค์šด ์ƒ์„ฑ
423
- markdown = generate_theory_markdown(theory, results, industry, keywords)
424
 
425
  # HTML ์‹œ๊ฐํ™” ์ƒ์„ฑ
426
- html = generate_theory_visualization(theory, results)
427
 
428
  return markdown, html
429
 
430
  except Exception as e:
431
  error_msg = f"โŒ {theory} ์ด๋ก  ์˜ค๋ฅ˜: {str(e)}"
432
- print(error_msg) # ๋””๋ฒ„๊น…์šฉ
433
  return error_msg, ""
434
 
435
- def generate_theory_markdown(theory: str, results: List[Dict], industry: str, keywords: str) -> str:
436
- """์ด๋ก ๋ณ„ ๋งž์ถค ๋งˆํฌ๋‹ค์šด ์ƒ์„ฑ"""
437
 
438
  theory_names = {
439
  "square": "Square Theory",
@@ -454,21 +316,10 @@ def generate_theory_markdown(theory: str, results: List[Dict], industry: str, ke
454
  }
455
 
456
  theory_icons = {
457
- "square": "๐ŸŸฆ",
458
- "blending": "๐Ÿ”€",
459
- "sound": "๐Ÿ”Š",
460
- "linguistic": "๐ŸŒ",
461
- "archetype": "๐ŸŽญ",
462
- "jobs": "โœ…",
463
- "scamper": "๐Ÿ”ง",
464
- "design": "๐Ÿ’ญ",
465
- "biomimicry": "๐ŸŒฟ",
466
- "cognitive": "๐Ÿง ",
467
- "vonrestorff": "โšก",
468
- "network": "๐ŸŒ",
469
- "memetics": "๐Ÿงฌ",
470
- "color": "๐ŸŽจ",
471
- "gestalt": "๐Ÿ‘๏ธ"
472
  }
473
 
474
  markdown = f"""# {theory_icons[theory]} {theory_names[theory]}
@@ -485,296 +336,271 @@ def generate_theory_markdown(theory: str, results: List[Dict], industry: str, ke
485
  """
486
 
487
  for idx, result in enumerate(results, 1):
488
- brand_name = result.get('brand_name', 'N/A')
489
- slogan = result.get('slogan', 'N/A')
 
 
 
 
 
 
 
490
 
491
  markdown += f"\n## {idx}. {brand_name}\n"
492
  markdown += f"**์Šฌ๋กœ๊ฑด**: *\"{slogan}\"*\n\n"
493
 
494
- # ์ด๋ก ๋ณ„ ํŠน์ˆ˜ ํ•„๋“œ ํ‘œ์‹œ
495
- if theory == "square":
496
- markdown += f"""
497
- ### Square ๊ตฌ์กฐ
498
- ```
499
- [{result.get('tl')}] โ”€({result.get('top_edge')})โ”€ [{result.get('tr')}]
500
- โ”‚ โ”‚
501
- ({result.get('left_edge')}) ({result.get('right_edge')})
502
- โ”‚ โ”‚
503
- [{result.get('bl')}] โ”€({result.get('bottom_edge')})โ”€ [{result.get('br')}]
504
- ```
505
- """
506
- elif theory == "blending":
507
- markdown += f"""
508
- ### ๊ฐœ๋… ํ˜ผํ•ฉ
509
- - **์ž…๋ ฅ ๊ณต๊ฐ„ 1**: {result.get('input_space1')}
510
- - **์ž…๋ ฅ ๊ณต๊ฐ„ 2**: {result.get('input_space2')}
511
- - **์ผ๋ฐ˜ ๊ณต๊ฐ„**: {result.get('generic_space')}
512
- - **ํ˜ผํ•ฉ ๊ณต๊ฐ„**: {result.get('blended_space')}
513
- - **์ฐฝ๋ฐœ์  ์†์„ฑ**: {result.get('emergent_properties')}
514
- """
515
- elif theory == "sound":
516
- markdown += f"""
517
- ### ์Œํ–ฅ ๋ถ„์„
518
- - **์Œ์„ฑ ๋ถ„์„**: {result.get('phonetic_analysis')}
519
- - **์Œํ–ฅ ์˜๋ฏธ**: {result.get('sound_meaning')}
520
- - **๋ชฉํ‘œ ๊ฐ์ •**: {result.get('target_emotion')}
521
- - **๋ฐœ์Œ ๊ฐ€์ด๋“œ**: {result.get('pronunciation_guide')}
522
- """
523
- elif theory == "archetype":
524
- markdown += f"""
525
- ### ์›ํ˜• ๋ถ„์„
526
- - **์›ํ˜•**: {result.get('archetype')}
527
- - **์›ํ˜• ํŠน์ง•**: {result.get('archetype_traits')}
528
- - **๋ธŒ๋žœ๋“œ ์„ฑ๊ฒฉ**: {result.get('brand_personality')}
529
- - **๋ชฉ์†Œ๋ฆฌ ํ†ค**: {result.get('voice_tone')}
530
  """
531
 
532
- # ์„ค๋ช… ์ถ”๊ฐ€
533
- explanation = result.get('explanation', result.get('value_proposition', ''))
534
- if explanation:
535
- markdown += f"\n๐Ÿ’ก **ํ•ต์‹ฌ ๊ฐ€์น˜**: {explanation}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
536
 
537
  markdown += "\n---\n"
538
 
539
  return markdown
540
 
541
- def generate_theory_visualization(theory: str, results: List[Dict]) -> str:
542
- """์ด๋ก ๋ณ„ ๋งž์ถค ์‹œ๊ฐํ™” ์ƒ์„ฑ"""
543
 
544
  html_parts = []
545
 
546
  for idx, result in enumerate(results, 1):
547
- if theory == "square":
548
- html_parts.append(visualize_square_brand(result))
549
- elif theory == "blending":
550
- html_parts.append(visualize_conceptual_blend(result))
551
- elif theory == "sound":
552
- html_parts.append(visualize_sound_symbolism(result))
553
- elif theory == "archetype":
554
- html_parts.append(visualize_archetype(result))
555
- elif theory == "color":
556
- html_parts.append(visualize_color_psychology(result))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
  else:
558
- html_parts.append(visualize_generic_brand(result, theory))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
 
560
  return "\n".join(html_parts)
561
 
562
- # ์‹œ๊ฐํ™” ํ•จ์ˆ˜๋“ค (์ผ๋ถ€๋งŒ ์˜ˆ์‹œ)
563
- def visualize_square_brand(brand: Dict) -> str:
564
- """Square Theory ์‹œ๊ฐํ™”"""
565
  return f"""
566
- <div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;">
567
- <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);">
568
- <h2 style="text-align: center; color: white; margin-bottom: 10px;">{brand.get('brand_name', 'Brand')}</h2>
569
- <p style="text-align: center; font-style: italic; color: rgba(255,255,255,0.9);">"{brand.get('slogan', '')}"</p>
570
-
571
- <div style="position: relative; width: 100%; height: 300px; background: rgba(255,255,255,0.1); border-radius: 12px; padding: 30px; margin-top: 20px;">
572
- <!-- Square ๊ตฌ์กฐ ์‹œ๊ฐํ™” -->
573
- <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);">
574
- {brand.get('tl', '?')}
575
  </div>
576
- <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);">
577
- {brand.get('tr', '?')}
578
  </div>
579
- <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);">
580
- {brand.get('bl', '?')}
581
  </div>
582
- <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);">
583
- {brand.get('br', '?')}
584
  </div>
585
 
586
- <!-- ๋ธŒ๋žœ๋“œ๋ช… ์ค‘์•™ -->
587
- <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);">
588
- <div style="font-size: 1.8em; font-weight: bold; color: #2c3e50; text-align: center;">{brand.get('brand_name', 'Brand')}</div>
 
 
 
 
 
 
 
 
 
589
  </div>
590
  </div>
591
  </div>
592
- </div>
593
  """
594
 
595
- def visualize_conceptual_blend(brand: Dict) -> str:
596
- """Conceptual Blending ์‹œ๊ฐํ™”"""
597
- brand_name = brand.get('brand_name', 'Brand')
598
- input1 = brand.get('input_space1', 'Concept 1')
599
- input2 = brand.get('input_space2', 'Concept 2')
600
- blended = brand.get('blended_space', 'Blended Concept')
601
- slogan = brand.get('slogan', '')
602
-
603
  return f"""
604
- <div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;">
605
- <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);">
606
- <h2 style="text-align: center; color: white; margin-bottom: 20px;">{brand_name}</h2>
607
-
608
- <div style="display: flex; justify-content: space-around; align-items: center; margin: 30px 0;">
609
- <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);">
610
  <div>
611
  <strong>Input 1</strong><br>
612
- <span style="font-size: 0.9em;">{input1}</span>
613
  </div>
614
  </div>
615
 
616
- <div style="font-size: 3em; color: white;">+</div>
617
 
618
- <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);">
619
  <div>
620
  <strong>Input 2</strong><br>
621
- <span style="font-size: 0.9em;">{input2}</span>
622
  </div>
623
  </div>
624
 
625
- <div style="font-size: 3em; color: white;">=</div>
626
-
627
- <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);">
628
- <div>
629
- <strong style="font-size: 1.2em;">Blend</strong><br>
630
- <span style="font-size: 0.95em;">{blended}</span>
631
- </div>
632
- </div>
633
- </div>
634
-
635
- <p style="text-align: center; font-style: italic; color: white; font-size: 1.1em; margin-top: 20px;">"{slogan}"</p>
636
- </div>
637
- </div>
638
- """
639
-
640
- def visualize_sound_symbolism(brand: Dict) -> str:
641
- """Sound Symbolism ์‹œ๊ฐํ™”"""
642
- return f"""
643
- <div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;">
644
- <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);">
645
- <h2 style="text-align: center; color: white; margin-bottom: 20px;">{brand.get('brand_name', 'Brand')}</h2>
646
-
647
- <div style="text-align: center; margin: 30px 0;">
648
- <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;">
649
- {brand.get('brand_name', 'BRAND')}
650
- </div>
651
- </div>
652
-
653
- <div style="background: rgba(255,255,255,0.9); padding: 25px; border-radius: 15px; margin: 20px 0;">
654
- <div style="text-align: center; margin-bottom: 15px;">
655
- <strong style="color: #fa709a; font-size: 1.2em;">์Œ์„ฑ ๋ถ„์„</strong><br>
656
- <span style="color: #555;">{brand.get('phonetic_analysis', '')}</span>
657
- </div>
658
 
659
- <div style="text-align: center;">
660
- <strong style="color: #fee140; font-size: 1.2em;">์Œํ–ฅ์ด ์ „๋‹ฌํ•˜๋Š” ๊ฐ์ •</strong><br>
661
- <span style="color: #555;">{brand.get('sound_meaning', '')}</span>
662
  </div>
663
  </div>
664
-
665
- <div style="text-align: center; color: white; font-style: italic;">
666
- ๋ฐœ์Œ: {brand.get('pronunciation_guide', '')}
667
- </div>
668
  </div>
669
- </div>
670
  """
671
 
672
- def visualize_archetype(brand: Dict) -> str:
673
- """Archetype Theory ์‹œ๊ฐํ™”"""
674
- archetype_colors = {
675
- "Hero": "#e74c3c",
676
- "Creator": "#9b59b6",
677
- "Sage": "#3498db",
678
- "Explorer": "#1abc9c",
679
- "Innocent": "#f1c40f",
680
- "Jester": "#e67e22",
681
- "Lover": "#e91e63",
682
- "Caregiver": "#00bcd4",
683
- "Ruler": "#795548",
684
- "Magician": "#673ab7",
685
- "Outlaw": "#212121",
686
- "Regular Guy": "#607d8b"
687
- }
688
 
689
- archetype = brand.get('archetype', 'Hero')
690
- color = archetype_colors.get(archetype, "#3498db")
691
-
692
- return f"""
693
- <div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;">
694
- <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);">
695
- <h2 style="text-align: center; color: white; margin-bottom: 30px;">{brand.get('brand_name', 'Brand')}</h2>
696
-
697
- <div style="text-align: center; margin: 30px 0;">
698
- <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);">
699
- <h3 style="margin: 0 0 15px 0; font-size: 2em;">{archetype}</h3>
700
- <p style="margin: 0; font-size: 1em; line-height: 1.5;">{brand.get('archetype_traits', '')}</p>
701
- </div>
702
- </div>
703
-
704
- <div style="background: rgba(255,255,255,0.9); padding: 25px; border-radius: 15px; margin: 20px 0;">
705
- <p style="margin: 10px 0;"><strong style="color: {color};">๋ธŒ๋žœ๋“œ ์„ฑ๊ฒฉ</strong>: {brand.get('brand_personality', '')}</p>
706
- <p style="margin: 10px 0;"><strong style="color: {color};">๋ชฉ์†Œ๋ฆฌ ํ†ค</strong>: {brand.get('voice_tone', '')}</p>
707
- </div>
708
-
709
- <p style="text-align: center; font-style: italic; font-size: 1.3em; color: white; margin-top: 30px;">"{brand.get('slogan', '')}"</p>
710
- </div>
711
- </div>
712
  """
713
-
714
- def visualize_color_psychology(brand: Dict) -> str:
715
- """Color Psychology ์‹œ๊ฐํ™”"""
716
- color = brand.get('primary_color', '#3498db')
717
 
718
- return f"""
719
- <div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;">
720
- <div style="background: #f8f9fa; padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1);">
721
- <h2 style="text-align: center; color: #2c3e50; margin-bottom: 30px;">{brand.get('brand_name', 'Brand')}</h2>
722
-
723
- <div style="text-align: center; margin: 30px 0;">
724
- <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;">
725
- <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);">
726
- {brand.get('primary_color', '')}
727
- </div>
728
- </div>
729
- </div>
730
-
731
- <div style="background: white; padding: 25px; border-radius: 15px; box-shadow: 0 5px 15px rgba(0,0,0,0.1);">
732
- <p style="margin: 10px 0;"><strong style="color: {color};">์ƒ‰์ƒ ์˜๋ฏธ</strong>: {brand.get('color_meaning', '')}</p>
733
- <p style="margin: 10px 0;"><strong style="color: {color};">๊ฐ์ •์  ๋ฐ˜์‘</strong>: {brand.get('emotional_response', '')}</p>
734
- <p style="margin: 10px 0;"><strong style="color: {color};">๋ฌธํ™”์  ์—ฐ์ƒ</strong>: {brand.get('cultural_associations', '')}</p>
735
- </div>
736
-
737
- <p style="text-align: center; font-style: italic; margin-top: 30px; color: #7f8c8d; font-size: 1.2em;">"{brand.get('slogan', '')}"</p>
738
- </div>
739
- </div>
740
  """
741
-
742
- def visualize_generic_brand(brand: Dict, theory: str) -> str:
743
- """์ผ๋ฐ˜์ ์ธ ๋ธŒ๋žœ๋“œ ์‹œ๊ฐํ™”"""
744
- # JSON์„ HTML๋กœ ๋ณ€ํ™˜ (f-string ๋ฐ–์—์„œ ์ฒ˜๋ฆฌ)
745
- json_str = json.dumps(brand, ensure_ascii=False, indent=2)
746
-
747
- theory_gradients = {
748
- "jobs": "linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)",
749
- "scamper": "linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)",
750
- "design": "linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%)",
751
- "biomimicry": "linear-gradient(135deg, #d4fc79 0%, #96e6a1 100%)",
752
- "cognitive": "linear-gradient(135deg, #fa709a 0%, #fee140 100%)",
753
- "vonrestorff": "linear-gradient(135deg, #f093fb 0%, #f5576c 100%)",
754
- "network": "linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)",
755
- "memetics": "linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)",
756
- "gestalt": "linear-gradient(135deg, #fd6585 0%, #0d25b9 100%)"
757
- }
758
-
759
- gradient = theory_gradients.get(theory, "linear-gradient(135deg, #667eea 0%, #764ba2 100%)")
760
 
761
- html = f"""
762
- <div style="max-width: 700px; margin: 20px auto; font-family: -apple-system, sans-serif;">
763
- <div style="background: {gradient}; padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);">
764
- <h2 style="text-align: center; color: white; margin-bottom: 10px;">{brand.get('brand_name', 'Brand')}</h2>
765
- <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>
766
-
767
- <div style="background: rgba(255,255,255,0.95); padding: 25px; border-radius: 15px; font-family: 'Courier New', monospace; font-size: 0.9em;">
768
- <pre style="margin: 0; white-space: pre-wrap; color: #2c3e50;">{json_str}</pre>
769
  </div>
770
  </div>
771
- </div>
772
  """
773
  return html
774
 
775
  # Gradio UI
776
  with gr.Blocks(
777
- title="Ultimate Brand Theory Generator",
778
  theme=gr.themes.Soft(),
779
  css="""
780
  .gradio-container {
@@ -791,7 +617,7 @@ with gr.Blocks(
791
  <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;">
792
  ๐ŸŒŸ Ultimate Brand Theory Generator
793
  </h1>
794
- <p style="font-size: 1.2em; color: #7f8c8d;">15๊ฐœ ์ด๋ก ์„ ํ™œ์šฉํ•œ ์ข…ํ•ฉ ๋ธŒ๋žœ๋“œ ์ƒ์„ฑ๊ธฐ</p>
795
  </div>
796
  """)
797
 
@@ -818,247 +644,70 @@ with gr.Blocks(
818
 
819
  gr.Markdown("""
820
  <div style="background: #e3f2fd; padding: 15px; border-radius: 8px; margin-top: 20px;">
821
- <h4 style="margin-top: 0; color: #1976d2;">๐Ÿ’ก ์‚ฌ์šฉ ๋ฐฉ๋ฒ•</h4>
822
- <ol style="margin: 10px 0; padding-left: 20px;">
823
- <li>์—…์ข…๊ณผ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”</li>
824
- <li>์›ํ•˜๋Š” ์ด๋ก  ํƒญ์„ ์„ ํƒํ•˜์„ธ์š”</li>
825
- <li>๊ฐ ํƒญ์˜ ์ƒ์„ฑ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”</li>
826
- </ol>
827
- <p style="margin: 0; font-size: 0.9em; color: #555;">
828
- ๊ฐ ์ด๋ก ์€ ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ ์›ํ•˜๋Š” ๊ฒƒ๋งŒ ์„ ํƒํ•ด์„œ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
829
- </p>
 
830
  </div>
831
  """)
832
 
833
  with gr.Column(scale=3):
834
  # 15๊ฐœ ํƒญ ์ƒ์„ฑ
835
  with gr.Tabs():
836
- # 1. Square Theory
837
- with gr.Tab("๐ŸŸฆ Square Theory"):
838
- with gr.Row():
839
- square_btn = gr.Button("Square Theory๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
840
- square_output = gr.Markdown()
841
- square_visual = gr.HTML()
842
- square_btn.click(
843
- lambda i, k: generate_by_theory(i, k, "square"),
844
- inputs=[industry_input, keywords_input],
845
- outputs=[square_output, square_visual]
846
- )
847
-
848
- # 2. Conceptual Blending
849
- with gr.Tab("๐Ÿ”€ Conceptual Blending"):
850
- with gr.Row():
851
- blending_btn = gr.Button("Conceptual Blending์œผ๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
852
- blending_output = gr.Markdown()
853
- blending_visual = gr.HTML()
854
- blending_btn.click(
855
- lambda i, k: generate_by_theory(i, k, "blending"),
856
- inputs=[industry_input, keywords_input],
857
- outputs=[blending_output, blending_visual]
858
- )
859
-
860
- # 3. Sound Symbolism
861
- with gr.Tab("๐Ÿ”Š Sound Symbolism"):
862
- with gr.Row():
863
- sound_btn = gr.Button("Sound Symbolism์œผ๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
864
- sound_output = gr.Markdown()
865
- sound_visual = gr.HTML()
866
- sound_btn.click(
867
- lambda i, k: generate_by_theory(i, k, "sound"),
868
- inputs=[industry_input, keywords_input],
869
- outputs=[sound_output, sound_visual]
870
- )
871
-
872
- # 4. Linguistic Relativity
873
- with gr.Tab("๐ŸŒ Linguistic Relativity"):
874
- with gr.Row():
875
- linguistic_btn = gr.Button("Linguistic Relativity๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
876
- linguistic_output = gr.Markdown()
877
- linguistic_visual = gr.HTML()
878
- linguistic_btn.click(
879
- lambda i, k: generate_by_theory(i, k, "linguistic"),
880
- inputs=[industry_input, keywords_input],
881
- outputs=[linguistic_output, linguistic_visual]
882
- )
883
-
884
- # 5. Archetype Theory
885
- with gr.Tab("๐ŸŽญ Archetype Theory"):
886
- with gr.Row():
887
- archetype_btn = gr.Button("Archetype Theory๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
888
- archetype_output = gr.Markdown()
889
- archetype_visual = gr.HTML()
890
- archetype_btn.click(
891
- lambda i, k: generate_by_theory(i, k, "archetype"),
892
- inputs=[industry_input, keywords_input],
893
- outputs=[archetype_output, archetype_visual]
894
- )
895
 
896
- # 6. Jobs-to-be-Done
897
- with gr.Tab("โœ… Jobs-to-be-Done"):
898
- with gr.Row():
899
- jobs_btn = gr.Button("Jobs-to-be-Done์œผ๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
900
- jobs_output = gr.Markdown()
901
- jobs_visual = gr.HTML()
902
- jobs_btn.click(
903
- lambda i, k: generate_by_theory(i, k, "jobs"),
904
- inputs=[industry_input, keywords_input],
905
- outputs=[jobs_output, jobs_visual]
906
- )
907
-
908
- # 7. SCAMPER
909
- with gr.Tab("๐Ÿ”ง SCAMPER Method"):
910
- with gr.Row():
911
- scamper_btn = gr.Button("SCAMPER Method๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
912
- scamper_output = gr.Markdown()
913
- scamper_visual = gr.HTML()
914
- scamper_btn.click(
915
- lambda i, k: generate_by_theory(i, k, "scamper"),
916
- inputs=[industry_input, keywords_input],
917
- outputs=[scamper_output, scamper_visual]
918
- )
919
-
920
- # 8. Design Thinking
921
- with gr.Tab("๐Ÿ’ญ Design Thinking"):
922
- with gr.Row():
923
- design_btn = gr.Button("Design Thinking์œผ๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
924
- design_output = gr.Markdown()
925
- design_visual = gr.HTML()
926
- design_btn.click(
927
- lambda i, k: generate_by_theory(i, k, "design"),
928
- inputs=[industry_input, keywords_input],
929
- outputs=[design_output, design_visual]
930
- )
931
-
932
- # 9. Biomimicry
933
- with gr.Tab("๐ŸŒฟ Biomimicry"):
934
- with gr.Row():
935
- biomimicry_btn = gr.Button("Biomimicry๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
936
- biomimicry_output = gr.Markdown()
937
- biomimicry_visual = gr.HTML()
938
- biomimicry_btn.click(
939
- lambda i, k: generate_by_theory(i, k, "biomimicry"),
940
- inputs=[industry_input, keywords_input],
941
- outputs=[biomimicry_output, biomimicry_visual]
942
- )
943
-
944
- # 10. Cognitive Load
945
- with gr.Tab("๐Ÿง  Cognitive Load"):
946
- with gr.Row():
947
- cognitive_btn = gr.Button("Cognitive Load๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
948
- cognitive_output = gr.Markdown()
949
- cognitive_visual = gr.HTML()
950
- cognitive_btn.click(
951
- lambda i, k: generate_by_theory(i, k, "cognitive"),
952
- inputs=[industry_input, keywords_input],
953
- outputs=[cognitive_output, cognitive_visual]
954
- )
955
-
956
- # 11. Von Restorff
957
- with gr.Tab("โšก Von Restorff Effect"):
958
- with gr.Row():
959
- vonrestorff_btn = gr.Button("Von Restorff Effect๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
960
- vonrestorff_output = gr.Markdown()
961
- vonrestorff_visual = gr.HTML()
962
- vonrestorff_btn.click(
963
- lambda i, k: generate_by_theory(i, k, "vonrestorff"),
964
- inputs=[industry_input, keywords_input],
965
- outputs=[vonrestorff_output, vonrestorff_visual]
966
- )
967
-
968
- # 12. Network Effects
969
- with gr.Tab("๐ŸŒ Network Effects"):
970
- with gr.Row():
971
- network_btn = gr.Button("Network Effects๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
972
- network_output = gr.Markdown()
973
- network_visual = gr.HTML()
974
- network_btn.click(
975
- lambda i, k: generate_by_theory(i, k, "network"),
976
- inputs=[industry_input, keywords_input],
977
- outputs=[network_output, network_visual]
978
- )
979
-
980
- # 13. Memetics
981
- with gr.Tab("๐Ÿงฌ Memetics"):
982
- with gr.Row():
983
- memetics_btn = gr.Button("Memetics๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
984
- memetics_output = gr.Markdown()
985
- memetics_visual = gr.HTML()
986
- memetics_btn.click(
987
- lambda i, k: generate_by_theory(i, k, "memetics"),
988
- inputs=[industry_input, keywords_input],
989
- outputs=[memetics_output, memetics_visual]
990
- )
991
-
992
- # 14. Color Psychology
993
- with gr.Tab("๐ŸŽจ Color Psychology"):
994
- with gr.Row():
995
- color_btn = gr.Button("Color Psychology๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
996
- color_output = gr.Markdown()
997
- color_visual = gr.HTML()
998
- color_btn.click(
999
- lambda i, k: generate_by_theory(i, k, "color"),
1000
- inputs=[industry_input, keywords_input],
1001
- outputs=[color_output, color_visual]
1002
- )
1003
-
1004
- # 15. Gestalt Principles
1005
- with gr.Tab("๐Ÿ‘๏ธ Gestalt Principles"):
1006
- with gr.Row():
1007
- gestalt_btn = gr.Button("Gestalt Principles๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
1008
- gestalt_output = gr.Markdown()
1009
- gestalt_visual = gr.HTML()
1010
- gestalt_btn.click(
1011
- lambda i, k: generate_by_theory(i, k, "gestalt"),
1012
- inputs=[industry_input, keywords_input],
1013
- outputs=[gestalt_output, gestalt_visual]
1014
- )
1015
 
1016
  gr.Markdown("""
1017
  <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; margin-top: 40px;">
1018
- <h3 style="margin-top: 0;">๐ŸŽฏ ํ™œ์šฉ ๊ฐ€์ด๋“œ</h3>
1019
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-top: 20px;">
1020
- <div>
1021
- <h4>1. ๋น„๊ต ๋ถ„์„</h4>
1022
- <p style="margin: 5px 0;">๊ฐ ์ด๋ก ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋ธŒ๋žœ๋“œ ์„ ํƒ</p>
1023
- </div>
1024
- <div>
1025
- <h4>2. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ</h4>
1026
- <p style="margin: 5px 0;">์—ฌ๋Ÿฌ ์ด๋ก ์˜ ์žฅ์ ์„ ๊ฒฐํ•ฉํ•œ ์ƒˆ๋กœ์šด ๋ธŒ๋žœ๋“œ ์ฐฝ์กฐ</p>
1027
- </div>
1028
- <div>
1029
- <h4>3. ํƒ€๊ฒŸ๋ณ„ ์„ ํƒ</h4>
1030
- <p style="margin: 5px 0;">๋ชฉํ‘œ ๊ณ ๊ฐ์ธต์— ๋”ฐ๋ผ ๊ฐ€์žฅ ํšจ๊ณผ์ ์ธ ์ด๋ก  ์„ ํƒ</p>
1031
- </div>
1032
- <div>
1033
- <h4>4. A/B ํ…Œ์ŠคํŠธ</h4>
1034
- <p style="margin: 5px 0;">๋‹ค์–‘ํ•œ ์ด๋ก  ๊ธฐ๋ฐ˜ ๋ธŒ๋žœ๋“œ๋กœ ์‹œ์žฅ ํ…Œ์ŠคํŠธ</p>
1035
- </div>
1036
- </div>
1037
- </div>
1038
-
1039
- <div style="margin-top: 30px; padding: 20px; background: #f8f9fa; border-radius: 10px;">
1040
- <h3 style="margin-top: 0;">๐Ÿ“š ๊ฐ ์ด๋ก ์˜ ๊ฐ•์ </h3>
1041
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 15px;">
1042
- <div>
1043
- <strong style="color: #3498db;">์ฆ‰๊ฐ์  ์ดํ•ด</strong>: Cognitive Load, Sound Symbolism
1044
- </div>
1045
- <div>
1046
- <strong style="color: #e74c3c;">๊ฐ์ •์  ์—ฐ๊ฒฐ</strong>: Archetype, Color Psychology
1047
- </div>
1048
- <div>
1049
- <strong style="color: #f39c12;">์ฐจ๋ณ„ํ™”</strong>: Von Restorff, SCAMPER
1050
- </div>
1051
- <div>
1052
- <strong style="color: #27ae60;">๋ฐ”์ด๋Ÿด ์ž ์žฌ๋ ฅ</strong>: Memetics, Network Effects
1053
- </div>
1054
  <div>
1055
- <strong style="color: #9b59b6;">๋ฌธ์ œ ํ•ด๊ฒฐ</strong>: Jobs-to-be-Done, Design Thinking
 
1056
  </div>
1057
  <div>
1058
- <strong style="color: #1abc9c;">ํ˜์‹ ์„ฑ</strong>: Biomimicry, Conceptual Blending
 
1059
  </div>
1060
  <div>
1061
- <strong style="color: #34495e;">๊ตฌ์กฐ์  ์™„์„ฑ๋„</strong>: Square Theory, Gestalt
 
1062
  </div>
1063
  </div>
1064
  </div>
 
1
  """
2
+ Ultimate Brand Theory Generator - Unified Output Version
3
+ ========================================================
4
+ 2025-05-28 | 15๊ฐœ ์ด๋ก ์„ ํ†ตํ•ฉํ•œ ์ข…ํ•ฉ ๋ธŒ๋žœ๋“œ ์ƒ์„ฑ๊ธฐ (ํ†ต์ผ๋œ ์ถœ๋ ฅ ๊ตฌ์กฐ)
5
+ ------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  """
7
 
8
  import os
 
39
  "gestalt": "์ง€๊ฐ ์›๋ฆฌ๋ฅผ ํ™œ์šฉํ•œ ๋ธŒ๋žœ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ „์ฒด๊ฐ€ ๋ถ€๋ถ„์˜ ํ•ฉ๋ณด๋‹ค ํฌ๋‹ค๋Š” ์›์น™์œผ๋กœ ํ†ตํ•ฉ์  ๋ธŒ๋žœ๋“œ ๊ฒฝํ—˜์„ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค."
40
  }
41
 
42
+ # ํ†ต์ผ๋œ ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ
43
+ UNIFIED_BASE_PROMPT = """
44
+ ๋‹น์‹ ์€ {theory_name} ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค. {theory_description}
45
+
46
+ ์‚ฌ์šฉ์ž ์ž…๋ ฅ(์—…์ข…/ํ‚ค์›Œ๋“œ)์„ ๋ฐ›์•„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ†ต์ผ๋œ JSON ํ˜•์‹์˜ ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜์„ธ์š”:
47
+
48
+ {{
49
+ "brands": [
50
+ {{
51
+ "core": {{
52
+ "brand_name": "๋ธŒ๋žœ๋“œ๋ช…",
53
+ "slogan": "์Šฌ๋กœ๊ฑด",
54
+ "core_value": "ํ•ต์‹ฌ ๊ฐ€์น˜",
55
+ "target_emotion": "๋ชฉํ‘œ ๊ฐ์ •",
56
+ "brand_personality": "๋ธŒ๋žœ๋“œ ์„ฑ๊ฒฉ"
57
+ }},
58
+ "visual": {{
59
+ "primary_color": "#HEX์ฝ”๋“œ",
60
+ "color_meaning": "์ƒ‰์ƒ ์˜๋ฏธ",
61
+ "visual_concept": "์‹œ๊ฐ์  ์ปจ์…‰",
62
+ "typography_style": "ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ ์Šคํƒ€์ผ"
63
+ }},
64
+ "linguistic": {{
65
+ "pronunciation": "๋ฐœ์Œ ๊ฐ€์ด๋“œ",
66
+ "etymology": "์–ด์›/๊ตฌ์„ฑ",
67
+ "global_adaptability": "๊ธ€๋กœ๋ฒŒ ์ ์‘์„ฑ",
68
+ "memorable_factor": "๊ธฐ์–ต ์šฉ์ด์„ฑ ์š”์†Œ"
69
+ }},
70
+ "strategic": {{
71
+ "differentiation": "์ฐจ๋ณ„ํ™” ํฌ์ธํŠธ",
72
+ "market_positioning": "์‹œ์žฅ ํฌ์ง€์…”๋‹",
73
+ "growth_potential": "์„ฑ์žฅ ์ž ์žฌ๋ ฅ",
74
+ "implementation_ease": "์‹คํ–‰ ์šฉ์ด์„ฑ"
75
+ }},
76
+ "theory_specific": {{
77
+ {theory_specific_fields}
78
+ }},
79
+ "evaluation": {{
80
+ "creativity_score": 0-10,
81
+ "memorability_score": 0-10,
82
+ "relevance_score": 0-10,
83
+ "overall_effectiveness": "์ „์ฒด์ ์ธ ํšจ๊ณผ์„ฑ ์„ค๋ช…"
84
+ }}
85
+ }}
86
+ ]
87
+ }}
88
+
89
+ ๋ฐ˜๋“œ์‹œ ์œ ํšจํ•œ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•˜๊ณ , ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ฑ„์›Œ์ฃผ์„ธ์š”.
90
+ ๊ฐ ์ด๋ก ์˜ ํŠน์„ฑ์„ theory_specific ์„น์…˜์— ๋‹ด๋˜, ๋‚˜๋จธ์ง€๋Š” ํ†ต์ผ๋œ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•˜์„ธ์š”.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  """
92
 
93
+ # ์ด๋ก ๋ณ„ ํŠน์ˆ˜ ํ•„๋“œ ์ •์˜
94
+ THEORY_SPECIFIC_FIELDS = {
95
+ "square": """
96
+ "tl": "์™ผ์ชฝ์ƒ๋‹จ",
97
+ "tr": "์˜ค๋ฅธ์ชฝ์ƒ๋‹จ",
98
+ "bl": "์™ผ์ชฝํ•˜๋‹จ",
99
+ "br": "์˜ค๋ฅธ์ชฝํ•˜๋‹จ",
100
+ "top_edge": "์ƒ๋‹จ ๊ด€๊ณ„",
101
+ "bottom_edge": "ํ•˜๋‹จ ๊ด€๊ณ„",
102
+ "left_edge": "์™ผ์ชฝ ๊ด€๊ณ„",
103
+ "right_edge": "์˜ค๋ฅธ์ชฝ ๊ด€๊ณ„",
104
+ "diagonal_insight": "๋Œ€๊ฐ์„  ํ†ต์ฐฐ"
105
+ """,
106
+
107
+ "blending": """
108
+ "input_space1": "์ฒซ ๋ฒˆ์งธ ๊ฐœ๋…",
109
+ "input_space2": "๋‘ ๋ฒˆ์งธ ๊ฐœ๋…",
110
+ "generic_space": "๊ณตํ†ต ๊ตฌ์กฐ",
111
+ "blended_space": "ํ˜ผํ•ฉ๋œ ์ƒˆ๋กœ์šด ์˜๋ฏธ",
112
+ "emergent_properties": "์ฐฝ๋ฐœ์  ์†์„ฑ๋“ค",
113
+ "blend_ratio": "ํ˜ผํ•ฉ ๋น„์œจ"
114
+ """,
115
+
116
+ "sound": """
117
+ "phonetic_analysis": "์Œ์„ฑ ๋ถ„์„",
118
+ "sound_meaning": "์Œํ–ฅ์ด ์ „๋‹ฌํ•˜๋Š” ์˜๋ฏธ",
119
+ "vowel_consonant_ratio": "๋ชจ์Œ/์ž์Œ ๋น„์œจ",
120
+ "phoneme_emotion_map": "์Œ์†Œ-๊ฐ์ • ๋งคํ•‘",
121
+ "cross_linguistic_sound": "์–ธ์–ด๊ฐ„ ์Œํ–ฅ ์ผ๊ด€์„ฑ"
122
+ """,
123
+
124
+ "linguistic": """
125
+ "korean_adaptation": "ํ•œ๊ตญ์–ด ์ ์‘",
126
+ "english_meaning": "์˜์–ด ์˜๋ฏธ",
127
+ "cultural_considerations": "๋ฌธํ™”์  ๊ณ ๋ ค์‚ฌํ•ญ",
128
+ "avoid_meanings": "ํ”ผํ•ด์•ผ ํ•  ์˜๋ฏธ๋“ค",
129
+ "localization_strategy": "ํ˜„์ง€ํ™” ์ „๋žต"
130
+ """,
131
+
132
+ "archetype": """
133
+ "archetype": "์„ ํƒ๋œ ์›ํ˜•",
134
+ "archetype_traits": "์›ํ˜•์˜ ํŠน์ง•๋“ค",
135
+ "shadow_side": "๊ทธ๋ฆผ์ž ์ธก๋ฉด",
136
+ "mythology_reference": "์‹ ํ™”์  ์ฐธ์กฐ",
137
+ "customer_journey": "๊ณ ๊ฐ ์—ฌ์ • ์—ฐ๊ฒฐ"
138
+ """,
139
+
140
+ "jobs": """
141
+ "functional_job": "๊ธฐ๋Šฅ์  ์ผ",
142
+ "emotional_job": "๊ฐ์ •์  ์ผ",
143
+ "social_job": "์‚ฌํšŒ์  ์ผ",
144
+ "job_statement": "ํ•ต์‹ฌ Job ๋ฌธ์žฅ",
145
+ "outcome_metrics": "์„ฑ๊ณผ ์ง€ํ‘œ"
146
+ """,
147
+
148
+ "scamper": """
149
+ "scamper_technique": "์‚ฌ์šฉ๋œ ๊ธฐ๋ฒ•",
150
+ "original_concept": "์›๋ž˜ ๊ฐœ๋…",
151
+ "transformation": "๋ณ€ํ˜• ๊ณผ์ •",
152
+ "innovation_type": "ํ˜์‹  ์œ ํ˜•",
153
+ "disruption_level": "ํŒŒ๊ดด์  ํ˜์‹  ์ˆ˜์ค€"
154
+ """,
155
+
156
+ "design": """
157
+ "user_insight": "์‚ฌ์šฉ์ž ํ†ต์ฐฐ",
158
+ "pain_point": "ํ•ด๊ฒฐํ•˜๋Š” ๋ฌธ์ œ์ ",
159
+ "desirability": "๋ฐ”๋žŒ์งํ•จ (์ธ๊ฐ„)",
160
+ "feasibility": "์‹คํ˜„๊ฐ€๋Šฅ์„ฑ (๊ธฐ์ˆ )",
161
+ "viability": "์ƒ์กด๊ฐ€๋Šฅ์„ฑ (๋น„์ฆˆ๋‹ˆ์Šค)"
162
+ """,
163
+
164
+ "biomimicry": """
165
+ "natural_inspiration": "์ž์—ฐ์  ์˜๊ฐ์›",
166
+ "biomimetic_principle": "์ƒ์ฒด๋ชจ๋ฐฉ ์›๋ฆฌ",
167
+ "form_function": "ํ˜•ํƒœ์™€ ๊ธฐ๋Šฅ",
168
+ "sustainability_aspect": "์ง€์†๊ฐ€๋Šฅ์„ฑ ์ธก๋ฉด",
169
+ "adaptation_strategy": "์ ์‘ ์ „๋žต"
170
+ """,
171
+
172
+ "cognitive": """
173
+ "syllable_count": "์Œ์ ˆ ์ˆ˜",
174
+ "processing_ease": "์ฒ˜๋ฆฌ ์šฉ์ด์„ฑ ์ ์ˆ˜",
175
+ "memory_hooks": "๊ธฐ์–ต ๊ณ ๋ฆฌ",
176
+ "cognitive_fluency": "์ธ์ง€์  ์œ ์ฐฝ์„ฑ",
177
+ "attention_span_fit": "์ฃผ์˜๋ ฅ ์ ํ•ฉ๋„"
178
+ """,
179
+
180
+ "vonrestorff": """
181
+ "category_norm": "์นดํ…Œ๊ณ ๋ฆฌ ํ‘œ์ค€",
182
+ "deviation_strategy": "์ผํƒˆ ์ „๋žต",
183
+ "uniqueness_factors": "๋…ํŠน์„ฑ ์š”์†Œ๋“ค",
184
+ "attention_triggers": "์ฃผ์˜ ํŠธ๋ฆฌ๊ฑฐ",
185
+ "isolation_effect": "๊ณ ๋ฆฝ ํšจ๊ณผ ํ™œ์šฉ"
186
+ """,
187
+
188
+ "network": """
189
+ "network_type": "๋„คํŠธ์›Œํฌ ์œ ํ˜•",
190
+ "viral_coefficient": "๋ฐ”์ด๋Ÿด ๊ณ„์ˆ˜",
191
+ "sharing_ease": "๊ณต์œ  ์šฉ์ด์„ฑ",
192
+ "community_aspect": "์ปค๋ฎค๋‹ˆํ‹ฐ ์ธก๋ฉด",
193
+ "network_value": "๋„คํŠธ์›Œํฌ ๊ฐ€์น˜"
194
+ """,
195
+
196
+ "memetics": """
197
+ "meme_structure": "๋ฐˆ ๊ตฌ์กฐ",
198
+ "replication_ease": "๋ณต์ œ ์šฉ์ด์„ฑ",
199
+ "mutation_potential": "๋ณ€์ด ์ž ์žฌ๋ ฅ",
200
+ "cultural_fitness": "๋ฌธํ™”์  ์ ํ•ฉ๋„",
201
+ "transmission_channels": "์ „๋‹ฌ ์ฑ„๋„"
202
+ """,
203
+
204
+ "color": """
205
+ "color_palette": "์ƒ‰์ƒ ํŒ”๋ ˆํŠธ",
206
+ "emotional_response": "๊ฐ์ •์  ๋ฐ˜์‘",
207
+ "cultural_associations": "๋ฌธํ™”์  ์—ฐ์ƒ",
208
+ "industry_alignment": "์—…์ข… ์ •๋ ฌ",
209
+ "color_accessibility": "์ƒ‰์ƒ ์ ‘๊ทผ์„ฑ"
210
+ """,
211
+
212
+ "gestalt": """
213
+ "gestalt_principle": "ํ™œ์šฉ ์›์น™",
214
+ "visual_structure": "์‹œ๊ฐ์  ๊ตฌ์กฐ",
215
+ "perceptual_grouping": "์ง€๊ฐ์  ๊ทธ๋ฃนํ™”",
216
+ "figure_ground": "์ „๊ฒฝ-๋ฐฐ๊ฒฝ ๊ด€๊ณ„",
217
+ "closure_effect": "ํ์‡„ ํšจ๊ณผ"
218
+ """
219
  }
220
 
221
+ def create_theory_prompt(theory: str) -> str:
222
+ """๊ฐ ์ด๋ก ๋ณ„ ํ†ต์ผ๋œ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ"""
223
+ theory_names = {
224
+ "square": "Square Theory",
225
+ "blending": "Conceptual Blending Theory",
226
+ "sound": "Sound Symbolism",
227
+ "linguistic": "Linguistic Relativity",
228
+ "archetype": "Jung์˜ Archetype Theory",
229
+ "jobs": "Jobs-to-be-Done Theory",
230
+ "scamper": "SCAMPER Method",
231
+ "design": "IDEO์˜ Design Thinking",
232
+ "biomimicry": "Biomimicry",
233
+ "cognitive": "Cognitive Load Theory",
234
+ "vonrestorff": "Von Restorff Effect",
235
+ "network": "Network Effects",
236
+ "memetics": "Memetics",
237
+ "color": "Color Psychology",
238
+ "gestalt": "Gestalt Theory"
239
+ }
240
+
241
+ return UNIFIED_BASE_PROMPT.format(
242
+ theory_name=theory_names[theory],
243
+ theory_description=THEORY_DESCRIPTIONS[theory],
244
+ theory_specific_fields=THEORY_SPECIFIC_FIELDS[theory]
245
+ )
246
 
247
  def generate_by_theory(industry: str, keywords: str, theory: str, count: int = 3) -> Tuple[str, str]:
248
  """ํŠน์ • ์ด๋ก ์œผ๋กœ ๋ธŒ๋žœ๋“œ ์ƒ์„ฑ"""
 
250
  if not industry or not keywords:
251
  return "โš ๏ธ ์—…์ข…๊ณผ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.", ""
252
 
253
+ prompt = create_theory_prompt(theory)
254
  user_input = f"""์—…์ข…: {industry}
255
  ํ‚ค์›Œ๋“œ: {keywords}
256
 
257
  ์œ„ ์ •๋ณด๋กœ {count}๊ฐœ์˜ ๋ธŒ๋žœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”.
258
+ ๊ฐ ๋ธŒ๋žœ๋“œ๋Š” ํ†ต์ผ๋œ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๋˜, theory_specific ์„น์…˜์—๋Š” {theory} ์ด๋ก ์˜ ํŠน์„ฑ์„ ๋ฐ˜์˜ํ•˜์„ธ์š”."""
 
259
 
260
  try:
261
  response = client.chat.completions.create(
262
+ model="gpt-4o-mini",
263
  messages=[
264
  {"role": "system", "content": prompt},
265
  {"role": "user", "content": user_input}
 
273
  data = json.loads(content)
274
 
275
  # ์‘๋‹ต ์ •๊ทœํ™”
276
+ if "brands" in data:
277
+ results = data["brands"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  else:
279
+ results = [data]
280
 
281
  if not isinstance(results, list):
282
  results = [results]
283
 
284
  # ๋งˆํฌ๋‹ค์šด ์ƒ์„ฑ
285
+ markdown = generate_unified_markdown(theory, results, industry, keywords)
286
 
287
  # HTML ์‹œ๊ฐํ™” ์ƒ์„ฑ
288
+ html = generate_unified_visualization(theory, results)
289
 
290
  return markdown, html
291
 
292
  except Exception as e:
293
  error_msg = f"โŒ {theory} ์ด๋ก  ์˜ค๋ฅ˜: {str(e)}"
294
+ print(error_msg)
295
  return error_msg, ""
296
 
297
+ def generate_unified_markdown(theory: str, results: List[Dict], industry: str, keywords: str) -> str:
298
+ """ํ†ต์ผ๋œ ๋งˆํฌ๋‹ค์šด ์ƒ์„ฑ"""
299
 
300
  theory_names = {
301
  "square": "Square Theory",
 
316
  }
317
 
318
  theory_icons = {
319
+ "square": "๐ŸŸฆ", "blending": "๐Ÿ”€", "sound": "๐Ÿ”Š", "linguistic": "๐ŸŒ",
320
+ "archetype": "๐ŸŽญ", "jobs": "โœ…", "scamper": "๐Ÿ”ง", "design": "๐Ÿ’ญ",
321
+ "biomimicry": "๐ŸŒฟ", "cognitive": "๐Ÿง ", "vonrestorff": "โšก", "network": "๐ŸŒ",
322
+ "memetics": "๐Ÿงฌ", "color": "๐ŸŽจ", "gestalt": "๐Ÿ‘๏ธ"
 
 
 
 
 
 
 
 
 
 
 
323
  }
324
 
325
  markdown = f"""# {theory_icons[theory]} {theory_names[theory]}
 
336
  """
337
 
338
  for idx, result in enumerate(results, 1):
339
+ core = result.get('core', {})
340
+ visual = result.get('visual', {})
341
+ linguistic = result.get('linguistic', {})
342
+ strategic = result.get('strategic', {})
343
+ theory_specific = result.get('theory_specific', {})
344
+ evaluation = result.get('evaluation', {})
345
+
346
+ brand_name = core.get('brand_name', 'N/A')
347
+ slogan = core.get('slogan', 'N/A')
348
 
349
  markdown += f"\n## {idx}. {brand_name}\n"
350
  markdown += f"**์Šฌ๋กœ๊ฑด**: *\"{slogan}\"*\n\n"
351
 
352
+ # ํ•ต์‹ฌ ์ •๋ณด
353
+ markdown += f"""### ๐Ÿ“ ํ•ต์‹ฌ ์ •๋ณด
354
+ - **ํ•ต์‹ฌ ๊ฐ€์น˜**: {core.get('core_value', 'N/A')}
355
+ - **๋ชฉํ‘œ ๊ฐ์ •**: {core.get('target_emotion', 'N/A')}
356
+ - **๋ธŒ๋žœ๋“œ ์„ฑ๊ฒฉ**: {core.get('brand_personality', 'N/A')}
357
+
358
+ ### ๐ŸŽจ ์‹œ๊ฐ์  ์ปจ์…‰
359
+ - **์ฃผ์š” ์ƒ‰์ƒ**: {visual.get('primary_color', '#000000')} - {visual.get('color_meaning', 'N/A')}
360
+ - **๋น„์ฃผ์–ผ ์ปจ๏ฟฝ๏ฟฝ**: {visual.get('visual_concept', 'N/A')}
361
+ - **ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ**: {visual.get('typography_style', 'N/A')}
362
+
363
+ ### ๐Ÿ—ฃ๏ธ ์–ธ์–ด์  ํŠน์„ฑ
364
+ - **๋ฐœ์Œ**: {linguistic.get('pronunciation', 'N/A')}
365
+ - **์–ด์›/๊ตฌ์„ฑ**: {linguistic.get('etymology', 'N/A')}
366
+ - **๊ธ€๋กœ๋ฒŒ ์ ์‘์„ฑ**: {linguistic.get('global_adaptability', 'N/A')}
367
+
368
+ ### ๐ŸŽฏ ์ „๋žต์  ๊ฐ€์น˜
369
+ - **์ฐจ๋ณ„ํ™” ํฌ์ธํŠธ**: {strategic.get('differentiation', 'N/A')}
370
+ - **์‹œ์žฅ ํฌ์ง€์…”๋‹**: {strategic.get('market_positioning', 'N/A')}
371
+ - **์„ฑ์žฅ ์ž ์žฌ๋ ฅ**: {strategic.get('growth_potential', 'N/A')}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  """
373
 
374
+ # ์ด๋ก ๋ณ„ ํŠน์ˆ˜ ์ •๋ณด
375
+ if theory_specific:
376
+ markdown += f"\n### ๐Ÿ’ก {theory_names[theory]} ํŠน์„ฑ\n"
377
+ for key, value in theory_specific.items():
378
+ # ํ‚ค๋ฅผ ์ฝ๊ธฐ ์‰ฌ์šด ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
379
+ display_key = key.replace('_', ' ').title()
380
+ markdown += f"- **{display_key}**: {value}\n"
381
+
382
+ # ํ‰๊ฐ€ ์ ์ˆ˜
383
+ markdown += f"""
384
+ ### ๐Ÿ“Š ํ‰๊ฐ€
385
+ - **์ฐฝ์˜์„ฑ**: {'โญ' * int(evaluation.get('creativity_score', 0))} ({evaluation.get('creativity_score', 0)}/10)
386
+ - **๊ธฐ์–ต์„ฑ**: {'โญ' * int(evaluation.get('memorability_score', 0))} ({evaluation.get('memorability_score', 0)}/10)
387
+ - **๊ด€๋ จ์„ฑ**: {'โญ' * int(evaluation.get('relevance_score', 0))} ({evaluation.get('relevance_score', 0)}/10)
388
+
389
+ ๐Ÿ’ฌ **์ „์ฒด ํ‰๊ฐ€**: {evaluation.get('overall_effectiveness', 'N/A')}
390
+ """
391
 
392
  markdown += "\n---\n"
393
 
394
  return markdown
395
 
396
+ def generate_unified_visualization(theory: str, results: List[Dict]) -> str:
397
+ """ํ†ต์ผ๋œ ์‹œ๊ฐํ™” ์ƒ์„ฑ"""
398
 
399
  html_parts = []
400
 
401
  for idx, result in enumerate(results, 1):
402
+ core = result.get('core', {})
403
+ visual = result.get('visual', {})
404
+ linguistic = result.get('linguistic', {})
405
+ strategic = result.get('strategic', {})
406
+ theory_specific = result.get('theory_specific', {})
407
+ evaluation = result.get('evaluation', {})
408
+
409
+ brand_name = core.get('brand_name', 'Brand')
410
+ slogan = core.get('slogan', '')
411
+ primary_color = visual.get('primary_color', '#667eea')
412
+
413
+ # ํ†ต์ผ๋œ ์นด๋“œ ๋ ˆ์ด์•„์›ƒ
414
+ html = f"""
415
+ <div style="max-width: 800px; margin: 30px auto; font-family: -apple-system, sans-serif;">
416
+ <div style="background: white; border-radius: 20px; box-shadow: 0 10px 40px rgba(0,0,0,0.1); overflow: hidden;">
417
+ <!-- ํ—ค๋” -->
418
+ <div style="background: linear-gradient(135deg, {primary_color} 0%, #2c3e50 100%); padding: 40px; color: white;">
419
+ <h2 style="margin: 0 0 10px 0; font-size: 2.5em;">{brand_name}</h2>
420
+ <p style="margin: 0; font-style: italic; font-size: 1.2em; opacity: 0.9;">"{slogan}"</p>
421
+ </div>
422
+
423
+ <!-- ๋ณธ๋ฌธ -->
424
+ <div style="padding: 40px;">
425
+ <!-- ํ‰๊ฐ€ ์ ์ˆ˜ -->
426
+ <div style="display: flex; justify-content: space-around; margin-bottom: 30px;">
427
+ <div style="text-align: center;">
428
+ <div style="font-size: 2em; color: {primary_color}; font-weight: bold;">
429
+ {evaluation.get('creativity_score', 0)}/10
430
+ </div>
431
+ <div style="color: #7f8c8d; margin-top: 5px;">์ฐฝ์˜์„ฑ</div>
432
+ </div>
433
+ <div style="text-align: center;">
434
+ <div style="font-size: 2em; color: {primary_color}; font-weight: bold;">
435
+ {evaluation.get('memorability_score', 0)}/10
436
+ </div>
437
+ <div style="color: #7f8c8d; margin-top: 5px;">๊ธฐ์–ต์„ฑ</div>
438
+ </div>
439
+ <div style="text-align: center;">
440
+ <div style="font-size: 2em; color: {primary_color}; font-weight: bold;">
441
+ {evaluation.get('relevance_score', 0)}/10
442
+ </div>
443
+ <div style="color: #7f8c8d; margin-top: 5px;">๊ด€๋ จ์„ฑ</div>
444
+ </div>
445
+ </div>
446
+
447
+ <!-- ํ•ต์‹ฌ ์ •๋ณด ๊ทธ๋ฆฌ๋“œ -->
448
+ <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-bottom: 30px;">
449
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px;">
450
+ <h4 style="margin: 0 0 10px 0; color: {primary_color};">ํ•ต์‹ฌ ๊ฐ€์น˜</h4>
451
+ <p style="margin: 0; color: #555;">{core.get('core_value', 'N/A')}</p>
452
+ </div>
453
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px;">
454
+ <h4 style="margin: 0 0 10px 0; color: {primary_color};">๋ชฉํ‘œ ๊ฐ์ •</h4>
455
+ <p style="margin: 0; color: #555;">{core.get('target_emotion', 'N/A')}</p>
456
+ </div>
457
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px;">
458
+ <h4 style="margin: 0 0 10px 0; color: {primary_color};">์ฐจ๋ณ„ํ™” ํฌ์ธํŠธ</h4>
459
+ <p style="margin: 0; color: #555;">{strategic.get('differentiation', 'N/A')}</p>
460
+ </div>
461
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px;">
462
+ <h4 style="margin: 0 0 10px 0; color: {primary_color};">๋ฐœ์Œ ๊ฐ€์ด๋“œ</h4>
463
+ <p style="margin: 0; color: #555;">{linguistic.get('pronunciation', 'N/A')}</p>
464
+ </div>
465
+ </div>
466
+ """
467
+
468
+ # ์ด๋ก ๋ณ„ ํŠน์ˆ˜ ์‹œ๊ฐํ™” ์ถ”๊ฐ€
469
+ if theory == "square" and all(k in theory_specific for k in ['tl', 'tr', 'bl', 'br']):
470
+ html += visualize_square_specific(theory_specific, primary_color)
471
+ elif theory == "blending" and 'input_space1' in theory_specific:
472
+ html += visualize_blending_specific(theory_specific, primary_color)
473
+ elif theory == "color" and 'color_palette' in theory_specific:
474
+ html += visualize_color_specific(theory_specific, primary_color)
475
  else:
476
+ # ๊ธฐ๋ณธ ์ด๋ก  ํŠน์„ฑ ํ‘œ์‹œ
477
+ html += f"""
478
+ <div style="background: linear-gradient(135deg, {primary_color}15 0%, {primary_color}05 100%); padding: 25px; border-radius: 15px; margin-top: 20px;">
479
+ <h4 style="margin: 0 0 15px 0; color: {primary_color};">์ด๋ก  ํŠน์„ฑ</h4>
480
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
481
+ """
482
+ for key, value in theory_specific.items():
483
+ display_key = key.replace('_', ' ').title()
484
+ html += f"""
485
+ <div>
486
+ <strong style="color: #555;">{display_key}:</strong><br>
487
+ <span style="color: #777;">{value}</span>
488
+ </div>
489
+ """
490
+ html += """
491
+ </div>
492
+ </div>
493
+ """
494
+
495
+ # ์ „์ฒด ํ‰๊ฐ€
496
+ html += f"""
497
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin-top: 20px;">
498
+ <h4 style="margin: 0 0 10px 0; color: {primary_color};">์ „์ฒด ํ‰๊ฐ€</h4>
499
+ <p style="margin: 0; color: #555; line-height: 1.6;">{evaluation.get('overall_effectiveness', 'N/A')}</p>
500
+ </div>
501
+ </div>
502
+ </div>
503
+ </div>
504
+ """
505
+
506
+ html_parts.append(html)
507
 
508
  return "\n".join(html_parts)
509
 
510
+ def visualize_square_specific(theory_specific: Dict, primary_color: str) -> str:
511
+ """Square Theory ํŠน์ˆ˜ ์‹œ๊ฐํ™”"""
 
512
  return f"""
513
+ <div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin-top: 20px;">
514
+ <h4 style="margin: 0 0 20px 0; color: {primary_color}; text-align: center;">Square ๊ตฌ์กฐ</h4>
515
+ <div style="position: relative; width: 100%; max-width: 400px; height: 300px; margin: 0 auto;">
516
+ <div style="position: absolute; top: 0; left: 0; background: white; color: {primary_color}; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); font-weight: bold;">
517
+ {theory_specific.get('tl', '?')}
 
 
 
 
518
  </div>
519
+ <div style="position: absolute; top: 0; right: 0; background: white; color: {primary_color}; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); font-weight: bold;">
520
+ {theory_specific.get('tr', '?')}
521
  </div>
522
+ <div style="position: absolute; bottom: 0; left: 0; background: white; color: {primary_color}; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); font-weight: bold;">
523
+ {theory_specific.get('bl', '?')}
524
  </div>
525
+ <div style="position: absolute; bottom: 0; right: 0; background: white; color: {primary_color}; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); font-weight: bold;">
526
+ {theory_specific.get('br', '?')}
527
  </div>
528
 
529
+ <!-- ์—ฐ๊ฒฐ์„ ๊ณผ ๊ด€๊ณ„ ํ‘œ์‹œ -->
530
+ <div style="position: absolute; top: 25px; left: 50%; transform: translateX(-50%); color: #7f8c8d; font-size: 0.9em;">
531
+ {theory_specific.get('top_edge', '')}
532
+ </div>
533
+ <div style="position: absolute; bottom: 25px; left: 50%; transform: translateX(-50%); color: #7f8c8d; font-size: 0.9em;">
534
+ {theory_specific.get('bottom_edge', '')}
535
+ </div>
536
+ <div style="position: absolute; top: 50%; left: 25px; transform: translateY(-50%) rotate(-90deg); color: #7f8c8d; font-size: 0.9em;">
537
+ {theory_specific.get('left_edge', '')}
538
+ </div>
539
+ <div style="position: absolute; top: 50%; right: 25px; transform: translateY(-50%) rotate(90deg); color: #7f8c8d; font-size: 0.9em;">
540
+ {theory_specific.get('right_edge', '')}
541
  </div>
542
  </div>
543
  </div>
 
544
  """
545
 
546
+ def visualize_blending_specific(theory_specific: Dict, primary_color: str) -> str:
547
+ """Conceptual Blending ํŠน์ˆ˜ ์‹œ๊ฐํ™”"""
 
 
 
 
 
 
548
  return f"""
549
+ <div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin-top: 20px;">
550
+ <h4 style="margin: 0 0 20px 0; color: {primary_color}; text-align: center;">๊ฐœ๋… ํ˜ผํ•ฉ</h4>
551
+ <div style="display: flex; justify-content: center; align-items: center; gap: 20px; flex-wrap: wrap;">
552
+ <div style="text-align: center; padding: 20px; background: white; color: {primary_color}; border-radius: 50%; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
 
 
553
  <div>
554
  <strong>Input 1</strong><br>
555
+ <span style="font-size: 0.9em;">{theory_specific.get('input_space1', '')}</span>
556
  </div>
557
  </div>
558
 
559
+ <div style="font-size: 2em; color: {primary_color};">+</div>
560
 
561
+ <div style="text-align: center; padding: 20px; background: white; color: {primary_color}; border-radius: 50%; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
562
  <div>
563
  <strong>Input 2</strong><br>
564
+ <span style="font-size: 0.9em;">{theory_specific.get('input_space2', '')}</span>
565
  </div>
566
  </div>
567
 
568
+ <div style="font-size: 2em; color: {primary_color};">=</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
569
 
570
+ <div style="text-align: center; padding: 20px; background: {primary_color}; color: white; border-radius: 20px; min-width: 150px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
571
+ <strong>Blend</strong><br>
572
+ <span style="font-size: 0.95em;">{theory_specific.get('blended_space', '')}</span>
573
  </div>
574
  </div>
 
 
 
 
575
  </div>
 
576
  """
577
 
578
+ def visualize_color_specific(theory_specific: Dict, primary_color: str) -> str:
579
+ """Color Psychology ํŠน์ˆ˜ ์‹œ๊ฐํ™”"""
580
+ palette = theory_specific.get('color_palette', primary_color)
581
+ colors = palette.split(',') if ',' in palette else [primary_color]
 
 
 
 
 
 
 
 
 
 
 
 
582
 
583
+ html = f"""
584
+ <div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin-top: 20px;">
585
+ <h4 style="margin: 0 0 20px 0; color: {primary_color}; text-align: center;">์ƒ‰์ƒ ํŒ”๋ ˆํŠธ</h4>
586
+ <div style="display: flex; justify-content: center; gap: 10px; flex-wrap: wrap;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  """
 
 
 
 
588
 
589
+ for color in colors[:5]: # ์ตœ๋Œ€ 5๊ฐœ ์ƒ‰์ƒ๋งŒ ํ‘œ์‹œ
590
+ color = color.strip()
591
+ html += f"""
592
+ <div style="width: 80px; height: 80px; background: {color}; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
 
595
+ html += """
 
 
 
 
 
 
 
596
  </div>
597
  </div>
 
598
  """
599
  return html
600
 
601
  # Gradio UI
602
  with gr.Blocks(
603
+ title="Ultimate Brand Theory Generator - Unified",
604
  theme=gr.themes.Soft(),
605
  css="""
606
  .gradio-container {
 
617
  <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;">
618
  ๐ŸŒŸ Ultimate Brand Theory Generator
619
  </h1>
620
+ <p style="font-size: 1.2em; color: #7f8c8d;">15๊ฐœ ์ด๋ก ์„ ํ™œ์šฉํ•œ ์ข…ํ•ฉ ๋ธŒ๋žœ๋“œ ์ƒ์„ฑ๊ธฐ (ํ†ต์ผ๋œ ์ถœ๋ ฅ ๊ตฌ์กฐ)</p>
621
  </div>
622
  """)
623
 
 
644
 
645
  gr.Markdown("""
646
  <div style="background: #e3f2fd; padding: 15px; border-radius: 8px; margin-top: 20px;">
647
+ <h4 style="margin-top: 0; color: #1976d2;">๐Ÿ”„ ํ†ต์ผ๋œ ์ถœ๋ ฅ ๊ตฌ์กฐ</h4>
648
+ <p style="margin: 10px 0;">๋ชจ๋“  ์ด๋ก ์—์„œ ๋™์ผํ•œ ๊ตฌ์กฐ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:</p>
649
+ <ul style="margin: 5px 0; padding-left: 20px;">
650
+ <li><strong>ํ•ต์‹ฌ ์ •๋ณด</strong>: ๋ธŒ๋žœ๋“œ๋ช…, ์Šฌ๋กœ๊ฑด, ๊ฐ€์น˜, ์„ฑ๊ฒฉ</li>
651
+ <li><strong>์‹œ๊ฐ์  ์š”์†Œ</strong>: ์ƒ‰์ƒ, ๋น„์ฃผ์–ผ ์ปจ์…‰</li>
652
+ <li><strong>์–ธ์–ด์  ํŠน์„ฑ</strong>: ๋ฐœ์Œ, ๊ธ€๋กœ๋ฒŒ ์ ์‘์„ฑ</li>
653
+ <li><strong>์ „๋žต์  ๊ฐ€์น˜</strong>: ์ฐจ๋ณ„ํ™”, ํฌ์ง€์…”๋‹</li>
654
+ <li><strong>์ด๋ก ๋ณ„ ํŠน์„ฑ</strong>: ๊ฐ ์ด๋ก ์˜ ๊ณ ์œ  ์š”์†Œ</li>
655
+ <li><strong>ํ‰๊ฐ€ ์ ์ˆ˜</strong>: ์ฐฝ์˜์„ฑ, ๊ธฐ์–ต์„ฑ, ๊ด€๋ จ์„ฑ</li>
656
+ </ul>
657
  </div>
658
  """)
659
 
660
  with gr.Column(scale=3):
661
  # 15๊ฐœ ํƒญ ์ƒ์„ฑ
662
  with gr.Tabs():
663
+ # ๊ฐ ์ด๋ก ๋ณ„ ํƒญ (์˜ˆ์‹œ๋กœ ๋ช‡ ๊ฐœ๋งŒ ํ‘œ์‹œ)
664
+ theories = [
665
+ ("๐ŸŸฆ Square Theory", "square"),
666
+ ("๐Ÿ”€ Conceptual Blending", "blending"),
667
+ ("๐Ÿ”Š Sound Symbolism", "sound"),
668
+ ("๐ŸŒ Linguistic Relativity", "linguistic"),
669
+ ("๐ŸŽญ Archetype Theory", "archetype"),
670
+ ("โœ… Jobs-to-be-Done", "jobs"),
671
+ ("๐Ÿ”ง SCAMPER Method", "scamper"),
672
+ ("๐Ÿ’ญ Design Thinking", "design"),
673
+ ("๐ŸŒฟ Biomimicry", "biomimicry"),
674
+ ("๐Ÿง  Cognitive Load", "cognitive"),
675
+ ("โšก Von Restorff Effect", "vonrestorff"),
676
+ ("๐ŸŒ Network Effects", "network"),
677
+ ("๐Ÿงฌ Memetics", "memetics"),
678
+ ("๐ŸŽจ Color Psychology", "color"),
679
+ ("๐Ÿ‘๏ธ Gestalt Principles", "gestalt")
680
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
 
682
+ for tab_name, theory_key in theories:
683
+ with gr.Tab(tab_name):
684
+ with gr.Row():
685
+ btn = gr.Button(f"{tab_name}๋กœ ์ƒ์„ฑ", variant="primary", size="sm")
686
+ output = gr.Markdown()
687
+ visual = gr.HTML()
688
+
689
+ btn.click(
690
+ lambda i, k, t=theory_key: generate_by_theory(i, k, t),
691
+ inputs=[industry_input, keywords_input],
692
+ outputs=[output, visual]
693
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
694
 
695
  gr.Markdown("""
696
  <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; margin-top: 40px;">
697
+ <h3 style="margin-top: 0;">๐Ÿ“Š ํ†ต์ผ๋œ ํ‰๊ฐ€ ์‹œ์Šคํ…œ</h3>
698
+ <p style="margin: 15px 0;">๋ชจ๋“  ๋ธŒ๋žœ๋“œ๋Š” ๋‹ค์Œ 3๊ฐ€์ง€ ๊ธฐ์ค€์œผ๋กœ ํ‰๊ฐ€๋ฉ๋‹ˆ๋‹ค:</p>
699
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
700
  <div>
701
+ <h4>์ฐฝ์˜์„ฑ (Creativity)</h4>
702
+ <p style="margin: 5px 0;">๋…์ฐฝ์„ฑ๊ณผ ํ˜์‹ ์„ฑ์˜ ์ •๋„</p>
703
  </div>
704
  <div>
705
+ <h4>๊ธฐ์–ต์„ฑ (Memorability)</h4>
706
+ <p style="margin: 5px 0;">์‰ฝ๊ฒŒ ๊ธฐ์–ต๋˜๊ณ  ํšŒ์ƒ๋˜๋Š” ์ •๋„</p>
707
  </div>
708
  <div>
709
+ <h4>๊ด€๋ จ์„ฑ (Relevance)</h4>
710
+ <p style="margin: 5px 0;">์—…์ข…๊ณผ ํ‚ค์›Œ๋“œ์™€์˜ ์—ฐ๊ด€์„ฑ</p>
711
  </div>
712
  </div>
713
  </div>