Spaces:
Running
on
Zero
Running
on
Zero
import os | |
import gradio as gr | |
import random | |
import time | |
import logging | |
import google.generativeai as genai | |
import torch | |
import numpy as np | |
from diffusers import DiffusionPipeline | |
from transformers import pipeline as hf_pipeline | |
import re | |
############################################################################## | |
# 1) ZeroGPU Environment Setup + Device and Dtype Configuration | |
############################################################################## | |
try: | |
import zerogpu | |
zerogpu.init() | |
print("ZeroGPU initialized successfully") | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
except ImportError: | |
print("ZeroGPU package not installed, continuing without it") | |
if os.getenv("ZERO_GPU"): | |
print("ZeroGPU environment variable is set but zerogpu package is not installed.") | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
except Exception as e: | |
print(f"Error initializing ZeroGPU: {e}") | |
print("Continuing without ZeroGPU") | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
dtype = torch.bfloat16 if device == "cuda" else torch.float32 | |
print(f"Using device: {device}, dtype: {dtype}") | |
############################################################################## | |
# 2) Load Models: Translation Model, Diffusion Pipeline | |
############################################################################## | |
try: | |
translator = hf_pipeline( | |
"translation", | |
model="Helsinki-NLP/opus-mt-ko-en", | |
device=0 if device == "cuda" else -1 | |
) | |
pipe = DiffusionPipeline.from_pretrained( | |
"black-forest-labs/FLUX.1-schnell", | |
torch_dtype=dtype | |
).to(device) | |
print("Models loaded successfully") | |
except Exception as e: | |
print(f"Error loading models: {e}") | |
def dummy_translator(text): | |
return [{'translation_text': text}] | |
class DummyPipe: | |
def __call__(self, **kwargs): | |
from PIL import Image | |
import numpy as np | |
dummy_img = Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8)) | |
class DummyResult: | |
def __init__(self, img): | |
self.images = [img] | |
return DummyResult(dummy_img) | |
translator = dummy_translator | |
pipe = DummyPipe() | |
MAX_SEED = np.iinfo(np.int32).max | |
MAX_IMAGE_SIZE = 2048 | |
############################################################################## | |
# Korean detection and input text cleaning functions | |
############################################################################## | |
def contains_korean(text): | |
for char in text: | |
if ord('κ°') <= ord(char) <= ord('ν£'): | |
return True | |
return False | |
def clean_input_text(text): | |
""" | |
Allows only Korean, English, numbers, whitespace and common punctuation marks. | |
Adjust allowed characters as needed. | |
""" | |
allowed = re.compile(r'[^γ±-γ κ°-ν£a-zA-Z0-9\s\.\,\!\?\-\:\;\'\"]') | |
cleaned_text = allowed.sub('', text) | |
return cleaned_text | |
def log_unexpected_characters(text): | |
allowed = re.compile(r'[γ±-γ κ°-ν£a-zA-Z0-9\s\.\,\!\?\-\:\;\'\"]') | |
unexpected_chars = [char for char in text if not allowed.match(char)] | |
if unexpected_chars: | |
print("Unexpected characters found:", set(unexpected_chars)) | |
else: | |
print("No unexpected characters in the input text.") | |
############################################################################## | |
# Image Generation Function | |
############################################################################## | |
def generate_design_image(prompt, seed=42, randomize_seed=True, width=1024, height=1024, num_inference_steps=4): | |
original_prompt = prompt | |
translated = False | |
# Clean the input text | |
prompt = clean_input_text(prompt) | |
# Pre-process: if input is too long, trim to 1000 characters | |
if len(prompt) > 1000: | |
prompt = prompt[:1000] | |
if contains_korean(prompt): | |
# When calling translation, add max_length and truncation options to avoid length issues | |
translation = translator(prompt, max_length=400, truncation=True) | |
prompt = translation[0]['translation_text'] | |
translated = True | |
if randomize_seed: | |
seed = random.randint(0, MAX_SEED) | |
generator = torch.Generator(device=device).manual_seed(seed) | |
image = pipe( | |
prompt=prompt, | |
width=width, | |
height=height, | |
num_inference_steps=num_inference_steps, | |
generator=generator, | |
guidance_scale=0.0 | |
).images[0] | |
return image | |
############################################################################## | |
# Logging Setup | |
############################################################################## | |
logging.basicConfig( | |
level=logging.INFO, | |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', | |
handlers=[ | |
logging.FileHandler("api_debug.log"), | |
logging.StreamHandler() | |
] | |
) | |
logger = logging.getLogger("idea_generator") | |
############################################################################## | |
# Gemini API Key | |
############################################################################## | |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
genai.configure(api_key=GEMINI_API_KEY) | |
############################################################################## | |
# Optional Transformation Choice Function | |
############################################################################## | |
def choose_alternative(transformation): | |
if "/" not in transformation: | |
return transformation | |
parts = transformation.split("/") | |
if len(parts) != 2: | |
return random.choice([part.strip() for part in parts]) | |
left = parts[0].strip() | |
right = parts[1].strip() | |
if " " in left: | |
tokens = left.split(" ", 1) | |
prefix = tokens[0] | |
if not right.startswith(prefix): | |
option1 = left | |
option2 = prefix + " " + right | |
else: | |
option1 = left | |
option2 = right | |
return random.choice([option1, option2]) | |
else: | |
return random.choice([left, right]) | |
############################################################################## | |
# Transformation Categories Dictionaries | |
############################################################################## | |
# Korean version | |
physical_transformation_categories = { | |
"μΌμ κΈ°λ₯": [ | |
"μκ° μΌμ/κ°μ§", "μ²κ° μΌμ/κ°μ§", "μ΄κ° μΌμ/κ°μ§", "λ―Έκ° μΌμ/κ°μ§", "νκ° μΌμ/κ°μ§", | |
"μ¨λ μΌμ/κ°μ§", "μ΅λ μΌμ/κ°μ§", "μλ ₯ μΌμ/κ°μ§", "κ°μλ μΌμ/κ°μ§", "νμ μΌμ/κ°μ§", | |
"κ·Όμ μΌμ/κ°μ§", "μμΉ μΌμ/κ°μ§", "μ΄λ μΌμ/κ°μ§", "κ°μ€ μΌμ/κ°μ§", "μ μΈμ μΌμ/κ°μ§", | |
"μμΈμ μΌμ/κ°μ§", "λ°©μ¬μ μΌμ/κ°μ§", "μκΈ°μ₯ μΌμ/κ°μ§", "μ κΈ°μ₯ μΌμ/κ°μ§", "ννλ¬Όμ§ μΌμ/κ°μ§", | |
"μ체μ νΈ μΌμ/κ°μ§", "μ§λ μΌμ/κ°μ§", "μμ μΌμ/κ°μ§", "λΉ μΈκΈ° μΌμ/κ°μ§", "λΉ νμ₯ μΌμ/κ°μ§", | |
"κΈ°μΈκΈ° μΌμ/κ°μ§", "pH μΌμ/κ°μ§", "μ λ₯ μΌμ/κ°μ§", "μ μ μΌμ/κ°μ§", "μ΄λ―Έμ§ μΌμ/κ°μ§", | |
"거리 μΌμ/κ°μ§", "κΉμ΄ μΌμ/κ°μ§", "μ€λ ₯ μΌμ/κ°μ§", "μλ μΌμ/κ°μ§", "νλ¦ μΌμ/κ°μ§", | |
"μμ μΌμ/κ°μ§", "νλ μΌμ/κ°μ§", "μΌλ μΌμ/κ°μ§", "κΈμ κ°μ§", "μμ μΌμ/κ°μ§", | |
"κ΄μ μΌμ/κ°μ§", "μ΄μ λ μΌμ/κ°μ§", "ν ν¨κ³Ό μΌμ/κ°μ§", "μ΄μν μΌμ/κ°μ§", "λ μ΄λ μΌμ/κ°μ§", | |
"λΌμ΄λ€ μΌμ/κ°μ§", "ν°μΉ μΌμ/κ°μ§", "μ μ€μ² μΌμ/κ°μ§", "μ¬λ° μΌμ/κ°μ§", "νμ μΌμ/κ°μ§" | |
], | |
"ν¬κΈ°μ νν λ³ν": [ | |
"λΆνΌ λμ΄λ¨/μ€μ΄λ¦", "κΈΈμ΄ λμ΄λ¨/μ€μ΄λ¦", "λλΉ λμ΄λ¨/μ€μ΄λ¦", "λμ΄ λμ΄λ¨/μ€μ΄λ¦", | |
"λ°λ λ³ν", "λ¬΄κ² μ¦κ°/κ°μ", "λͺ¨μ λ³ν", "μν λ³ν", "λΆκ· λ± λ³ν", | |
"볡μ‘ν νν λ³ν", "λΉνλ¦Ό/κΌ¬μ", "λΆκ· μΌν νμ₯/μΆμ", "λͺ¨μ리 λ₯κΈκ²/λ μΉ΄λ‘κ²", | |
"κΉ¨μ§/κ°λΌμ§", "μ¬λ¬ μ‘°κ° λλ μ§", "λ¬Ό μ ν", "λ¨Όμ§ μ ν", "μ°κ·Έλ¬μ§/볡μ", | |
"μ ν/νΌμ³μ§", "μμ°©/ν½μ°½", "λμ΄λ¨/μμΆ", "ꡬ겨μ§/ννν΄μ§", "λκ°μ§/λ¨λ¨ν΄μ§", | |
"λ§λ¦Ό/ν΄μ§", "κΊΎμ/ꡬλΆλ¬μ§" | |
], | |
"νλ©΄ λ° μΈκ΄ λ³ν": [ | |
"μμ λ³ν", "μ§κ° λ³ν", "ν¬λͺ /λΆν¬λͺ λ³ν", "λ°μ§μ/λ¬΄κ΄ λ³ν", | |
"λΉ λ°μ¬ μ λ λ³ν", "λ¬΄λ¬ λ³ν", "κ°λμ λ°λ₯Έ μμ λ³ν", "λΉμ λ°λ₯Έ μμ λ³ν", | |
"μ¨λμ λ°λ₯Έ μμ λ³ν", "νλ‘κ·Έλ¨ ν¨κ³Ό", "νλ©΄ κ°λλ³ λΉ λ°μ¬", "νλ©΄ λͺ¨μ λ³ν", | |
"μ΄λ―ΈμΈ νλ©΄ ꡬ쑰 λ³ν", "μκ° μΈμ ν¨κ³Ό", "μΌλ£©/ν¨ν΄ μμ±", "νλ¦Ό/μ λͺ ν¨ λ³ν", | |
"κ΄ν/μ€κΈ° λ³ν", "μμ‘°/μ±λ λ³ν", "λ°κ΄/νκ΄", "λΉ μ°λ ν¨κ³Ό", | |
"λΉ ν‘μ λ³ν", "λ°ν¬λͺ ν¨κ³Ό", "κ·Έλ¦Όμ ν¨κ³Ό λ³ν", "μμΈμ λ°μ λ³ν", | |
"μΌκ΄ ν¨κ³Ό" | |
], | |
"λ¬Όμ§μ μν λ³ν": [ | |
"κ³ μ²΄/μ‘체/기체 μ ν", "κ²°μ ν/μ©ν΄", "μ°ν/λΆμ", "λ±λ±ν΄μ§/λΆλλ¬μμ§", | |
"νΉμ μν μ ν", "무μ ν/κ²°μ ν μ ν", "μ±λΆ λΆλ¦¬", "λ―ΈμΈ μ μ νμ±/λΆν΄", | |
"μ € νμ±/νμ΄μ§", "μ€μμ μν λ³ν", "λΆμ μκ° μ λ ¬/λΆν΄", "μνλ³ν μ§μ° νμ", | |
"λ Ήμ", "κ΅³μ", "μ¦λ°/μμΆ", "μΉν/μ¦μ°©", "μΉ¨μ /λΆμ ", "λΆμ°/μμ§", | |
"건쑰/μ΅μ€", "ν½μ€/μμΆ", "λκ²°/ν΄λ", "νν/μΉ¨μ", "μΆ©μ /λ°©μ ", | |
"κ²°ν©/λΆλ¦¬", "λ°ν¨/λΆν¨" | |
], | |
"μμ§μ νΉμ± λ³ν": [ | |
"κ°μ/κ°μ", "μΌμ μλ μ μ§", "μ§λ/μ§λ κ°μ", "λΆλͺν/νκΉ", | |
"νμ μλ μ¦κ°/κ°μ", "νμ λ°©ν₯ λ³ν", "λΆκ·μΉ μμ§μ", "λ©μ·λ€ λ―Έλλ¬μ§λ νμ", | |
"곡μ§/λ°κ³΅μ§", "μ 체 μ μ ν/μλ ₯ λ³ν", "μμ§μ μ ν λ³ν", "λ³΅ν© μ§λ μμ§μ", | |
"νΉμ μ 체 μ μμ§μ", "νμ -μ΄λ μ°κ³ μμ§μ", "κ΄μ± μ μ§", "좩격 ν‘μ", | |
"좩격 μ λ¬", "μ΄λλ 보쑴", "λ§μ°°λ ₯ λ³ν", "κ΄μ± νμΆ", "λΆμμ κ· ν", | |
"λμ μμ μ±", "νλ€λ¦Ό κ°μ ", "κ²½λ‘ μμΈ‘μ±", "ννΌ μμ§μ" | |
], | |
"ꡬ쑰μ λ³ν": [ | |
"λΆν μΆκ°/μ κ±°", "쑰립/λΆν΄", "μ κΈ°/ν΄κΈ°", "λ³ν/μμ볡ꡬ", "μ΅μ ꡬ쑰 λ³ν", | |
"μκ° μ¬λ°°μ΄", "μμ° ν¨ν΄ νμ±/μλ©Έ", "κ·μΉμ ν¨ν΄ λ³ν", "λͺ¨λμ λ³ν", | |
"볡μ‘μ± μ¦κ° ꡬ쑰", "μλ λͺ¨μ κΈ°μ΅ ν¨κ³Ό", "μκ°μ λ°λ₯Έ νν λ³ν", "λΆλΆ μ κ±°", | |
"λΆλΆ κ΅μ²΄", "κ²°ν©", "λΆλ¦¬", "λΆν /ν΅ν©", "μ€μ²©/κ²ΉμΉ¨", "λ΄λΆ ꡬ쑰 λ³ν", | |
"μΈλΆ ꡬ쑰 λ³ν", "μ€μ¬μΆ μ΄λ", "κ· νμ λ³ν", "κ³μΈ΅ ꡬ쑰 λ³ν", "μ§μ§ ꡬ쑰 λ³ν", | |
"μλ ₯ λΆμ° ꡬ쑰", "좩격 ν‘μ ꡬ쑰", "그리λ/λ§€νΈλ¦μ€ ꡬ쑰 λ³ν", "μνΈ μ°κ²°μ± λ³ν" | |
], | |
"κ³΅κ° μ΄λ": [ | |
"μ/λ€ μ΄λ", "μ’/μ° μ΄λ", "μ/μλ μ΄λ", "μΈλ‘μΆ νμ (κ³ κ° λλμ)", | |
"κ°λ‘μΆ νμ (κ³ κ° μ κΈ°)", "κΈΈμ΄μΆ νμ (μμΌλ‘ κΈ°μΈμ)", "μ μ΄λ", "λμ ν μ΄λ", | |
"κ΄μ±μ μν λ―Έλλ¬μ§", "νμ μΆ λ³ν", "λΆκ·μΉ νμ ", "νλ€λ¦Ό μ΄λ", "ν¬λ¬Όμ μ΄λ", | |
"무μ€λ ₯ λΆμ ", "μλ©΄ μ λΆμ ", "μ ν/λμ½", "μ¬λΌμ΄λ©", "λ‘€λ§", "μμ λν", | |
"μ볡 μ΄λ", "νμ± νκΉ", "κ΄ν΅", "ννΌ μμ§μ", "μ§κ·Έμ¬κ·Έ μ΄λ", "μ€μ μ΄λ" | |
], | |
"μκ° κ΄λ ¨ λ³ν": [ | |
"λ Έν/νν", "λ§λͺ¨/λΆμ", "μ λ°λ¨/λ³μ", "μμ/ν볡", "μλͺ μ£ΌκΈ° λ³ν", | |
"μ¬μ©μ μνΈμμ©μ λ°λ₯Έ μ μ", "νμ΅ κΈ°λ° νν μ΅μ ν", "μκ°μ λ°λ₯Έ λ¬Όμ± λ³ν", | |
"μ§λ¨ κΈ°μ΅ ν¨κ³Ό", "λ¬Ένμ μλ―Έ λ³ν", "μ§μ° λ°μ", "μ΄μ μν μμ‘΄ λ³ν", | |
"μ μ§μ μκ° λ³ν", "μ§νμ λ³ν", "μ£ΌκΈ°μ μ¬μ", "κ³μ λ³ν μ μ", | |
"μμ²΄λ¦¬λ¬ λ³ν", "μμ μ£ΌκΈ° λ¨κ³", "μ±μ₯/ν΄ν", "μκΈ° 볡ꡬ/μ¬μ", | |
"μμ° μν μ μ", "μ§μμ±/μΌμμ±", "κΈ°μ΅ ν¨κ³Ό", "μ§μ°λ μμ©", "λμ ν¨κ³Ό" | |
], | |
"λΉκ³Ό μκ° ν¨κ³Ό": [ | |
"λ°κ΄/μλ±", "λΉ ν¬κ³Ό/μ°¨λ¨", "λΉ μ°λ/μ§μ€", "μμ μ€ννΈλΌ λ³ν", "λΉ νμ ", | |
"λΉ κ°μ", "νλ‘κ·Έλ¨ μμ±", "λ μ΄μ ν¨κ³Ό", "λΉ νΈκ΄", "νκ΄/μΈκ΄", | |
"μμΈμ /μ μΈμ λ°κ΄", "κ΄νμ μ°©μ", "λΉ κ΅΄μ ", "κ·Έλ¦Όμ μμ±/μ κ±°", | |
"μμμ°¨ ν¨κ³Ό", "무μ§κ° ν¨κ³Ό", "κΈλ‘μ° ν¨κ³Ό", "νλμ ν¨κ³Ό", "μ‘°λͺ ν¨ν΄", | |
"λΉ ν¨κ³Ό", "κ΄ νν° ν¨κ³Ό", "λΉμ λ°©ν₯μ± λ³ν", "ν¬μ ν¨κ³Ό", "λΉ κ°μ§/λ°μ", | |
"κ΄λ λ³ν" | |
], | |
"μ리μ μ§λ ν¨κ³Ό": [ | |
"Sound generation/cessation", "Pitch change", "Volume change", "Timbre change", | |
"Resonance/antiresonance", "Acoustic vibration", "Ultrasonic/infrasonic emission", "Sound concentration/distribution", | |
"Sound reflection/absorption", "Acoustic Doppler effect", "Sound wave interference", "Acoustic resonance", | |
"Vibration pattern change", "Percussive effect", "Audio feedback", "Sound shielding/amplification", | |
"Directional sound", "Sound distortion", "Beat generation", "Harmonics generation", "Frequency modulation", | |
"Acoustic shockwave", "Sound filtering" | |
], | |
"Thermal Changes": [ | |
"Temperature rise/fall", "Thermal expansion/contraction", "Heat transfer/blocking", "Pressure increase/decrease", | |
"Magnetization due to heat change", "Entropy change", "Thermoelectric effect", "Magnetic-induced thermal change", | |
"Heat storage/release during phase change", "Thermal stress buildup/release", "Impact of rapid temperature change", | |
"Radiative cooling/heating", "Exothermic/endothermic", "Heat distribution change", "Heat reflection/absorption", | |
"Cooling condensation", "Thermal activation", "Thermal discoloration", "Coefficient of thermal expansion change", "Thermal stability change", | |
"Heat resistance/cold resistance", "Self-heating", "Thermal equilibrium/imbalance", "Thermal deformation", "Heat dispersion/concentration" | |
], | |
"Electrical and Magnetic Changes": [ | |
"Magnetism creation/cessation", "Charge increase/decrease", "Electric field creation/cessation", "Magnetic field creation/cessation", | |
"Superconducting transition", "Ferroelectric property change", "Quantum state change", "Plasma formation/cessation", | |
"Spin wave transmission", "Electricity generation by light", "Electricity generation by pressure", "Current change in magnetic field", | |
"Electrical resistance change", "Electrical conductivity change", "Static electricity generation/discharge", "Electromagnetic induction", | |
"Electromagnetic wave emission/absorption", "Capacitance change", "Magnetic hysteresis", "Electrical polarization", | |
"Electron flow direction change", "Electrical resonance", "Electrical shielding/exposure", "Magnetic shielding/exposure", | |
"Magnetic field alignment" | |
], | |
"Chemical Change": [ | |
"Surface coating change", "Material composition change", "Chemical reaction change", "Catalytic action start/stop", | |
"Light-induced chemical reaction", "Electricity-induced chemical reaction", "Monolayer formation", "Molecular-level structural change", | |
"Biomimetic surface change", "Environmentally responsive material change", "Periodic chemical reaction", "Oxidation", "Reduction", | |
"Polymerization", "Water splitting", "Compound formation", "Radiation effects", "Acid-base reaction", "Neutralization reaction", | |
"Ionization", "Chemical adsorption/desorption", "Catalytic efficiency change", "Enzyme activity change", "Colorimetric reaction", | |
"pH change", "Chemical equilibrium shift", "Bond formation/breakage", "Solubility change" | |
], | |
"Biological Change": [ | |
"Growth/shrinkage", "Cell division/death", "Bioluminescence", "Metabolic change", "Immune response", | |
"Hormone secretion", "Neural response", "Genetic expression", "Adaptation/evolution", "Circadian rhythm change", | |
"Regeneration/healing", "Aging/maturation", "Biomimetic change", "Biofilm formation", "Biological degradation", | |
"Enzyme activation/inactivation", "Biological signaling", "Stress response", "Thermoregulation", "Biological clock change", | |
"Extracellular matrix change", "Biomechanical response", "Cell motility", "Cell polarity change", "Nutritional status change" | |
], | |
"Environmental Interaction": [ | |
"Temperature response", "Humidity response", "Pressure response", "Gravity response", "Magnetic field response", | |
"Light response", "Sound response", "Chemical detection", "Mechanical stimulus detection", "Electrical stimulus response", | |
"Radiation response", "Vibration detection", "pH response", "Solvent response", "Gas exchange", | |
"Pollution response", "Weather response", "Seasonal response", "Circadian response", "Ecosystem interaction", | |
"Symbiotic/competitive interaction", "Predator/prey relationship", "Swarm formation", "Territorial behavior", "Migration/settlement pattern" | |
] | |
} | |
############################################################################## | |
# Gemini API Call Function (Language Independent) | |
############################################################################## | |
def query_gemini_api(prompt): | |
try: | |
model = genai.GenerativeModel('gemini-2.0-flash-thinking-exp-01-21') | |
response = model.generate_content(prompt) | |
try: | |
if hasattr(response, 'text'): | |
return response.text | |
if hasattr(response, 'candidates') and response.candidates: | |
candidate = response.candidates[0] | |
if hasattr(candidate, 'content'): | |
content = candidate.content | |
if hasattr(content, 'parts') and content.parts: | |
if len(content.parts) > 0: | |
return content.parts[0].text | |
if hasattr(response, 'parts') and response.parts: | |
if len(response.parts) > 0: | |
return response.parts[0].text | |
return "Unable to generate a response. API response structure is different than expected." | |
except Exception as inner_e: | |
logger.error(f"Error processing response: {inner_e}") | |
return f"An error occurred while processing the response: {str(inner_e)}" | |
except Exception as e: | |
logger.error(f"Error calling Gemini API: {e}") | |
if "API key not valid" in str(e): | |
return "API key is not valid. Please check your GEMINI_API_KEY environment variable." | |
return f"An error occurred while calling the API: {str(e)}" | |
############################################################################## | |
# Description Expansion Functions (LLM) - Korean and English Versions | |
############################################################################## | |
def enhance_with_llm(base_description, obj_name, category): | |
prompt = f""" | |
λ€μμ '{obj_name}'μ '{category}' κ΄λ ¨ κ°λ¨ν μ€λͺ μ λλ€: | |
"{base_description}" | |
μ λ΄μ©μ λ³΄λ€ κ΅¬μ²΄ννμ¬, | |
1) μ°½μμ μΈ λͺ¨λΈ/컨μ /νμμ λ³νμ λν μ΄ν΄, | |
2) νμ ν¬μΈνΈμ κΈ°λ₯μ± λ±μ μ€μ¬μΌλ‘ | |
3~4λ¬Έμ₯μ μμ΄λμ΄λ‘ νμ₯ν΄ μ£ΌμΈμ. | |
""" | |
return query_gemini_api(prompt) | |
def enhance_with_llm_en(base_description, obj_name, category): | |
prompt = f""" | |
Below is a brief description related to '{category}' for '{obj_name}': | |
"{base_description}" | |
Please expand the above content into a more detailed explanation, focusing on: | |
1) Creative transformation of the model/concept/shape, | |
2) Innovative aspects and functionality, | |
in 3-4 sentences. | |
""" | |
return query_gemini_api(prompt) | |
############################################################################## | |
# Transformation Idea Generation Functions for Both Languages | |
############################################################################## | |
def generate_single_object_transformation_for_category_lang(obj, selected_category, categories_dict, lang="ko"): | |
transformations = categories_dict.get(selected_category) | |
if not transformations: | |
return {} | |
transformation = choose_alternative(random.choice(transformations)) | |
if lang == "ko": | |
base_description = f"{obj}μ΄(κ°) {transformation} νμμ 보μΈλ€" | |
else: | |
base_description = f"{obj} exhibits {transformation}" | |
return {selected_category: {"base": base_description, "enhanced": None}} | |
def generate_two_objects_interaction_for_category_lang(obj1, obj2, selected_category, categories_dict, lang="ko"): | |
transformations = categories_dict.get(selected_category) | |
if not transformations: | |
return {} | |
transformation = choose_alternative(random.choice(transformations)) | |
if lang == "ko": | |
template = random.choice([ | |
"{obj1}μ΄(κ°) {obj2}μ κ²°ν©νμ¬ {change}κ° λ°μνλ€", | |
"{obj1}κ³Ό(μ) {obj2}μ΄(κ°) μΆ©λνλ©΄μ {change}κ° μΌμ΄λ¬λ€" | |
]) | |
else: | |
template = random.choice([ | |
"{obj1} combined with {obj2} resulted in {change}", | |
"A collision between {obj1} and {obj2} led to {change}" | |
]) | |
base_description = template.format(obj1=obj1, obj2=obj2, change=transformation) | |
return {selected_category: {"base": base_description, "enhanced": None}} | |
def generate_three_objects_interaction_for_category_lang(obj1, obj2, obj3, selected_category, categories_dict, lang="ko"): | |
transformations = categories_dict.get(selected_category) | |
if not transformations: | |
return {} | |
transformation = choose_alternative(random.choice(transformations)) | |
if lang == "ko": | |
template = random.choice([ | |
"{obj1}, {obj2}, {obj3}μ΄(κ°) μΌκ°ν κ΅¬μ‘°λ‘ κ²°ν©νμ¬ {change}κ° λ°μνλ€", | |
"{obj1}μ΄(κ°) {obj2}μ(κ³Ό) {obj3} μ¬μ΄μμ λ§€κ°μ²΄ μν μ νλ©° {change}λ₯Ό μ΄μ§νλ€" | |
]) | |
else: | |
template = random.choice([ | |
"{obj1}, {obj2}, and {obj3} formed a triangular structure resulting in {change}", | |
"{obj1} acted as an intermediary between {obj2} and {obj3}, facilitating {change}" | |
]) | |
base_description = template.format(obj1=obj1, obj2=obj2, obj3=obj3, change=transformation) | |
return {selected_category: {"base": base_description, "enhanced": None}} | |
def enhance_descriptions_lang(results, objects, lang="ko"): | |
obj_name = " λ° ".join([obj for obj in objects if obj]) if lang=="ko" else " and ".join([obj for obj in objects if obj]) | |
for category, result in results.items(): | |
if lang == "ko": | |
result["enhanced"] = enhance_with_llm(result["base"], obj_name, category) | |
else: | |
result["enhanced"] = enhance_with_llm_en(result["base"], obj_name, category) | |
return results | |
def generate_transformations_lang(text1, text2, text3, selected_category, categories_dict, lang="ko"): | |
if text2 and text3: | |
results = generate_three_objects_interaction_for_category_lang(text1, text2, text3, selected_category, categories_dict, lang) | |
objects = [text1, text2, text3] | |
elif text2: | |
results = generate_two_objects_interaction_for_category_lang(text1, text2, selected_category, categories_dict, lang) | |
objects = [text1, text2] | |
else: | |
results = generate_single_object_transformation_for_category_lang(text1, selected_category, categories_dict, lang) | |
objects = [text1] | |
return enhance_descriptions_lang(results, objects, lang) | |
def format_results_lang(results, lang="ko"): | |
formatted = "" | |
if lang == "ko": | |
for category, result in results.items(): | |
formatted += f"## {category}\n**κΈ°λ³Έ μμ΄λμ΄**: {result['base']}\n\n**νμ₯λ μμ΄λμ΄**: {result['enhanced']}\n\n---\n\n" | |
else: | |
for category, result in results.items(): | |
formatted += f"## {category}\n**Base Idea**: {result['base']}\n\n**Expanded Idea**: {result['enhanced']}\n\n---\n\n" | |
return formatted | |
def process_inputs_lang(text1, text2, text3, selected_category, categories_dict, lang="ko", progress=gr.Progress()): | |
text1 = text1.strip() if text1 else None | |
text2 = text2.strip() if text2 else None | |
text3 = text3.strip() if text3 else None | |
if not text1: | |
return "μ€λ₯: μ΅μ νλμ ν€μλλ₯Ό μ λ ₯ν΄μ£ΌμΈμ." if lang=="ko" else "Error: Please enter at least one keyword." | |
if lang == "ko": | |
progress(0.05, desc="μμ΄λμ΄ μμ± μ€λΉ μ€...") | |
time.sleep(0.3) | |
progress(0.1, desc="μ°½μμ μΈ μμ΄λμ΄ μμ± μμ...") | |
else: | |
progress(0.05, desc="Preparing idea generation...") | |
time.sleep(0.3) | |
progress(0.1, desc="Generating creative idea...") | |
results = generate_transformations_lang(text1, text2, text3, selected_category, categories_dict, lang) | |
if lang == "ko": | |
progress(0.8, desc="κ²°κ³Ό ν¬λ§·ν μ€...") | |
formatted = format_results_lang(results, lang) | |
progress(1.0, desc="μλ£!") | |
else: | |
progress(0.8, desc="Formatting results...") | |
formatted = format_results_lang(results, lang) | |
progress(1.0, desc="Done!") | |
return formatted | |
def process_all_lang(text1, text2, text3, selected_category, categories_dict, lang="ko", progress=gr.Progress()): | |
idea_result = process_inputs_lang(text1, text2, text3, selected_category, categories_dict, lang, progress) | |
image_result = generate_design_image( | |
idea_result, | |
seed=42, | |
randomize_seed=True, | |
width=1024, | |
height=1024, | |
num_inference_steps=4 | |
) | |
return idea_result, image_result | |
############################################################################## | |
# Warning Message Function for API Key (Language Specific) | |
############################################################################## | |
def get_warning_message_lang(lang="ko"): | |
if not GEMINI_API_KEY: | |
return "β οΈ νκ²½ λ³μ GEMINI_API_KEYκ° μ€μ λμ§ μμμ΅λλ€. Gemini API ν€λ₯Ό μ€μ νμΈμ." if lang=="ko" else "β οΈ The GEMINI_API_KEY environment variable is not set. Please set your Gemini API key." | |
return "" | |
############################################################################## | |
# Add "Business Ideas" category to each dictionary | |
############################################################################## | |
physical_transformation_categories["λΉμ¦λμ€ μμ΄λμ΄"] = [ | |
"μμ₯ μ¬μ μ/μ κ· μμ₯ κ°μ²", | |
"λΉμ¦λμ€ λͺ¨λΈ νμ /λμ§νΈ μ ν", | |
"κ³ κ° κ²½ν νμ /μλΉμ€ νμ ", | |
"νλ ₯ λ° ννΈλμ κ°ν/μνκ³ κ΅¬μΆ", | |
"κΈλ‘λ² νμ₯/μ§μν μ λ΅", | |
"μ΄μ ν¨μ¨μ± μ¦λ/μκ° μ κ°", | |
"λΈλλ 리ν¬μ§μ λ/μ΄λ―Έμ§ μ ν", | |
"μ§μ κ°λ₯ν μ±μ₯/μ¬νμ κ°μΉ μ°½μΆ", | |
"λ°μ΄ν° κΈ°λ° μμ¬κ²°μ /AI λμ ", | |
"μ κΈ°μ μ΅ν©/νμ ν¬μ" | |
] | |
physical_transformation_categories_en["Business Ideas"] = [ | |
"Market redefinition/new market creation", | |
"Business model innovation/digital transformation", | |
"Customer experience and service innovation", | |
"Enhanced partnerships and ecosystem building", | |
"Global expansion and localization strategy", | |
"Operational efficiency improvement/cost reduction", | |
"Brand repositioning/image transformation", | |
"Sustainable growth and social value creation", | |
"Data-driven decision making/AI adoption", | |
"Convergence of new technologies/innovative investments" | |
] | |
############################################################################## | |
# Helper function for caching examples in the English tab | |
############################################################################## | |
def process_all_lang_example(text1, text2, text3, selected_category): | |
# κ³ μ λ stateκ°(physical_transformation_categories_en, "en")μΌλ‘ νΈμΆ | |
return process_all_lang(text1, text2, text3, selected_category, physical_transformation_categories_en, "en") | |
############################################################################## | |
# Gradio UI with Two Tabs: English (Main Home) and Korean | |
############################################################################## | |
with gr.Blocks( | |
title="Idea Transformer", | |
theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral") | |
) as demo: | |
gr.HTML(""" | |
<style> | |
body { | |
background: linear-gradient(135deg, #e0eafc, #cfdef3); | |
font-family: 'Arial', sans-serif; | |
} | |
.gradio-container { | |
padding: 20px; | |
} | |
h1, h2 { | |
text-align: center; | |
} | |
h1 { | |
color: #333; | |
} | |
h2 { | |
color: #555; | |
} | |
.output { | |
background-color: #ffffff; | |
padding: 15px; | |
border-radius: 8px; | |
} | |
.gr-button { | |
background-color: #4CAF50; | |
color: white; | |
border: none; | |
border-radius: 4px; | |
padding: 8px 16px; | |
} | |
.progress-message { | |
color: #2196F3; | |
font-weight: bold; | |
margin-top: 10px; | |
} | |
</style> | |
""") | |
with gr.Tabs(): | |
with gr.Tab(label="English"): | |
gr.Markdown("# π Idea Transformer") | |
gr.Markdown("Based on up to **three keywords** and a **selected category**, this tool generates a creative transformation idea and a design image using the expanded idea as a prompt. https://discord.gg/openfreeai") | |
warning_en = gr.Markdown(get_warning_message_lang("en")) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
text_input1_en = gr.Textbox(label="Keyword 1 (required)", placeholder="e.g., Smartphone") | |
text_input2_en = gr.Textbox(label="Keyword 2 (optional)", placeholder="e.g., Artificial Intelligence") | |
text_input3_en = gr.Textbox(label="Keyword 3 (optional)", placeholder="e.g., Healthcare") | |
category_radio_en = gr.Radio( | |
label="Select Category", | |
choices=list(physical_transformation_categories_en.keys()), | |
value=list(physical_transformation_categories_en.keys())[0], | |
info="Select a category." | |
) | |
status_msg_en = gr.Markdown("π‘ Click the 'Generate Idea' button to create an idea and design image based on the selected category.") | |
processing_indicator_en = gr.HTML(""" | |
<div style="display: flex; justify-content: center; align-items: center; margin: 10px 0;"> | |
<div style="border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite;"></div> | |
<p style="margin-left: 10px; font-weight: bold; color: #3498db;">Processing...</p> | |
</div> | |
<style> | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
</style> | |
""", visible=False) | |
submit_button_en = gr.Button("Generate Idea", variant="primary") | |
with gr.Column(scale=2): | |
idea_output_en = gr.Markdown(label="Idea Output") | |
generated_image_en = gr.Image(label="Generated Design Image", type="pil") | |
gr.Examples( | |
examples=[ | |
["Smartphone", "", "", "Sensor Functions"], | |
["Car", "", "", "Size and Shape Change"], | |
["Car", "Artificial Intelligence", "", "Surface and Appearance Change"], | |
["Drone", "Artificial Intelligence", "", "Material State Change"], | |
["Sneakers", "Wearable", "Health", "Structural Change"], | |
], | |
inputs=[text_input1_en, text_input2_en, text_input3_en, category_radio_en], | |
fn=process_all_lang_example, | |
outputs=[idea_output_en, generated_image_en], | |
cache_examples=True | |
) | |
def show_processing_indicator_en(): | |
return gr.update(visible=True) | |
def hide_processing_indicator_en(): | |
return gr.update(visible=False) | |
submit_button_en.click( | |
fn=show_processing_indicator_en, | |
inputs=None, | |
outputs=processing_indicator_en | |
).then( | |
fn=process_all_lang, | |
inputs=[text_input1_en, text_input2_en, text_input3_en, category_radio_en, gr.State(physical_transformation_categories_en), gr.State("en")], | |
outputs=[idea_output_en, generated_image_en] | |
).then( | |
fn=hide_processing_indicator_en, | |
inputs=None, | |
outputs=processing_indicator_en | |
) | |
with gr.Tab(label="νκ΅μ΄"): | |
gr.Markdown("# π μμ΄λμ΄ νΈλμ€ν¬λ¨Έ") | |
gr.Markdown("μ λ ₯ν **ν€μλ**(μ΅λ 3κ°)μ **μΉ΄ν κ³ λ¦¬**λ₯Ό λ°νμΌλ‘, μ°½μμ μΈ λͺ¨λΈ/컨μ /νμ λ³ν μμ΄λμ΄λ₯Ό μμ±νκ³ , ν΄λΉ νμ₯ μμ΄λμ΄λ₯Ό ν둬ννΈλ‘ νμ¬ λμμΈ μ΄λ―Έμ§λ₯Ό μμ±ν©λλ€. https://discord.gg/openfreeai") | |
warning_ko = gr.Markdown(get_warning_message_lang("ko")) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
text_input1_ko = gr.Textbox(label="ν€μλ 1 (νμ)", placeholder="μ: μ€λ§νΈν°") | |
text_input2_ko = gr.Textbox(label="ν€μλ 2 (μ ν)", placeholder="μ: μΈκ³΅μ§λ₯") | |
text_input3_ko = gr.Textbox(label="ν€μλ 3 (μ ν)", placeholder="μ: ν¬μ€μΌμ΄") | |
category_radio_ko = gr.Radio( | |
label="μΉ΄ν κ³ λ¦¬ μ ν", | |
choices=list(physical_transformation_categories.keys()), | |
value=list(physical_transformation_categories.keys())[0], | |
info="μΆλ ₯ν μΉ΄ν κ³ λ¦¬λ₯Ό μ ννμΈμ." | |
) | |
status_msg_ko = gr.Markdown("π‘ 'μμ΄λμ΄ μμ±νκΈ°' λ²νΌμ ν΄λ¦νλ©΄ μ νν μΉ΄ν κ³ λ¦¬μ ν΄λΉνλ μμ΄λμ΄μ λμμΈ μ΄λ―Έμ§κ° μμ±λ©λλ€.") | |
processing_indicator_ko = gr.HTML(""" | |
<div style="display: flex; justify-content: center; align-items: center; margin: 10px 0;"> | |
<div style="border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite;"></div> | |
<p style="margin-left: 10px; font-weight: bold; color: #3498db;">μ²λ¦¬ μ€μ λλ€...</p> | |
</div> | |
<style> | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
</style> | |
""", visible=False) | |
submit_button_ko = gr.Button("μμ΄λμ΄ μμ±νκΈ°", variant="primary") | |
with gr.Column(scale=2): | |
idea_output_ko = gr.Markdown(label="μμ΄λμ΄ κ²°κ³Ό") | |
generated_image_ko = gr.Image(label="μμ±λ λμμΈ μ΄λ―Έμ§", type="pil") | |
gr.Examples( | |
examples=[ | |
["μ€λ§νΈν°", "", "", "μΌμ κΈ°λ₯"], | |
["μλμ°¨", "", "", "ν¬κΈ°μ νν λ³ν"], | |
["μλμ°¨", "μΈκ³΅μ§λ₯", "", "νλ©΄ λ° μΈκ΄ λ³ν"], | |
["λλ‘ ", "μΈκ³΅μ§λ₯", "", "λ¬Όμ§μ μν λ³ν"], | |
["μ΄λν", "μ¨μ΄λ¬λΈ", "건κ°", "ꡬ쑰μ λ³ν"], | |
], | |
inputs=[text_input1_ko, text_input2_ko, text_input3_ko, category_radio_ko] | |
) | |
def show_processing_indicator_ko(): | |
return gr.update(visible=True) | |
def hide_processing_indicator_ko(): | |
return gr.update(visible=False) | |
submit_button_ko.click( | |
fn=show_processing_indicator_ko, | |
inputs=None, | |
outputs=processing_indicator_ko | |
).then( | |
fn=process_all_lang, | |
inputs=[text_input1_ko, text_input2_ko, text_input3_ko, category_radio_ko, gr.State(physical_transformation_categories), gr.State("ko")], | |
outputs=[idea_output_ko, generated_image_ko] | |
).then( | |
fn=hide_processing_indicator_ko, | |
inputs=None, | |
outputs=processing_indicator_ko | |
) | |
if __name__ == "__main__": | |
demo.launch(debug=True) | |