|
""" |
|
THEORIAโข - Theory-driven Naming AI |
|
=================================== |
|
ํน๋ณํ 15๊ฐ์ ์ด๋ก ์ผ๋ก ์์ฑํ๋ ๋ค์ด๋ฐ AI |
|
Theory-driven Naming AI with 15 Specialized Theories |
|
----------------------------------- |
|
""" |
|
|
|
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 |
|
import time |
|
|
|
|
|
if not os.getenv("OPENAI_API_KEY"): |
|
raise EnvironmentError("OPENAI_API_KEY ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ธ์.") |
|
|
|
client = OpenAI() |
|
|
|
|
|
TEXTS = { |
|
"en": { |
|
"title": "THEORIAโข", |
|
"subtitle": "Theory-driven Naming AI with 15 Specialized Theories", |
|
"description": "Generate innovative brand names using 15 cognitive and creative theories", |
|
"industry_label": "๐ญ Industry", |
|
"industry_placeholder": "e.g., cafe, fitness, education, beauty...", |
|
"keywords_label": "๐ Keywords", |
|
"keywords_placeholder": "premium, comfortable, urban, eco-friendly...", |
|
"keywords_info": "Core values or characteristics the brand should embody", |
|
"generate_button": "Generate with {theory}", |
|
"language_label": "๐ Language", |
|
"progress_message": "Generating innovative names using {theory}...", |
|
"error_message": "โ Error in {theory}: {error}", |
|
"input_required": "โ ๏ธ Please enter both industry and keywords.", |
|
"evaluation_labels": { |
|
"creativity": "Creativity", |
|
"memorability": "Memorability", |
|
"relevance": "Relevance" |
|
} |
|
}, |
|
"ko": { |
|
"title": "THEORIAโข", |
|
"subtitle": "ํน๋ณํ 15๊ฐ์ ์ด๋ก ์ผ๋ก ์์ฑํ๋ ๋ค์ด๋ฐ AI", |
|
"description": "15๊ฐ์ง ์ธ์ง ๋ฐ ์ฐฝ์ ์ด๋ก ์ ํ์ฉํ ํ์ ์ ์ธ ๋ธ๋๋๋ช
์์ฑ", |
|
"industry_label": "๐ญ ์
์ข
", |
|
"industry_placeholder": "์: ์นดํ, ํผํธ๋์ค, ๊ต์ก, ๋ทฐํฐ...", |
|
"keywords_label": "๐ ํต์ฌ ํค์๋", |
|
"keywords_placeholder": "ํ๋ฆฌ๋ฏธ์, ํธ์ํ, ๋์์ ์ธ, ์นํ๊ฒฝ...", |
|
"keywords_info": "๋ธ๋๋๊ฐ ๋ด์์ผ ํ ํต์ฌ ๊ฐ์น๋ ํน์ง๋ค", |
|
"generate_button": "{theory}๋ก ์์ฑ", |
|
"language_label": "๐ ์ธ์ด", |
|
"progress_message": "{theory}๋ฅผ ํ์ฉํด ํ์ ์ ์ธ ์ด๋ฆ์ ์์ฑํ๊ณ ์์ต๋๋ค...", |
|
"error_message": "โ {theory} ์ค๋ฅ: {error}", |
|
"input_required": "โ ๏ธ ์
์ข
๊ณผ ํค์๋๋ฅผ ๋ชจ๋ ์
๋ ฅํด์ฃผ์ธ์.", |
|
"evaluation_labels": { |
|
"creativity": "์ฐฝ์์ฑ", |
|
"memorability": "๊ธฐ์ต์ฑ", |
|
"relevance": "๊ด๋ จ์ฑ" |
|
} |
|
} |
|
} |
|
|
|
|
|
THEORY_DESCRIPTIONS = { |
|
"en": { |
|
"square": "Creates a semantic square structure where 4 words are connected by meaningful relationships. Hidden diagonal connections create 'aha!' moments.", |
|
"blending": "Blends two or more concepts to create new meaning. Like Netflix (Net+Flix), it births innovative concepts.", |
|
"sound": "Utilizes associations between phonemes and meaning. 'i,e' convey lightness and speed, 'o,u' convey weight and slowness.", |
|
"linguistic": "Creates global brands considering linguistic thought differences. Reflects cultural nuances and localization strategies.", |
|
"archetype": "Leverages Jung's 12 universal archetypes. Creates unconscious emotional connections like Hero (Nike) or Creator (Apple).", |
|
"jobs": "Focuses on the 'job' customers are trying to get done. Integrates functional, emotional, and social needs.", |
|
"scamper": "Uses 7 creative techniques (Substitute, Combine, Adapt, Modify, Put to other use, Eliminate, Reverse) for innovation.", |
|
"design": "Pursues human-centered innovation. Finds the intersection of desirability (human), feasibility (technical), and viability (business).", |
|
"biomimicry": "Creates nature-inspired brands. Applies 3.8 billion years of evolutionary wisdom to branding.", |
|
"cognitive": "Creates brands that minimize cognitive processing. Uses 1-3 syllables for instant recognition and recall.", |
|
"vonrestorff": "Creates unique, memorable brands. Intentionally violates category conventions for 30x better recall.", |
|
"network": "Creates brands that maximize network value. Designs structures where value increases with more users.", |
|
"memetics": "Creates culturally replicable and evolving brands. Embeds viral elements that spread naturally like memes.", |
|
"color": "Creates brands using color associations and emotions. Applies color psychology: red (passion), blue (trust), green (nature).", |
|
"gestalt": "Creates brands using perception principles. Designs holistic brand experiences where the whole exceeds the sum of parts." |
|
}, |
|
"ko": { |
|
"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": "์ง๊ฐ ์๋ฆฌ๋ฅผ ํ์ฉํ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ์ ์ฒด๊ฐ ๋ถ๋ถ์ ํฉ๋ณด๋ค ํฌ๋ค๋ ์์น์ผ๋ก ํตํฉ์ ๋ธ๋๋ ๊ฒฝํ์ ์ค๊ณํฉ๋๋ค." |
|
} |
|
} |
|
|
|
|
|
UNIFIED_BASE_PROMPT_EN = """ |
|
You are a {theory_name} expert. {theory_description} |
|
|
|
Based on the user input (industry/keywords), generate an array in the following unified JSON format: |
|
|
|
{{ |
|
"brands": [ |
|
{{ |
|
"core": {{ |
|
"brand_name": "Brand Name", |
|
"slogan": "Slogan", |
|
"core_value": "Core Value", |
|
"target_emotion": "Target Emotion", |
|
"brand_personality": "Brand Personality" |
|
}}, |
|
"visual": {{ |
|
"primary_color": "#HEX", |
|
"color_meaning": "Color Meaning", |
|
"visual_concept": "Visual Concept", |
|
"typography_style": "Typography Style" |
|
}}, |
|
"linguistic": {{ |
|
"pronunciation": "Pronunciation Guide", |
|
"etymology": "Etymology/Structure", |
|
"global_adaptability": "Global Adaptability", |
|
"memorable_factor": "Memorability Factor" |
|
}}, |
|
"strategic": {{ |
|
"differentiation": "Differentiation Point", |
|
"market_positioning": "Market Positioning", |
|
"growth_potential": "Growth Potential", |
|
"implementation_ease": "Implementation Ease" |
|
}}, |
|
"theory_specific": {{ |
|
{theory_specific_fields} |
|
}}, |
|
"evaluation": {{ |
|
"creativity_score": 0-10, |
|
"memorability_score": 0-10, |
|
"relevance_score": 0-10, |
|
"overall_effectiveness": "Overall effectiveness description" |
|
}} |
|
}} |
|
] |
|
}} |
|
|
|
Return valid JSON format and fill all fields. |
|
Include theory-specific characteristics in the theory_specific section while maintaining the unified structure. |
|
All content should be in English. |
|
""" |
|
|
|
|
|
UNIFIED_BASE_PROMPT_KO = """ |
|
๋น์ ์ {theory_name} ์ ๋ฌธ๊ฐ์
๋๋ค. {theory_description} |
|
|
|
์ฌ์ฉ์ ์
๋ ฅ(์
์ข
/ํค์๋)์ ๋ฐ์ ๋ค์๊ณผ ๊ฐ์ ํต์ผ๋ JSON ํ์์ ๋ฐฐ์ด์ ์์ฑํ์ธ์: |
|
|
|
{{ |
|
"brands": [ |
|
{{ |
|
"core": {{ |
|
"brand_name": "ํ๊ธ ๋ธ๋๋๋ช
", |
|
"slogan": "์ฌ๋ก๊ฑด", |
|
"core_value": "ํต์ฌ ๊ฐ์น", |
|
"target_emotion": "๋ชฉํ ๊ฐ์ ", |
|
"brand_personality": "๋ธ๋๋ ์ฑ๊ฒฉ" |
|
}}, |
|
"visual": {{ |
|
"primary_color": "#HEX์ฝ๋", |
|
"color_meaning": "์์ ์๋ฏธ", |
|
"visual_concept": "์๊ฐ์ ์ปจ์
", |
|
"typography_style": "ํ์ดํฌ๊ทธ๋ํผ ์คํ์ผ" |
|
}}, |
|
"linguistic": {{ |
|
"pronunciation": "ํ๊ธ ๋ฐ์ ๊ฐ์ด๋", |
|
"etymology": "์ด์/๊ตฌ์ฑ (์์ด๋ช
ํฌํจ)", |
|
"global_adaptability": "์์ด ๋ธ๋๋๋ช
(์: Mother's Garden)", |
|
"memorable_factor": "๊ธฐ์ต ์ฉ์ด์ฑ ์์" |
|
}}, |
|
"strategic": {{ |
|
"differentiation": "์ฐจ๋ณํ ํฌ์ธํธ", |
|
"market_positioning": "์์ฅ ํฌ์ง์
๋", |
|
"growth_potential": "์ฑ์ฅ ์ ์ฌ๋ ฅ", |
|
"implementation_ease": "์คํ ์ฉ์ด์ฑ" |
|
}}, |
|
"theory_specific": {{ |
|
{theory_specific_fields} |
|
}}, |
|
"evaluation": {{ |
|
"creativity_score": 0-10, |
|
"memorability_score": 0-10, |
|
"relevance_score": 0-10, |
|
"overall_effectiveness": "์ ์ฒด์ ์ธ ํจ๊ณผ์ฑ ์ค๋ช
" |
|
}} |
|
}} |
|
] |
|
}} |
|
|
|
์ค์: |
|
1. brand_name์ ๋ฐ๋์ ํ๊ธ๋ก ์์ฑํ์ธ์. |
|
2. linguistic > global_adaptability์๋ ๋ฐ๋์ ์์ด ๋ธ๋๋๋ช
์ ํฌํจํ์ธ์. |
|
3. ์์ด๋ช
์ ํ๊ธ๋ช
์ ์๋ฏธ๋ฅผ ์ ์ ๋ฌํ๋, ๊ธ๋ก๋ฒํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ ์ด๋ฆ์ผ๋ก ๋ง๋์ธ์. |
|
4. ๋ชจ๋ ํ๋๋ฅผ ํ๊ตญ์ด๋ก ์์ฑํ๋, ์์ด ๋ธ๋๋๋ช
๋ง ์์ด๋ก ํ๊ธฐํ์ธ์. |
|
""" |
|
|
|
|
|
THEORY_SPECIFIC_FIELDS_EN = { |
|
"square": """ |
|
"tl": "Top Left", |
|
"tr": "Top Right", |
|
"bl": "Bottom Left", |
|
"br": "Bottom Right", |
|
"top_edge": "Top Relationship", |
|
"bottom_edge": "Bottom Relationship", |
|
"left_edge": "Left Relationship", |
|
"right_edge": "Right Relationship", |
|
"diagonal_insight": "Diagonal Insight" |
|
""", |
|
|
|
"blending": """ |
|
"input_space1": "First Concept", |
|
"input_space2": "Second Concept", |
|
"generic_space": "Common Structure", |
|
"blended_space": "Blended New Meaning", |
|
"emergent_properties": "Emergent Properties", |
|
"blend_ratio": "Blend Ratio" |
|
""", |
|
|
|
"sound": """ |
|
"phonetic_analysis": "Phonetic Analysis", |
|
"sound_meaning": "Sound Meaning", |
|
"vowel_consonant_ratio": "Vowel/Consonant Ratio", |
|
"phoneme_emotion_map": "Phoneme-Emotion Mapping", |
|
"cross_linguistic_sound": "Cross-linguistic Sound Consistency" |
|
""", |
|
|
|
"linguistic": """ |
|
"korean_adaptation": "Korean Adaptation", |
|
"english_meaning": "English Meaning", |
|
"cultural_considerations": "Cultural Considerations", |
|
"avoid_meanings": "Meanings to Avoid", |
|
"localization_strategy": "Localization Strategy" |
|
""", |
|
|
|
"archetype": """ |
|
"archetype": "Selected Archetype", |
|
"archetype_traits": "Archetype Traits", |
|
"shadow_side": "Shadow Side", |
|
"mythology_reference": "Mythological Reference", |
|
"customer_journey": "Customer Journey Connection" |
|
""", |
|
|
|
"jobs": """ |
|
"functional_job": "Functional Job", |
|
"emotional_job": "Emotional Job", |
|
"social_job": "Social Job", |
|
"job_statement": "Core Job Statement", |
|
"outcome_metrics": "Outcome Metrics" |
|
""", |
|
|
|
"scamper": """ |
|
"scamper_technique": "Technique Used", |
|
"original_concept": "Original Concept", |
|
"transformation": "Transformation Process", |
|
"innovation_type": "Innovation Type", |
|
"disruption_level": "Disruption Level" |
|
""", |
|
|
|
"design": """ |
|
"user_insight": "User Insight", |
|
"pain_point": "Pain Point Solved", |
|
"desirability": "Desirability (Human)", |
|
"feasibility": "Feasibility (Technical)", |
|
"viability": "Viability (Business)" |
|
""", |
|
|
|
"biomimicry": """ |
|
"natural_inspiration": "Natural Inspiration", |
|
"biomimetic_principle": "Biomimetic Principle", |
|
"form_function": "Form and Function", |
|
"sustainability_aspect": "Sustainability Aspect", |
|
"adaptation_strategy": "Adaptation Strategy" |
|
""", |
|
|
|
"cognitive": """ |
|
"syllable_count": "Syllable Count", |
|
"processing_ease": "Processing Ease Score", |
|
"memory_hooks": "Memory Hooks", |
|
"cognitive_fluency": "Cognitive Fluency", |
|
"attention_span_fit": "Attention Span Fit" |
|
""", |
|
|
|
"vonrestorff": """ |
|
"category_norm": "Category Norm", |
|
"deviation_strategy": "Deviation Strategy", |
|
"uniqueness_factors": "Uniqueness Factors", |
|
"attention_triggers": "Attention Triggers", |
|
"isolation_effect": "Isolation Effect Usage" |
|
""", |
|
|
|
"network": """ |
|
"network_type": "Network Type", |
|
"viral_coefficient": "Viral Coefficient", |
|
"sharing_ease": "Sharing Ease", |
|
"community_aspect": "Community Aspect", |
|
"network_value": "Network Value" |
|
""", |
|
|
|
"memetics": """ |
|
"meme_structure": "Meme Structure", |
|
"replication_ease": "Replication Ease", |
|
"mutation_potential": "Mutation Potential", |
|
"cultural_fitness": "Cultural Fitness", |
|
"transmission_channels": "Transmission Channels" |
|
""", |
|
|
|
"color": """ |
|
"color_palette": "Color Palette", |
|
"emotional_response": "Emotional Response", |
|
"cultural_associations": "Cultural Associations", |
|
"industry_alignment": "Industry Alignment", |
|
"color_accessibility": "Color Accessibility" |
|
""", |
|
|
|
"gestalt": """ |
|
"gestalt_principle": "Principle Used", |
|
"visual_structure": "Visual Structure", |
|
"perceptual_grouping": "Perceptual Grouping", |
|
"figure_ground": "Figure-Ground Relationship", |
|
"closure_effect": "Closure Effect" |
|
""" |
|
} |
|
|
|
|
|
THEORY_SPECIFIC_FIELDS_KO = { |
|
"square": """ |
|
"tl": "์ผ์ชฝ์๋จ", |
|
"tr": "์ค๋ฅธ์ชฝ์๋จ", |
|
"bl": "์ผ์ชฝํ๋จ", |
|
"br": "์ค๋ฅธ์ชฝํ๋จ", |
|
"top_edge": "์๋จ ๊ด๊ณ", |
|
"bottom_edge": "ํ๋จ ๊ด๊ณ", |
|
"left_edge": "์ผ์ชฝ ๊ด๊ณ", |
|
"right_edge": "์ค๋ฅธ์ชฝ ๊ด๊ณ", |
|
"diagonal_insight": "๋๊ฐ์ ํต์ฐฐ" |
|
""", |
|
|
|
"blending": """ |
|
"input_space1": "์ฒซ ๋ฒ์งธ ๊ฐ๋
", |
|
"input_space2": "๋ ๋ฒ์งธ ๊ฐ๋
", |
|
"generic_space": "๊ณตํต ๊ตฌ์กฐ", |
|
"blended_space": "ํผํฉ๋ ์๋ก์ด ์๋ฏธ", |
|
"emergent_properties": "์ฐฝ๋ฐ์ ์์ฑ๋ค", |
|
"blend_ratio": "ํผํฉ ๋น์จ" |
|
""", |
|
|
|
"sound": """ |
|
"phonetic_analysis": "์์ฑ ๋ถ์", |
|
"sound_meaning": "์ํฅ์ด ์ ๋ฌํ๋ ์๋ฏธ", |
|
"vowel_consonant_ratio": "๋ชจ์/์์ ๋น์จ", |
|
"phoneme_emotion_map": "์์-๊ฐ์ ๋งคํ", |
|
"cross_linguistic_sound": "์ธ์ด๊ฐ ์ํฅ ์ผ๊ด์ฑ" |
|
""", |
|
|
|
"linguistic": """ |
|
"korean_adaptation": "ํ๊ตญ์ด ์ ์", |
|
"english_meaning": "์์ด ๋ธ๋๋๋ช
", |
|
"cultural_considerations": "๋ฌธํ์ ๊ณ ๋ ค์ฌํญ", |
|
"avoid_meanings": "ํผํด์ผ ํ ์๋ฏธ๋ค", |
|
"localization_strategy": "ํ์งํ ์ ๋ต" |
|
""", |
|
|
|
"archetype": """ |
|
"archetype": "์ ํ๋ ์ํ", |
|
"archetype_traits": "์ํ์ ํน์ง๋ค", |
|
"shadow_side": "๊ทธ๋ฆผ์ ์ธก๋ฉด", |
|
"mythology_reference": "์ ํ์ ์ฐธ์กฐ", |
|
"customer_journey": "๊ณ ๊ฐ ์ฌ์ ์ฐ๊ฒฐ" |
|
""", |
|
|
|
"jobs": """ |
|
"functional_job": "๊ธฐ๋ฅ์ ์ผ", |
|
"emotional_job": "๊ฐ์ ์ ์ผ", |
|
"social_job": "์ฌํ์ ์ผ", |
|
"job_statement": "ํต์ฌ Job ๋ฌธ์ฅ", |
|
"outcome_metrics": "์ฑ๊ณผ ์งํ" |
|
""", |
|
|
|
"scamper": """ |
|
"scamper_technique": "์ฌ์ฉ๋ ๊ธฐ๋ฒ", |
|
"original_concept": "์๋ ๊ฐ๋
", |
|
"transformation": "๋ณํ ๊ณผ์ ", |
|
"innovation_type": "ํ์ ์ ํ", |
|
"disruption_level": "ํ๊ดด์ ํ์ ์์ค" |
|
""", |
|
|
|
"design": """ |
|
"user_insight": "์ฌ์ฉ์ ํต์ฐฐ", |
|
"pain_point": "ํด๊ฒฐํ๋ ๋ฌธ์ ์ ", |
|
"desirability": "๋ฐ๋์งํจ (์ธ๊ฐ)", |
|
"feasibility": "์คํ๊ฐ๋ฅ์ฑ (๊ธฐ์ )", |
|
"viability": "์์กด๊ฐ๋ฅ์ฑ (๋น์ฆ๋์ค)" |
|
""", |
|
|
|
"biomimicry": """ |
|
"natural_inspiration": "์์ฐ์ ์๊ฐ์", |
|
"biomimetic_principle": "์์ฒด๋ชจ๋ฐฉ ์๋ฆฌ", |
|
"form_function": "ํํ์ ๊ธฐ๋ฅ", |
|
"sustainability_aspect": "์ง์๊ฐ๋ฅ์ฑ ์ธก๋ฉด", |
|
"adaptation_strategy": "์ ์ ์ ๋ต" |
|
""", |
|
|
|
"cognitive": """ |
|
"syllable_count": "์์ ์", |
|
"processing_ease": "์ฒ๋ฆฌ ์ฉ์ด์ฑ ์ ์", |
|
"memory_hooks": "๊ธฐ์ต ๊ณ ๋ฆฌ", |
|
"cognitive_fluency": "์ธ์ง์ ์ ์ฐฝ์ฑ", |
|
"attention_span_fit": "์ฃผ์๋ ฅ ์ ํฉ๋" |
|
""", |
|
|
|
"vonrestorff": """ |
|
"category_norm": "์นดํ
๊ณ ๋ฆฌ ํ์ค", |
|
"deviation_strategy": "์ผํ ์ ๋ต", |
|
"uniqueness_factors": "๋
ํน์ฑ ์์๋ค", |
|
"attention_triggers": "์ฃผ์ ํธ๋ฆฌ๊ฑฐ", |
|
"isolation_effect": "๊ณ ๋ฆฝ ํจ๊ณผ ํ์ฉ" |
|
""", |
|
|
|
"network": """ |
|
"network_type": "๋คํธ์ํฌ ์ ํ", |
|
"viral_coefficient": "๋ฐ์ด๋ด ๊ณ์", |
|
"sharing_ease": "๊ณต์ ์ฉ์ด์ฑ", |
|
"community_aspect": "์ปค๋ฎค๋ํฐ ์ธก๋ฉด", |
|
"network_value": "๋คํธ์ํฌ ๊ฐ์น" |
|
""", |
|
|
|
"memetics": """ |
|
"meme_structure": "๋ฐ ๊ตฌ์กฐ", |
|
"replication_ease": "๋ณต์ ์ฉ์ด์ฑ", |
|
"mutation_potential": "๋ณ์ด ์ ์ฌ๋ ฅ", |
|
"cultural_fitness": "๋ฌธํ์ ์ ํฉ๋", |
|
"transmission_channels": "์ ๋ฌ ์ฑ๋" |
|
""", |
|
|
|
"color": """ |
|
"color_palette": "์์ ํ๋ ํธ", |
|
"emotional_response": "๊ฐ์ ์ ๋ฐ์", |
|
"cultural_associations": "๋ฌธํ์ ์ฐ์", |
|
"industry_alignment": "์
์ข
์ ๋ ฌ", |
|
"color_accessibility": "์์ ์ ๊ทผ์ฑ" |
|
""", |
|
|
|
"gestalt": """ |
|
"gestalt_principle": "ํ์ฉ ์์น", |
|
"visual_structure": "์๊ฐ์ ๊ตฌ์กฐ", |
|
"perceptual_grouping": "์ง๊ฐ์ ๊ทธ๋ฃนํ", |
|
"figure_ground": "์ ๊ฒฝ-๋ฐฐ๊ฒฝ ๊ด๊ณ", |
|
"closure_effect": "ํ์ ํจ๊ณผ" |
|
""" |
|
} |
|
|
|
def create_theory_prompt(theory: str, language: str) -> str: |
|
"""๊ฐ ์ด๋ก ๋ณ ํต์ผ๋ ํ๋กฌํํธ ์์ฑ""" |
|
theory_names = { |
|
"en": { |
|
"square": "Square Theory", |
|
"blending": "Conceptual Blending Theory", |
|
"sound": "Sound Symbolism", |
|
"linguistic": "Linguistic Relativity", |
|
"archetype": "Jung's Archetype Theory", |
|
"jobs": "Jobs-to-be-Done Theory", |
|
"scamper": "SCAMPER Method", |
|
"design": "IDEO's Design Thinking", |
|
"biomimicry": "Biomimicry", |
|
"cognitive": "Cognitive Load Theory", |
|
"vonrestorff": "Von Restorff Effect", |
|
"network": "Network Effects", |
|
"memetics": "Memetics", |
|
"color": "Color Psychology", |
|
"gestalt": "Gestalt Theory" |
|
}, |
|
"ko": { |
|
"square": "Square Theory", |
|
"blending": "Conceptual Blending Theory", |
|
"sound": "Sound Symbolism", |
|
"linguistic": "Linguistic Relativity", |
|
"archetype": "Jung์ Archetype Theory", |
|
"jobs": "Jobs-to-be-Done Theory", |
|
"scamper": "SCAMPER Method", |
|
"design": "IDEO์ Design Thinking", |
|
"biomimicry": "Biomimicry", |
|
"cognitive": "Cognitive Load Theory", |
|
"vonrestorff": "Von Restorff Effect", |
|
"network": "Network Effects", |
|
"memetics": "Memetics", |
|
"color": "Color Psychology", |
|
"gestalt": "Gestalt Theory" |
|
} |
|
} |
|
|
|
base_prompt = UNIFIED_BASE_PROMPT_EN if language == "en" else UNIFIED_BASE_PROMPT_KO |
|
theory_specific_fields = THEORY_SPECIFIC_FIELDS_EN if language == "en" else THEORY_SPECIFIC_FIELDS_KO |
|
|
|
return base_prompt.format( |
|
theory_name=theory_names[language][theory], |
|
theory_description=THEORY_DESCRIPTIONS[language][theory], |
|
theory_specific_fields=theory_specific_fields[theory] |
|
) |
|
|
|
def generate_by_theory(industry: str, keywords: str, theory: str, language: str, count: int = 3) -> Tuple[str, str, gr.update]: |
|
"""ํน์ ์ด๋ก ์ผ๋ก ๋ธ๋๋ ์์ฑ""" |
|
|
|
texts = TEXTS[language] |
|
|
|
if not industry or not keywords: |
|
return texts["input_required"], "", gr.update(visible=False) |
|
|
|
prompt = create_theory_prompt(theory, language) |
|
|
|
if language == "en": |
|
user_input = f"""Industry: {industry} |
|
Keywords: {keywords} |
|
|
|
Generate {count} brands with the above information. |
|
Each brand should have a unified structure, with theory-specific characteristics in the theory_specific section.""" |
|
else: |
|
user_input = f"""์
์ข
: {industry} |
|
ํค์๋: {keywords} |
|
|
|
์ ์ ๋ณด๋ก {count}๊ฐ์ ๋ธ๋๋๋ฅผ ์์ฑํ์ธ์. |
|
๊ฐ ๋ธ๋๋๋ ํต์ผ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋, theory_specific ์น์
์๋ {theory} ์ด๋ก ์ ํน์ฑ์ ๋ฐ์ํ์ธ์. |
|
์ค์: linguistic > global_adaptability ํ๋์ ๋ฐ๋์ ์์ด ๋ธ๋๋๋ช
์ ํฌํจํ์ธ์.""" |
|
|
|
try: |
|
|
|
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" |
|
} |
|
|
|
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 "brands" in data: |
|
results = data["brands"] |
|
else: |
|
results = [data] |
|
|
|
if not isinstance(results, list): |
|
results = [results] |
|
|
|
|
|
markdown = generate_unified_markdown(theory, results, industry, keywords, language) |
|
|
|
|
|
html = generate_unified_visualization(theory, results, language) |
|
|
|
return markdown, html, gr.update(visible=False) |
|
|
|
except Exception as e: |
|
error_msg = texts["error_message"].format(theory=theory_names[theory], error=str(e)) |
|
print(error_msg) |
|
return error_msg, "", gr.update(visible=False) |
|
|
|
def generate_unified_markdown(theory: str, results: List[Dict], industry: str, keywords: str, language: 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": "๐๏ธ" |
|
} |
|
|
|
texts = TEXTS[language] |
|
|
|
if language == "en": |
|
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;">Theory Overview</h3> |
|
<p style="margin: 0; line-height: 1.6;">{THEORY_DESCRIPTIONS[language][theory]}</p> |
|
</div> |
|
|
|
**Industry**: {industry} | **Keywords**: {keywords} |
|
*Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}* |
|
|
|
--- |
|
""" |
|
else: |
|
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[language][theory]}</p> |
|
</div> |
|
|
|
**์
์ข
**: {industry} | **ํค์๋**: {keywords} |
|
*์์ฑ ์๊ฐ: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}* |
|
|
|
--- |
|
""" |
|
|
|
for idx, result in enumerate(results, 1): |
|
core = result.get('core', {}) |
|
visual = result.get('visual', {}) |
|
linguistic = result.get('linguistic', {}) |
|
strategic = result.get('strategic', {}) |
|
theory_specific = result.get('theory_specific', {}) |
|
evaluation = result.get('evaluation', {}) |
|
|
|
brand_name = core.get('brand_name', 'N/A') |
|
slogan = core.get('slogan', 'N/A') |
|
|
|
|
|
if language == "ko": |
|
|
|
english_name = None |
|
|
|
|
|
if theory == "linguistic" and 'english_meaning' in theory_specific: |
|
english_name = theory_specific.get('english_meaning', '') |
|
|
|
|
|
if not english_name or english_name == 'N/A': |
|
english_name = linguistic.get('global_adaptability', '') |
|
|
|
|
|
if not english_name or english_name == 'N/A': |
|
etymology = linguistic.get('etymology', '') |
|
if etymology and '์์ด' in etymology and ':' in etymology: |
|
|
|
parts = etymology.split(':') |
|
for i, part in enumerate(parts): |
|
if '์์ด' in part and i + 1 < len(parts): |
|
english_name = parts[i + 1].strip().split(',')[0].strip() |
|
break |
|
|
|
|
|
if english_name and english_name != 'N/A' and english_name != brand_name: |
|
|
|
if len(english_name) > 50 or '(' in english_name or ',' in english_name: |
|
english_name = english_name.split('(')[0].split(',')[0].strip() |
|
|
|
|
|
if not any(ord(char) >= 0xAC00 and ord(char) <= 0xD7A3 for char in english_name): |
|
brand_display = f"{brand_name} / {english_name}" |
|
else: |
|
brand_display = brand_name |
|
else: |
|
brand_display = brand_name |
|
else: |
|
brand_display = brand_name |
|
|
|
markdown += f"\n## {idx}. {brand_display}\n" |
|
|
|
if language == "en": |
|
markdown += f"""**Slogan**: *"{slogan}"* |
|
|
|
### ๐ Core Information |
|
- **Core Value**: {core.get('core_value', 'N/A')} |
|
- **Target Emotion**: {core.get('target_emotion', 'N/A')} |
|
- **Brand Personality**: {core.get('brand_personality', 'N/A')} |
|
|
|
### ๐จ Visual Concept |
|
- **Primary Color**: {visual.get('primary_color', '#000000')} - {visual.get('color_meaning', 'N/A')} |
|
- **Visual Concept**: {visual.get('visual_concept', 'N/A')} |
|
- **Typography**: {visual.get('typography_style', 'N/A')} |
|
|
|
### ๐ฃ๏ธ Linguistic Features |
|
- **Pronunciation**: {linguistic.get('pronunciation', 'N/A')} |
|
- **Etymology**: {linguistic.get('etymology', 'N/A')} |
|
- **Global Adaptability**: {linguistic.get('global_adaptability', 'N/A')} |
|
|
|
### ๐ฏ Strategic Value |
|
- **Differentiation**: {strategic.get('differentiation', 'N/A')} |
|
- **Market Positioning**: {strategic.get('market_positioning', 'N/A')} |
|
- **Growth Potential**: {strategic.get('growth_potential', 'N/A')} |
|
""" |
|
else: |
|
markdown += f"""**์ฌ๋ก๊ฑด**: *"{slogan}"* |
|
|
|
### ๐ ํต์ฌ ์ ๋ณด |
|
- **ํต์ฌ ๊ฐ์น**: {core.get('core_value', 'N/A')} |
|
- **๋ชฉํ ๊ฐ์ **: {core.get('target_emotion', 'N/A')} |
|
- **๋ธ๋๋ ์ฑ๊ฒฉ**: {core.get('brand_personality', 'N/A')} |
|
|
|
### ๐จ ์๊ฐ์ ์ปจ์
|
|
- **์ฃผ์ ์์**: {visual.get('primary_color', '#000000')} - {visual.get('color_meaning', 'N/A')} |
|
- **๋น์ฃผ์ผ ์ปจ์
**: {visual.get('visual_concept', 'N/A')} |
|
- **ํ์ดํฌ๊ทธ๋ํผ**: {visual.get('typography_style', 'N/A')} |
|
|
|
### ๐ฃ๏ธ ์ธ์ด์ ํน์ฑ |
|
- **๋ฐ์**: {linguistic.get('pronunciation', 'N/A')} |
|
- **์ด์/๊ตฌ์ฑ**: {linguistic.get('etymology', 'N/A')} |
|
- **๊ธ๋ก๋ฒ ์ ์์ฑ**: {linguistic.get('global_adaptability', 'N/A')} |
|
|
|
### ๐ฏ ์ ๋ต์ ๊ฐ์น |
|
- **์ฐจ๋ณํ ํฌ์ธํธ**: {strategic.get('differentiation', 'N/A')} |
|
- **์์ฅ ํฌ์ง์
๋**: {strategic.get('market_positioning', 'N/A')} |
|
- **์ฑ์ฅ ์ ์ฌ๋ ฅ**: {strategic.get('growth_potential', 'N/A')} |
|
""" |
|
|
|
|
|
if theory_specific: |
|
theory_header = f"### ๐ก {theory_names[theory]} " + ("Features" if language == "en" else "ํน์ฑ") + "\n" |
|
markdown += theory_header |
|
for key, value in theory_specific.items(): |
|
display_key = key.replace('_', ' ').title() |
|
markdown += f"- **{display_key}**: {value}\n" |
|
|
|
|
|
eval_labels = texts["evaluation_labels"] |
|
|
|
if language == "en": |
|
markdown += f""" |
|
### ๐ Evaluation |
|
- **{eval_labels['creativity']}**: {'โญ' * int(evaluation.get('creativity_score', 0))} ({evaluation.get('creativity_score', 0)}/10) |
|
- **{eval_labels['memorability']}**: {'โญ' * int(evaluation.get('memorability_score', 0))} ({evaluation.get('memorability_score', 0)}/10) |
|
- **{eval_labels['relevance']}**: {'โญ' * int(evaluation.get('relevance_score', 0))} ({evaluation.get('relevance_score', 0)}/10) |
|
|
|
๐ฌ **Overall Assessment**: {evaluation.get('overall_effectiveness', 'N/A')} |
|
""" |
|
else: |
|
markdown += f""" |
|
### ๐ ํ๊ฐ |
|
- **{eval_labels['creativity']}**: {'โญ' * int(evaluation.get('creativity_score', 0))} ({evaluation.get('creativity_score', 0)}/10) |
|
- **{eval_labels['memorability']}**: {'โญ' * int(evaluation.get('memorability_score', 0))} ({evaluation.get('memorability_score', 0)}/10) |
|
- **{eval_labels['relevance']}**: {'โญ' * int(evaluation.get('relevance_score', 0))} ({evaluation.get('relevance_score', 0)}/10) |
|
|
|
๐ฌ **์ ์ฒด ํ๊ฐ**: {evaluation.get('overall_effectiveness', 'N/A')} |
|
""" |
|
|
|
markdown += "\n---\n" |
|
|
|
return markdown |
|
|
|
def generate_unified_visualization(theory: str, results: List[Dict], language: str) -> str: |
|
"""ํต์ผ๋ ์๊ฐํ ์์ฑ""" |
|
|
|
texts = TEXTS[language] |
|
eval_labels = texts["evaluation_labels"] |
|
|
|
html_parts = [] |
|
|
|
for idx, result in enumerate(results, 1): |
|
core = result.get('core', {}) |
|
visual = result.get('visual', {}) |
|
linguistic = result.get('linguistic', {}) |
|
strategic = result.get('strategic', {}) |
|
theory_specific = result.get('theory_specific', {}) |
|
evaluation = result.get('evaluation', {}) |
|
|
|
brand_name = core.get('brand_name', 'Brand') |
|
slogan = core.get('slogan', '') |
|
primary_color = visual.get('primary_color', '#667eea') |
|
|
|
|
|
if language == "ko": |
|
|
|
english_name = None |
|
|
|
|
|
if theory == "linguistic" and 'english_meaning' in theory_specific: |
|
english_name = theory_specific.get('english_meaning', '') |
|
|
|
|
|
if not english_name or english_name == 'N/A': |
|
english_name = linguistic.get('global_adaptability', '') |
|
|
|
|
|
if not english_name or english_name == 'N/A': |
|
etymology = linguistic.get('etymology', '') |
|
if etymology and '์์ด' in etymology and ':' in etymology: |
|
|
|
parts = etymology.split(':') |
|
for i, part in enumerate(parts): |
|
if '์์ด' in part and i + 1 < len(parts): |
|
english_name = parts[i + 1].strip().split(',')[0].strip() |
|
break |
|
|
|
|
|
if english_name and english_name != 'N/A' and english_name != brand_name: |
|
|
|
if len(english_name) > 50 or '(' in english_name or ',' in english_name: |
|
english_name = english_name.split('(')[0].split(',')[0].strip() |
|
|
|
|
|
if not any(ord(char) >= 0xAC00 and ord(char) <= 0xD7A3 for char in english_name): |
|
brand_display = f"{brand_name} / {english_name}" |
|
else: |
|
brand_display = brand_name |
|
else: |
|
brand_display = brand_name |
|
else: |
|
brand_display = brand_name |
|
|
|
|
|
if language == "en": |
|
labels = { |
|
"core_value": "Core Value", |
|
"target_emotion": "Target Emotion", |
|
"differentiation": "Differentiation", |
|
"pronunciation": "Pronunciation" |
|
} |
|
else: |
|
labels = { |
|
"core_value": "ํต์ฌ ๊ฐ์น", |
|
"target_emotion": "๋ชฉํ ๊ฐ์ ", |
|
"differentiation": "์ฐจ๋ณํ ํฌ์ธํธ", |
|
"pronunciation": "๋ฐ์ ๊ฐ์ด๋" |
|
} |
|
|
|
|
|
html = f""" |
|
<div style="max-width: 800px; margin: 30px auto; font-family: -apple-system, sans-serif;"> |
|
<div style="background: white; border-radius: 20px; box-shadow: 0 10px 40px rgba(0,0,0,0.1); overflow: hidden;"> |
|
<!-- ํค๋ --> |
|
<div style="background: linear-gradient(135deg, {primary_color} 0%, #2c3e50 100%); padding: 40px; color: white;"> |
|
<h2 style="margin: 0 0 10px 0; font-size: 2.5em;">{brand_display}</h2> |
|
<p style="margin: 0; font-style: italic; font-size: 1.2em; opacity: 0.9;">"{slogan}"</p> |
|
</div> |
|
|
|
<!-- ๋ณธ๋ฌธ --> |
|
<div style="padding: 40px;"> |
|
<!-- ํ๊ฐ ์ ์ --> |
|
<div style="display: flex; justify-content: space-around; margin-bottom: 30px;"> |
|
<div style="text-align: center;"> |
|
<div style="font-size: 2em; color: {primary_color}; font-weight: bold;"> |
|
{evaluation.get('creativity_score', 0)}/10 |
|
</div> |
|
<div style="color: #7f8c8d; margin-top: 5px;">{eval_labels['creativity']}</div> |
|
</div> |
|
<div style="text-align: center;"> |
|
<div style="font-size: 2em; color: {primary_color}; font-weight: bold;"> |
|
{evaluation.get('memorability_score', 0)}/10 |
|
</div> |
|
<div style="color: #7f8c8d; margin-top: 5px;">{eval_labels['memorability']}</div> |
|
</div> |
|
<div style="text-align: center;"> |
|
<div style="font-size: 2em; color: {primary_color}; font-weight: bold;"> |
|
{evaluation.get('relevance_score', 0)}/10 |
|
</div> |
|
<div style="color: #7f8c8d; margin-top: 5px;">{eval_labels['relevance']}</div> |
|
</div> |
|
</div> |
|
|
|
<!-- ํต์ฌ ์ ๋ณด ๊ทธ๋ฆฌ๋ --> |
|
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-bottom: 30px;"> |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0; color: {primary_color};">{labels['core_value']}</h4> |
|
<p style="margin: 0; color: #555;">{core.get('core_value', 'N/A')}</p> |
|
</div> |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0; color: {primary_color};">{labels['target_emotion']}</h4> |
|
<p style="margin: 0; color: #555;">{core.get('target_emotion', 'N/A')}</p> |
|
</div> |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0; color: {primary_color};">{labels['differentiation']}</h4> |
|
<p style="margin: 0; color: #555;">{strategic.get('differentiation', 'N/A')}</p> |
|
</div> |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0; color: {primary_color};">{labels['pronunciation']}</h4> |
|
<p style="margin: 0; color: #555;">{linguistic.get('pronunciation', 'N/A')}</p> |
|
</div> |
|
</div> |
|
""" |
|
|
|
|
|
if theory == "square" and all(k in theory_specific for k in ['tl', 'tr', 'bl', 'br']): |
|
html += visualize_square_specific(theory_specific, primary_color) |
|
elif theory == "blending" and 'input_space1' in theory_specific: |
|
html += visualize_blending_specific(theory_specific, primary_color) |
|
elif theory == "color" and 'color_palette' in theory_specific: |
|
html += visualize_color_specific(theory_specific, primary_color) |
|
else: |
|
|
|
theory_header = "Theory Features" if language == "en" else "์ด๋ก ํน์ฑ" |
|
html += f""" |
|
<div style="background: linear-gradient(135deg, {primary_color}15 0%, {primary_color}05 100%); padding: 25px; border-radius: 15px; margin-top: 20px;"> |
|
<h4 style="margin: 0 0 15px 0; color: {primary_color};">{theory_header}</h4> |
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> |
|
""" |
|
for key, value in theory_specific.items(): |
|
display_key = key.replace('_', ' ').title() |
|
html += f""" |
|
<div> |
|
<strong style="color: #555;">{display_key}:</strong><br> |
|
<span style="color: #777;">{value}</span> |
|
</div> |
|
""" |
|
html += """ |
|
</div> |
|
</div> |
|
""" |
|
|
|
|
|
overall_header = "Overall Assessment" if language == "en" else "์ ์ฒด ํ๊ฐ" |
|
html += f""" |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin-top: 20px;"> |
|
<h4 style="margin: 0 0 10px 0; color: {primary_color};">{overall_header}</h4> |
|
<p style="margin: 0; color: #555; line-height: 1.6;">{evaluation.get('overall_effectiveness', 'N/A')}</p> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
html_parts.append(html) |
|
|
|
return "\n".join(html_parts) |
|
|
|
def visualize_square_specific(theory_specific: Dict, primary_color: str) -> str: |
|
"""Square Theory ํน์ ์๊ฐํ""" |
|
return f""" |
|
<div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin-top: 20px;"> |
|
<h4 style="margin: 0 0 20px 0; color: {primary_color}; text-align: center;">Square Structure</h4> |
|
<div style="position: relative; width: 100%; max-width: 400px; height: 300px; margin: 0 auto;"> |
|
<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;"> |
|
{theory_specific.get('tl', '?')} |
|
</div> |
|
<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;"> |
|
{theory_specific.get('tr', '?')} |
|
</div> |
|
<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;"> |
|
{theory_specific.get('bl', '?')} |
|
</div> |
|
<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;"> |
|
{theory_specific.get('br', '?')} |
|
</div> |
|
|
|
<!-- ์ฐ๊ฒฐ์ ๊ณผ ๊ด๊ณ ํ์ --> |
|
<div style="position: absolute; top: 25px; left: 50%; transform: translateX(-50%); color: #7f8c8d; font-size: 0.9em;"> |
|
{theory_specific.get('top_edge', '')} |
|
</div> |
|
<div style="position: absolute; bottom: 25px; left: 50%; transform: translateX(-50%); color: #7f8c8d; font-size: 0.9em;"> |
|
{theory_specific.get('bottom_edge', '')} |
|
</div> |
|
<div style="position: absolute; top: 50%; left: 25px; transform: translateY(-50%) rotate(-90deg); color: #7f8c8d; font-size: 0.9em;"> |
|
{theory_specific.get('left_edge', '')} |
|
</div> |
|
<div style="position: absolute; top: 50%; right: 25px; transform: translateY(-50%) rotate(90deg); color: #7f8c8d; font-size: 0.9em;"> |
|
{theory_specific.get('right_edge', '')} |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_blending_specific(theory_specific: Dict, primary_color: str) -> str: |
|
"""Conceptual Blending ํน์ ์๊ฐํ""" |
|
return f""" |
|
<div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin-top: 20px;"> |
|
<h4 style="margin: 0 0 20px 0; color: {primary_color}; text-align: center;">Concept Blending</h4> |
|
<div style="display: flex; justify-content: center; align-items: center; gap: 20px; flex-wrap: wrap;"> |
|
<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);"> |
|
<div> |
|
<strong>Input 1</strong><br> |
|
<span style="font-size: 0.9em;">{theory_specific.get('input_space1', '')}</span> |
|
</div> |
|
</div> |
|
|
|
<div style="font-size: 2em; color: {primary_color};">+</div> |
|
|
|
<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);"> |
|
<div> |
|
<strong>Input 2</strong><br> |
|
<span style="font-size: 0.9em;">{theory_specific.get('input_space2', '')}</span> |
|
</div> |
|
</div> |
|
|
|
<div style="font-size: 2em; color: {primary_color};">=</div> |
|
|
|
<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);"> |
|
<strong>Blend</strong><br> |
|
<span style="font-size: 0.95em;">{theory_specific.get('blended_space', '')}</span> |
|
</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def visualize_color_specific(theory_specific: Dict, primary_color: str) -> str: |
|
"""Color Psychology ํน์ ์๊ฐํ""" |
|
palette = theory_specific.get('color_palette', primary_color) |
|
colors = palette.split(',') if ',' in palette else [primary_color] |
|
|
|
html = f""" |
|
<div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin-top: 20px;"> |
|
<h4 style="margin: 0 0 20px 0; color: {primary_color}; text-align: center;">Color Palette</h4> |
|
<div style="display: flex; justify-content: center; gap: 10px; flex-wrap: wrap;"> |
|
""" |
|
|
|
for color in colors[:5]: |
|
color = color.strip() |
|
html += f""" |
|
<div style="width: 80px; height: 80px; background: {color}; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"></div> |
|
""" |
|
|
|
html += """ |
|
</div> |
|
</div> |
|
""" |
|
return html |
|
|
|
|
|
with gr.Blocks( |
|
title="THEORIAโข - Theory-driven Naming AI", |
|
theme=gr.themes.Soft(), |
|
css=""" |
|
.gradio-container { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
max-width: 1400px !important; |
|
} |
|
/* ํญ ๋ค๋น๊ฒ์ด์
์คํ์ผ ๊ฐ์ */ |
|
.tab-nav { |
|
display: grid !important; |
|
grid-template-columns: repeat(5, 1fr) !important; |
|
gap: 8px !important; |
|
padding: 15px !important; |
|
background: #f8f9fa !important; |
|
border-radius: 10px !important; |
|
margin-bottom: 20px !important; |
|
} |
|
.tab-nav button { |
|
font-size: 0.8em !important; |
|
padding: 10px 8px !important; |
|
white-space: normal !important; |
|
line-height: 1.3 !important; |
|
height: auto !important; |
|
min-height: 50px !important; |
|
display: flex !important; |
|
align-items: center !important; |
|
justify-content: center !important; |
|
text-align: center !important; |
|
border-radius: 8px !important; |
|
transition: all 0.3s ease !important; |
|
} |
|
.tab-nav button:hover { |
|
transform: translateY(-2px) !important; |
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important; |
|
} |
|
.tab-nav button.selected { |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; |
|
color: white !important; |
|
font-weight: 600 !important; |
|
} |
|
/* ๋ชจ๋ฐ์ผ ๋ฐ์ํ */ |
|
@media (max-width: 768px) { |
|
.tab-nav { |
|
grid-template-columns: repeat(3, 1fr) !important; |
|
} |
|
} |
|
@media (max-width: 480px) { |
|
.tab-nav { |
|
grid-template-columns: repeat(2, 1fr) !important; |
|
} |
|
} |
|
@keyframes pulse { |
|
0% { opacity: 0.6; } |
|
50% { opacity: 1; } |
|
100% { opacity: 0.6; } |
|
} |
|
.progress-bar { |
|
animation: pulse 1.5s ease-in-out infinite; |
|
} |
|
""" |
|
) as demo: |
|
|
|
current_language = gr.State(value="en") |
|
|
|
def update_ui_language(language): |
|
"""UI ์ธ์ด ์
๋ฐ์ดํธ""" |
|
texts = TEXTS[language] |
|
|
|
return ( |
|
language, |
|
|
|
gr.update(value=f""" |
|
<div style="text-align: center; padding: 30px 0;"> |
|
<h1 style="font-size: 3em; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 10px;"> |
|
{texts['title']} |
|
</h1> |
|
<p style="font-size: 1.4em; color: #7f8c8d; font-weight: 500;">{texts['subtitle']}</p> |
|
<p style="font-size: 1.1em; color: #95a5a6; margin-top: 10px;">{texts['description']}</p> |
|
</div> |
|
"""), |
|
gr.update(label=texts['industry_label'], placeholder=texts['industry_placeholder']), |
|
gr.update(label=texts['keywords_label'], placeholder=texts['keywords_placeholder'], info=texts['keywords_info']), |
|
) |
|
|
|
|
|
title_section = gr.Markdown(""" |
|
<div style="text-align: center; padding: 30px 0;"> |
|
<h1 style="font-size: 3em; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 10px;"> |
|
THEORIAโข |
|
</h1> |
|
<p style="font-size: 1.4em; color: #7f8c8d; font-weight: 500;">Theory-driven Naming AI with 15 Specialized Theories</p> |
|
<p style="font-size: 1.1em; color: #95a5a6; margin-top: 10px;">Generate innovative brand names using 15 cognitive and creative theories</p> |
|
</div> |
|
""") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1, min_width=250): |
|
gr.Markdown(""" |
|
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 20px;"> |
|
<h3 style="margin-top: 0; color: #2c3e50;">๐ Brand Information</h3> |
|
</div> |
|
""") |
|
|
|
|
|
language_selector = gr.Radio( |
|
choices=[("English", "en"), ("ํ๊ตญ์ด", "ko")], |
|
value="en", |
|
label="๐ Language", |
|
info="Select output language" |
|
) |
|
|
|
industry_input = gr.Textbox( |
|
label="๐ญ Industry", |
|
placeholder="e.g., cafe, fitness, education, beauty...", |
|
value="์นดํ/์ปคํผ์" |
|
) |
|
|
|
keywords_input = gr.Textbox( |
|
label="๐ Keywords", |
|
placeholder="premium, comfortable, urban, eco-friendly...", |
|
info="Core values or characteristics the brand should embody", |
|
lines=2 |
|
) |
|
|
|
|
|
language_selector.change( |
|
update_ui_language, |
|
inputs=[language_selector], |
|
outputs=[current_language, title_section, industry_input, keywords_input] |
|
) |
|
|
|
gr.Markdown(""" |
|
<div style="background: #e3f2fd; padding: 15px; border-radius: 8px; margin-top: 20px;"> |
|
<h4 style="margin-top: 0; color: #1976d2;">๐ฏ 15 Theories</h4> |
|
<p style="margin: 10px 0; font-size: 0.9em;">Each theory offers unique approach:</p> |
|
<ul style="margin: 5px 0; padding-left: 20px; font-size: 0.8em; line-height: 1.4;"> |
|
<li><strong>Cognitive</strong>: Square, Sound, Cognitive, Gestalt</li> |
|
<li><strong>Creative</strong>: Blending, SCAMPER, Biomimicry</li> |
|
<li><strong>Strategic</strong>: Jobs-to-be-Done, Design</li> |
|
<li><strong>Cultural</strong>: Archetype, Linguistic, Memetics</li> |
|
<li><strong>Distinctive</strong>: Von Restorff, Color, Network</li> |
|
</ul> |
|
</div> |
|
|
|
<div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin-top: 15px;"> |
|
<h4 style="margin-top: 0; color: #856404;">๐ก Tips</h4> |
|
<ul style="margin: 5px 0; padding-left: 20px; font-size: 0.8em; line-height: 1.4;"> |
|
<li>Try multiple theories</li> |
|
<li>Compare results</li> |
|
<li>Combine insights</li> |
|
</ul> |
|
</div> |
|
""") |
|
|
|
with gr.Column(scale=4): |
|
|
|
gr.Markdown(""" |
|
<div style="background: #f8f9fa; padding: 15px; border-radius: 10px; margin-bottom: 20px;"> |
|
<h3 style="margin: 0; color: #2c3e50; text-align: center;">Select a Theory to Generate Names</h3> |
|
</div> |
|
""") |
|
|
|
|
|
with gr.Tabs(elem_classes="tab-nav"): |
|
theories = [ |
|
("๐ฆ Square Theory", "square"), |
|
("๐ Conceptual Blending", "blending"), |
|
("๐ Sound Symbolism", "sound"), |
|
("๐ Linguistic Relativity", "linguistic"), |
|
("๐ญ Archetype Theory", "archetype"), |
|
("โ
Jobs-to-be-Done", "jobs"), |
|
("๐ง SCAMPER Method", "scamper"), |
|
("๐ญ Design Thinking", "design"), |
|
("๐ฟ Biomimicry", "biomimicry"), |
|
("๐ง Cognitive Load", "cognitive"), |
|
("โก Von Restorff Effect", "vonrestorff"), |
|
("๐ Network Effects", "network"), |
|
("๐งฌ Memetics", "memetics"), |
|
("๐จ Color Psychology", "color"), |
|
("๐๏ธ Gestalt Principles", "gestalt") |
|
] |
|
|
|
for tab_name, theory_key in theories: |
|
with gr.Tab(tab_name): |
|
with gr.Column(): |
|
|
|
progress_msg = gr.Markdown( |
|
visible=False |
|
) |
|
|
|
with gr.Row(): |
|
btn = gr.Button( |
|
f"Generate with {tab_name}", |
|
variant="primary", |
|
size="lg", |
|
elem_id=f"btn_{theory_key}" |
|
) |
|
|
|
output = gr.Markdown() |
|
visual = gr.HTML() |
|
|
|
def show_progress(industry, keywords, theory, language, tab_name): |
|
"""ํ๋ก๊ทธ๋ ์ค๋ฐ ํ์""" |
|
if not industry or not keywords: |
|
return "", "", gr.update(visible=False) |
|
|
|
texts = TEXTS[language] |
|
progress_text = texts["progress_message"].format(theory=tab_name) |
|
|
|
progress_html = f""" |
|
<div style="text-align: center; padding: 20px; background: #f0f8ff; border-radius: 10px; margin: 10px 0;"> |
|
<div class="progress-bar" style="font-size: 1.2em; color: #1976d2;"> |
|
{progress_text} |
|
</div> |
|
<div style="margin-top: 10px;"> |
|
<div style="width: 100%; background: #e0e0e0; border-radius: 5px; overflow: hidden;"> |
|
<div style="width: 100%; height: 4px; background: linear-gradient(90deg, #1976d2 0%, #42a5f5 50%, #1976d2 100%); animation: slide 1.5s linear infinite;"></div> |
|
</div> |
|
</div> |
|
</div> |
|
<style> |
|
@keyframes slide {{ |
|
0% {{ transform: translateX(-100%); }} |
|
100% {{ transform: translateX(100%); }} |
|
}} |
|
</style> |
|
""" |
|
return "", "", gr.update(visible=True, value=progress_html) |
|
|
|
def generate_and_hide_progress(industry, keywords, theory, language): |
|
"""์์ฑ ํ ํ๋ก๊ทธ๋ ์ค๋ฐ ์จ๊น""" |
|
result_md, result_html, _ = generate_by_theory(industry, keywords, theory, language) |
|
return result_md, result_html, gr.update(visible=False) |
|
|
|
|
|
btn.click( |
|
lambda i, k, l, t=theory_key, n=tab_name: show_progress(i, k, t, l, n), |
|
inputs=[industry_input, keywords_input, current_language], |
|
outputs=[output, visual, progress_msg] |
|
).then( |
|
|
|
lambda i, k, l, t=theory_key: generate_and_hide_progress(i, k, t, l), |
|
inputs=[industry_input, keywords_input, current_language], |
|
outputs=[output, visual, progress_msg] |
|
) |
|
|
|
gr.Markdown(""" |
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px; border-radius: 15px; margin-top: 40px;"> |
|
<h3 style="margin-top: 0; text-align: center;">๐ Why THEORIAโข?</h3> |
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 25px; margin-top: 25px;"> |
|
<div style="background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0;">๐งช Scientific Foundation</h4> |
|
<p style="margin: 0; font-size: 0.95em;">Based on proven cognitive and creative theories from psychology, linguistics, and design</p> |
|
</div> |
|
<div style="background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0;">๐ฏ Multi-dimensional Approach</h4> |
|
<p style="margin: 0; font-size: 0.95em;">15 different perspectives ensure you find the perfect name for your brand</p> |
|
</div> |
|
<div style="background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0;">๐ Unified Evaluation</h4> |
|
<p style="margin: 0; font-size: 0.95em;">Consistent scoring system allows easy comparison across all theories</p> |
|
</div> |
|
<div style="background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px;"> |
|
<h4 style="margin: 0 0 10px 0;">๐ Global Ready</h4> |
|
<p style="margin: 0; font-size: 0.95em;">Multilingual support and cultural considerations built into every theory</p> |
|
</div> |
|
</div> |
|
|
|
<div style="text-align: center; margin-top: 30px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.2);"> |
|
<p style="margin: 0; font-size: 0.9em; opacity: 0.8;"> |
|
THEORIAโข - Where Science Meets Creativity in Brand Naming |
|
</p> |
|
</div> |
|
</div> |
|
""") |
|
|
|
if __name__ == "__main__": |
|
demo.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=False |
|
) |