openfree commited on
Commit
3599d8e
Β·
verified Β·
1 Parent(s): 3ebe514

Update app-backup.py

Browse files
Files changed (1) hide show
  1. app-backup.py +362 -187
app-backup.py CHANGED
@@ -12,7 +12,7 @@ from transformers import pipeline as hf_pipeline
12
  import re
13
 
14
  ##############################################################################
15
- # 1) ZeroGPU ν™˜κ²½ 처리 + device, dtype μ„€μ •
16
  ##############################################################################
17
  try:
18
  import zerogpu
@@ -34,7 +34,7 @@ dtype = torch.bfloat16 if device == "cuda" else torch.float32
34
  print(f"Using device: {device}, dtype: {dtype}")
35
 
36
  ##############################################################################
37
- # 2) λͺ¨λΈ λ‘œλ“œ: λ²ˆμ—­ λͺ¨λΈ, DiffusionPipeline
38
  ##############################################################################
39
  try:
40
  translator = hf_pipeline(
@@ -71,7 +71,7 @@ MAX_SEED = np.iinfo(np.int32).max
71
  MAX_IMAGE_SIZE = 2048
72
 
73
  ##############################################################################
74
- # ν•œκ΅­μ–΄ 감지 ν•¨μˆ˜
75
  ##############################################################################
76
  def contains_korean(text):
77
  for char in text:
@@ -79,45 +79,39 @@ def contains_korean(text):
79
  return True
80
  return False
81
 
82
- ##############################################################################
83
- # μž…λ ₯ ν…μŠ€νŠΈ 클린징 ν•¨μˆ˜: ν•œκΈ€, 영문, 숫자, 곡백 및 일반적인 λ¬Έμž₯ λΆ€ν˜Έλ§Œ ν—ˆμš©
84
- ##############################################################################
85
  def clean_input_text(text):
86
  """
87
- ν•œκΈ€, 영문, 숫자, 곡백 및 . , ! ? - : ; ' " λ“±μ˜ λ¬Έμž₯ λΆ€ν˜Έλ§Œ 남기고 μ œκ±°ν•©λ‹ˆλ‹€.
88
- ν•„μš”μ— 따라 ν—ˆμš©ν•  문자λ₯Ό μ‘°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
89
  """
90
  allowed = re.compile(r'[^γ„±-γ…Žκ°€-힣a-zA-Z0-9\s\.\,\!\?\-\:\;\'\"]')
91
  cleaned_text = allowed.sub('', text)
92
  return cleaned_text
93
 
94
- ##############################################################################
95
- # μž…λ ₯ ν…μŠ€νŠΈμ˜ μ˜ˆμƒμΉ˜ λͺ»ν•œ 문자 둜그 ν•¨μˆ˜ (λ””λ²„κΉ…μš©)
96
- ##############################################################################
97
  def log_unexpected_characters(text):
98
  allowed = re.compile(r'[γ„±-γ…Žκ°€-힣a-zA-Z0-9\s\.\,\!\?\-\:\;\'\"]')
99
  unexpected_chars = [char for char in text if not allowed.match(char)]
100
  if unexpected_chars:
101
- print("μ˜ˆμƒμΉ˜ λͺ»ν•œ 문자 발견:", set(unexpected_chars))
102
  else:
103
- print("μž…λ ₯ ν…μŠ€νŠΈμ— μ˜ˆμƒμΉ˜ λͺ»ν•œ λ¬ΈμžλŠ” μ—†μŠ΅λ‹ˆλ‹€.")
104
 
105
  ##############################################################################
106
- # 이미지 생성 ν•¨μˆ˜
107
  ##############################################################################
108
  def generate_design_image(prompt, seed=42, randomize_seed=True, width=1024, height=1024, num_inference_steps=4):
109
  original_prompt = prompt
110
  translated = False
111
 
112
- # μž…λ ₯ ν…μŠ€νŠΈ 클린징 적용
113
  prompt = clean_input_text(prompt)
114
 
115
- # 사전 처리: μž…λ ₯ ν…μŠ€νŠΈκ°€ λ„ˆλ¬΄ κΈΈλ©΄ 미리 자λ₯΄κΈ° (예: 1000자 이상이면 1000자둜 μž˜λΌλƒ„)
116
  if len(prompt) > 1000:
117
  prompt = prompt[:1000]
118
 
119
  if contains_korean(prompt):
120
- # λ²ˆμ—­ 호좜 μ‹œ max_length와 truncation μ˜΅μ…˜μ„ μΆ”κ°€ν•˜μ—¬ 길이 초과 문제λ₯Ό λ°©μ§€
121
  translation = translator(prompt, max_length=400, truncation=True)
122
  prompt = translation[0]['translation_text']
123
  translated = True
@@ -138,9 +132,8 @@ def generate_design_image(prompt, seed=42, randomize_seed=True, width=1024, heig
138
 
139
  return image
140
 
141
-
142
  ##############################################################################
143
- # λ‘œκΉ… μ„€μ •
144
  ##############################################################################
145
  logging.basicConfig(
146
  level=logging.INFO,
@@ -153,13 +146,13 @@ logging.basicConfig(
153
  logger = logging.getLogger("idea_generator")
154
 
155
  ##############################################################################
156
- # Gemini API ν‚€
157
  ##############################################################################
158
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
159
  genai.configure(api_key=GEMINI_API_KEY)
160
 
161
  ##############################################################################
162
- # 선택적 λ³€ν˜• 선택 ν•¨μˆ˜
163
  ##############################################################################
164
  def choose_alternative(transformation):
165
  if "/" not in transformation:
@@ -183,8 +176,9 @@ def choose_alternative(transformation):
183
  return random.choice([left, right])
184
 
185
  ##############################################################################
186
- # 물리적 λ³€ν™” μΉ΄ν…Œκ³ λ¦¬ 사전 (총 15개)
187
  ##############################################################################
 
188
  physical_transformation_categories = {
189
  "μ„Όμ„œ κΈ°λŠ₯": [
190
  "μ‹œκ° μ„Όμ„œ/감지", "청각 μ„Όμ„œ/감지", "촉각 μ„Όμ„œ/감지", "미각 μ„Όμ„œ/감지", "후각 μ„Όμ„œ/감지",
@@ -214,10 +208,7 @@ physical_transformation_categories = {
214
  "광택/윀기 λ³€ν™”", "색쑰/채도 λ³€ν™”", "λ°œκ΄‘/ν˜•κ΄‘", "λΉ› μ‚°λž€ 효과",
215
  "λΉ› 흑수 λ³€ν™”", "반투λͺ… 효과", "그림자 효과 λ³€ν™”", "μžμ™Έμ„  λ°˜μ‘ λ³€ν™”",
216
  "μ•Όκ΄‘ 효과"
217
- ],
218
-
219
-
220
-
221
  "물질의 μƒνƒœ λ³€ν™”": [
222
  "고체/앑체/기체 μ „ν™˜", "κ²°μ •ν™”/μš©ν•΄", "μ‚°ν™”/뢀식", "딱딱해짐/λΆ€λ“œλŸ¬μ›Œμ§",
223
  "특수 μƒνƒœ μ „ν™˜", "λ¬΄μ •ν˜•/κ²°μ •ν˜• μ „ν™˜", "μ„±λΆ„ 뢄리", "λ―Έμ„Έ μž…μž ν˜•μ„±/λΆ„ν•΄",
@@ -226,7 +217,6 @@ physical_transformation_categories = {
226
  "건쑰/슡윀", "팽윀/μˆ˜μΆ•", "동결/해동", "풍화/침식", "μΆ©μ „/λ°©μ „",
227
  "κ²°ν•©/뢄리", "발효/λΆ€νŒ¨"
228
  ],
229
-
230
  "μ›€μ§μž„ νŠΉμ„± λ³€ν™”": [
231
  "가속/감속", "일정 속도 μœ μ§€", "진동/진동 κ°μ†Œ", "λΆ€λ”ͺ힘/νŠ•κΉ€",
232
  "νšŒμ „ 속도 증가/κ°μ†Œ", "νšŒμ „ λ°©ν–₯ λ³€ν™”", "λΆˆκ·œμΉ™ μ›€μ§μž„", "λ©ˆμ·„λ‹€ λ―Έλ„λŸ¬μ§€λŠ” ν˜„μƒ",
@@ -273,53 +263,138 @@ physical_transformation_categories = {
273
  "진동 νŒ¨ν„΄ λ³€ν™”", "타악 효과", "음ν–₯ ν”Όλ“œλ°±", "음ν–₯ 차폐/증폭",
274
  "μ†Œλ¦¬ μ§€ν–₯μ„±", "음ν–₯ μ™œκ³‘", "λΉ„νŠΈ 생성", "ν•˜λͺ¨λ‹‰μŠ€ 생성", "주파수 λ³€μ‘°",
275
  "음ν–₯ 좩격파", "음ν–₯ 필터링"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  ],
277
- "μ—΄ κ΄€λ ¨ λ³€ν™”": [
278
- "μ˜¨λ„ μƒμŠΉ/ν•˜κ°•", "열에 μ˜ν•œ 팽창/μˆ˜μΆ•", "μ—΄ 전달/차단", "μ••λ ₯ μƒμŠΉ/ν•˜κ°•",
279
- "μ—΄ 변화에 λ”°λ₯Έ μžν™”", "λ¬΄μ§ˆμ„œλ„ λ³€ν™”", "μ—΄μ „κΈ° ν˜„μƒ", "자기μž₯에 μ˜ν•œ μ—΄ λ³€ν™”",
280
- "μƒνƒœλ³€ν™” 쀑 μ—΄ μ €μž₯/방좜", "μ—΄ 슀트레슀 λ°œμƒ/ν•΄μ†Œ", "κΈ‰κ²©ν•œ μ˜¨λ„ λ³€ν™” 영ν–₯",
281
- "볡사열에 μ˜ν•œ 냉각/κ°€μ—΄", "λ°œμ—΄/흑열", "μ—΄ 뢄포 λ³€ν™”", "μ—΄ λ°˜μ‚¬/흑수",
282
- "냉각 응좕", "μ—΄ ν™œμ„±ν™”", "μ—΄ 변색", "μ—΄ 팽창 κ³„μˆ˜ λ³€ν™”", "μ—΄ μ•ˆμ •μ„± λ³€ν™”",
283
- "λ‚΄μ—΄μ„±/λ‚΄ν•œμ„±", "μžκΈ°λ°œμ—΄", "열적 ν‰ν˜•/λΆˆκ· ν˜•", "열적 λ³€ν˜•", "μ—΄ λΆ„μ‚°/집쀑"
284
  ],
285
- "μ „κΈ° 및 자기 λ³€ν™”": [
286
- "μžμ„± 생성/μ†Œλ©Έ", "μ „ν•˜λŸ‰ 증가/κ°μ†Œ", "μ „κΈ°μž₯ 생성/μ†Œλ©Έ", "자기μž₯ 생성/μ†Œλ©Έ",
287
- "μ΄ˆμ „λ„ μƒνƒœ μ „ν™˜", "κ°•μœ μ „μ²΄ νŠΉμ„± λ³€ν™”", "μ–‘μž μƒνƒœ λ³€ν™”", "ν”ŒλΌμ¦ˆλ§ˆ μƒνƒœ ν˜•μ„±/μ†Œλ©Έ",
288
- "μŠ€ν•€νŒŒ 전달", "빛에 μ˜ν•œ μ „κΈ° λ°œμƒ", "μ••λ ₯에 μ˜ν•œ μ „κΈ° λ°œμƒ", "자기μž₯ 속 μ „λ₯˜ λ³€ν™”",
289
- "μ „κΈ° μ €ν•­ λ³€ν™”", "μ „κΈ° 전도성 λ³€ν™”", "μ •μ „κΈ° λ°œμƒ/λ°©μ „", "μ „μžκΈ° μœ λ„",
290
- "μ „μžκΈ°νŒŒ 방좜/흑수", "μ „κΈ° μš©λŸ‰ λ³€ν™”", "자기 이λ ₯ ν˜„μƒ", "전기적 λΆ„κ·Ή",
291
- "μ „μž 흐름 λ°©ν–₯ λ³€ν™”", "전기적 곡λͺ…", "전기적 차폐/λ…ΈμΆœ", "자기 차폐/λ…ΈμΆœ",
292
- "자기μž₯ λ°©ν–₯ μ •λ ¬"
293
  ],
294
- "화학적 λ³€ν™”": [
295
- "ν‘œλ©΄ μ½”νŒ… λ³€ν™”", "물질 μ„±λΆ„ λ³€ν™”", "ν™”ν•™ λ°˜μ‘ λ³€ν™”", "촉맀 μž‘μš© μ‹œμž‘/쀑단",
296
- "빛에 μ˜ν•œ ν™”ν•™ λ°˜μ‘", "전기에 μ˜ν•œ ν™”ν•™ λ°˜μ‘", "λ‹¨λΆ„μžλ§‰ ν˜•μ„±", "λΆ„μž μˆ˜μ€€ 계산 λ³€ν™”",
297
- "μžμ—° λͺ¨λ°© ν‘œλ©΄ λ³€ν™”", "ν™˜κ²½ λ°˜μ‘ν˜• 물질 λ³€ν™”", "주기적 ν™”ν•™ λ°˜μ‘", "μ‚°ν™”", "ν™˜μ›",
298
- "κ³ λΆ„μžν™”", "λ¬Ό λΆ„ν•΄", "ν™”ν•©", "방사선 영ν–₯", "μ‚°-μ—ΌκΈ° λ°˜μ‘", "쀑화 λ°˜μ‘",
299
- "μ΄μ˜¨ν™”", "화학적 흑착/νƒˆμ°©", "촉맀 효율 λ³€ν™”", "νš¨μ†Œ ν™œμ„± λ³€ν™”", "λ°œμƒ‰ λ°˜μ‘",
300
- "pH λ³€ν™”", "화학적 ν‰ν˜• 이동", "κ²°ν•© ν˜•μ„±/λΆ„ν•΄", "μš©ν•΄λ„ λ³€ν™”"
301
  ],
302
-
303
- "생물학적 λ³€ν™”": [
304
- "생μž₯/μœ„μΆ•", "세포 λΆ„μ—΄/사멸", "생물 λ°œκ΄‘", "μ‹ μ§„λŒ€μ‚¬ λ³€ν™”", "λ©΄μ—­ λ°˜μ‘",
305
- "호λ₯΄λͺ¬ λΆ„λΉ„", "μ‹ κ²½ λ°˜μ‘", "μœ μ „μ  λ°œν˜„", "적응/μ§„ν™”", "생체리듬 λ³€ν™”",
306
- "μž¬μƒ/치유", "λ…Έν™”/μ„±μˆ™", "생체 λͺ¨λ°© λ³€ν™”", "λ°”μ΄μ˜€ν•„λ¦„ ν˜•μ„±", "생물학적 λΆ„ν•΄",
307
- "νš¨μ†Œ ν™œμ„±ν™”/λΉ„ν™œμ„±ν™”", "생물학적 μ‹ ν˜Έ 전달", "슀트레슀 λ°˜μ‘", "체온 쑰절",
308
- "생물학적 μ‹œκ³„ λ³€ν™”", "세포외 기질 λ³€ν™”", "생체 역학적 λ°˜μ‘", "세포 μš΄λ™μ„±",
309
- "세포 κ·Ήμ„± λ³€ν™”", "μ˜μ–‘ μƒνƒœ λ³€ν™”"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  ],
311
- "ν™˜κ²½ μƒν˜Έμž‘μš©": [
312
- "μ˜¨λ„ λ°˜μ‘", "μŠ΅λ„ λ°˜μ‘", "κΈ°μ•• λ°˜μ‘", "쀑λ ₯ λ°˜μ‘", "자기μž₯ λ°˜μ‘",
313
- "λΉ› λ°˜μ‘", "μ†Œλ¦¬ λ°˜μ‘", "ν™”ν•™ 물질 감지", "기계적 자극 감지", "μ „κΈ° 자극 λ°˜μ‘",
314
- "방사선 λ°˜μ‘", "진동 감지", "pH λ°˜μ‘", "용맀 λ°˜μ‘", "기체 κ΅ν™˜",
315
- "ν™˜κ²½ μ˜€μ—Ό λ°˜μ‘", "날씨 λ°˜μ‘", "κ³„μ ˆ λ³€ν™” λ°˜μ‘", "일주기 λ°˜μ‘", "μƒνƒœκ³„ μƒν˜Έμž‘μš©",
316
- "곡생/경쟁 λ°˜μ‘", "포식/피식 관계", "κ΅°μ§‘ ν˜•μ„±", "μ˜μ—­ μ„€μ •", "이주/μ •μ°© νŒ¨ν„΄"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  ]
318
-
319
  }
320
 
321
  ##############################################################################
322
- # Gemini API 호좜 ν•¨μˆ˜
323
  ##############################################################################
324
  def query_gemini_api(prompt):
325
  try:
@@ -349,7 +424,7 @@ def query_gemini_api(prompt):
349
  return f"An error occurred while calling the API: {str(e)}"
350
 
351
  ##############################################################################
352
- # μ„€λͺ… ν™•μž₯ ν•¨μˆ˜ (LLM 이용)
353
  ##############################################################################
354
  def enhance_with_llm(base_description, obj_name, category):
355
  prompt = f"""
@@ -362,101 +437,129 @@ def enhance_with_llm(base_description, obj_name, category):
362
  """
363
  return query_gemini_api(prompt)
364
 
 
 
 
 
 
 
 
 
 
 
 
365
  ##############################################################################
366
- # 각 객체수(1, 2, 3)에 λ”°λ₯Έ λ³€ν˜• 아이디어 생성
367
  ##############################################################################
368
- def generate_single_object_transformation_for_category(obj, selected_category):
369
- transformations = physical_transformation_categories.get(selected_category)
370
  if not transformations:
371
  return {}
372
  transformation = choose_alternative(random.choice(transformations))
373
- base_description = f"{obj}이(κ°€) {transformation} ν˜„μƒμ„ 보인닀"
 
 
 
374
  return {selected_category: {"base": base_description, "enhanced": None}}
375
 
376
- def generate_two_objects_interaction_for_category(obj1, obj2, selected_category):
377
- transformations = physical_transformation_categories.get(selected_category)
378
  if not transformations:
379
  return {}
380
  transformation = choose_alternative(random.choice(transformations))
381
- template = random.choice([
382
- "{obj1}이(κ°€) {obj2}에 κ²°ν•©ν•˜μ—¬ {change}κ°€ λ°œμƒν–ˆλ‹€",
383
- "{obj1}κ³Ό(와) {obj2}이(κ°€) μΆ©λŒν•˜λ©΄μ„œ {change}κ°€ 일어났닀"
384
- ])
 
 
 
 
 
 
385
  base_description = template.format(obj1=obj1, obj2=obj2, change=transformation)
386
  return {selected_category: {"base": base_description, "enhanced": None}}
387
 
388
- def generate_three_objects_interaction_for_category(obj1, obj2, obj3, selected_category):
389
- transformations = physical_transformation_categories.get(selected_category)
390
  if not transformations:
391
  return {}
392
  transformation = choose_alternative(random.choice(transformations))
393
- template = random.choice([
394
- "{obj1}, {obj2}, {obj3}이(κ°€) μ‚Όκ°ν˜• ꡬ쑰둜 κ²°ν•©ν•˜μ—¬ {change}κ°€ λ°œμƒν–ˆλ‹€",
395
- "{obj1}이(κ°€) {obj2}와(κ³Ό) {obj3} μ‚¬μ΄μ—μ„œ 맀개체 역할을 ν•˜λ©° {change}λ₯Ό μ΄‰μ§„ν–ˆλ‹€"
396
- ])
 
 
 
 
 
 
397
  base_description = template.format(obj1=obj1, obj2=obj2, obj3=obj3, change=transformation)
398
  return {selected_category: {"base": base_description, "enhanced": None}}
399
 
400
- ##############################################################################
401
- # μƒμ„±λœ κΈ°λ³Έ μ„€λͺ…을 LLM을 톡해 ν™•μž₯ (각 μΉ΄ν…Œκ³ λ¦¬λ³„)
402
- ##############################################################################
403
- def enhance_descriptions(results, objects):
404
- obj_name = " 및 ".join([obj for obj in objects if obj])
405
  for category, result in results.items():
406
- result["enhanced"] = enhance_with_llm(result["base"], obj_name, category)
 
 
 
407
  return results
408
 
409
- ##############################################################################
410
- # μ‚¬μš©μž μž…λ ₯(μ΅œλŒ€ 3개 ν‚€μ›Œλ“œ) + 선택 μΉ΄ν…Œκ³ λ¦¬ β†’ λ³€ν™” 아이디어 생성
411
- ##############################################################################
412
- def generate_transformations(text1, text2, text3, selected_category):
413
  if text2 and text3:
414
- results = generate_three_objects_interaction_for_category(text1, text2, text3, selected_category)
415
  objects = [text1, text2, text3]
416
  elif text2:
417
- results = generate_two_objects_interaction_for_category(text1, text2, selected_category)
418
  objects = [text1, text2]
419
  else:
420
- results = generate_single_object_transformation_for_category(text1, selected_category)
421
  objects = [text1]
422
- return enhance_descriptions(results, objects)
423
 
424
- ##############################################################################
425
- # κ²°κ³Ό ν¬λ§·νŒ…
426
- ##############################################################################
427
- def format_results(results):
428
  formatted = ""
429
- for category, result in results.items():
430
- formatted += f"## {category}\n**κΈ°λ³Έ 아이디어**: {result['base']}\n\n**ν™•μž₯된 아이디어**: {result['enhanced']}\n\n---\n\n"
 
 
 
 
431
  return formatted
432
 
433
- ##############################################################################
434
- # Gradio UIμ—μ„œ 호좜될 ν•¨μˆ˜ (ν…μŠ€νŠΈ μ•„μ΄λ””μ–΄λ§Œ 생성)
435
- ##############################################################################
436
- def process_inputs(text1, text2, text3, selected_category, progress=gr.Progress()):
437
  text1 = text1.strip() if text1 else None
438
  text2 = text2.strip() if text2 else None
439
  text3 = text3.strip() if text3 else None
440
 
441
  if not text1:
442
- return "였λ₯˜: μ΅œμ†Œ ν•˜λ‚˜μ˜ ν‚€μ›Œλ“œλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”."
443
 
444
- progress(0.05, desc="아이디어 생성 μ€€λΉ„ 쀑...")
445
- time.sleep(0.3)
446
- progress(0.1, desc="창의적인 아이디어 생성 μ‹œμž‘...")
 
 
 
 
 
447
 
448
- results = generate_transformations(text1, text2, text3, selected_category)
449
 
450
- progress(0.8, desc="κ²°κ³Ό ν¬λ§·νŒ… 쀑...")
451
- formatted = format_results(results)
452
- progress(1.0, desc="μ™„λ£Œ!")
 
 
 
 
 
453
  return formatted
454
 
455
- ##############################################################################
456
- # 아이디어와 이미지λ₯Ό ν•¨κ»˜ μƒμ„±ν•˜λŠ” μ΅œμ’… ν•¨μˆ˜
457
- ##############################################################################
458
- def process_all(text1, text2, text3, selected_category, progress=gr.Progress()):
459
- idea_result = process_inputs(text1, text2, text3, selected_category, progress)
460
  image_result = generate_design_image(
461
  idea_result,
462
  seed=42,
@@ -468,18 +571,19 @@ def process_all(text1, text2, text3, selected_category, progress=gr.Progress()):
468
  return idea_result, image_result
469
 
470
  ##############################################################################
471
- # API ν‚€ κ²½κ³  λ©”μ‹œμ§€
472
  ##############################################################################
473
- def get_warning_message():
474
  if not GEMINI_API_KEY:
475
- return "⚠️ ν™˜κ²½ λ³€μˆ˜ GEMINI_API_KEYκ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. Gemini API ν‚€λ₯Ό μ„€μ •ν•˜μ„Έμš”."
476
  return ""
477
 
 
478
  ##############################################################################
479
- # Gradio UI
480
  ##############################################################################
481
  with gr.Blocks(
482
- title="ν‚€μ›Œλ“œ 기반 창의적 λ³€ν™” 아이디어 및 λ””μžμΈ 생성기",
483
  theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")
484
  ) as demo:
485
 
@@ -521,73 +625,144 @@ with gr.Blocks(
521
  </style>
522
  """)
523
 
524
- gr.Markdown("# πŸš€ 아이디어 트랜슀포머")
525
- gr.Markdown("μž…λ ₯ν•œ **ν‚€μ›Œλ“œ**(μ΅œλŒ€ 3개)와 **μΉ΄ν…Œκ³ λ¦¬**λ₯Ό λ°”νƒ•μœΌλ‘œ, 창의적인 λͺ¨λΈ/컨셉/ν˜•μƒ λ³€ν™” 아이디어λ₯Ό μƒμ„±ν•˜κ³ , ν•΄λ‹Ή ν™•μž₯ 아이디어λ₯Ό ν”„λ‘¬ν”„νŠΈλ‘œ ν•˜μ—¬ λ””μžμΈ 이미지λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.")
526
-
527
- warning = gr.Markdown(get_warning_message())
528
-
529
- with gr.Row():
530
- with gr.Column(scale=1):
531
- text_input1 = gr.Textbox(label="ν‚€μ›Œλ“œ 1 (ν•„μˆ˜)", placeholder="예: 슀마트폰")
532
- text_input2 = gr.Textbox(label="ν‚€μ›Œλ“œ 2 (선택)", placeholder="예: 인곡지λŠ₯")
533
- text_input3 = gr.Textbox(label="ν‚€μ›Œλ“œ 3 (선택)", placeholder="예: ν—¬μŠ€μΌ€μ–΄")
534
- category_radio = gr.Radio(
535
- label="μΉ΄ν…Œκ³ λ¦¬ 선택",
536
- choices=list(physical_transformation_categories.keys()),
537
- value=list(physical_transformation_categories.keys())[0],
538
- info="좜λ ₯ν•  μΉ΄ν…Œκ³ λ¦¬λ₯Ό μ„ νƒν•˜μ„Έμš”."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  )
540
- status_msg = gr.Markdown("πŸ’‘ '아이디어 μƒμ„±ν•˜κΈ°' λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ μ„ νƒν•œ μΉ΄ν…Œκ³ λ¦¬μ— ν•΄λ‹Ήν•˜λŠ” 아이디어와 λ””μžμΈ 이미지가 μƒμ„±λ©λ‹ˆλ‹€.")
541
 
542
- processing_indicator = gr.HTML("""
543
- <div style="display: flex; justify-content: center; align-items: center; margin: 10px 0;">
544
- <div style="border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite;"></div>
545
- <p style="margin-left: 10px; font-weight: bold; color: #3498db;">처리 μ€‘μž…λ‹ˆλ‹€...</p>
546
- </div>
547
- <style>
548
- @keyframes spin {
549
- 0% { transform: rotate(0deg); }
550
- 100% { transform: rotate(360deg); }
551
- }
552
- </style>
553
- """, visible=False)
554
 
555
- submit_button = gr.Button("아이디어 μƒμ„±ν•˜κΈ°", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
556
 
557
- with gr.Column(scale=2):
558
- idea_output = gr.Markdown(label="아이디어 κ²°κ³Ό")
559
- generated_image = gr.Image(label="μƒμ„±λœ λ””μžμΈ 이미지", type="pil")
560
-
561
- gr.Examples(
562
- examples=[
563
- ["슀마트폰", "", "", "μ„Όμ„œ κΈ°λŠ₯"],
564
- ["μžλ™μ°¨", "", "", "크기와 ν˜•νƒœ λ³€ν™”"],
565
- ["μžλ™μ°¨", "인곡지λŠ₯", "", "ν‘œλ©΄ 및 μ™Έκ΄€ λ³€ν™”"],
566
- ["λ“œλ‘ ", "인곡지λŠ₯", "", "물질의 μƒνƒœ λ³€ν™”"],
567
- ["μš΄λ™ν™”", "μ›¨μ–΄λŸ¬λΈ”", "건강", "ꡬ쑰적 λ³€ν™”"],
568
- ],
569
- inputs=[text_input1, text_input2, text_input3, category_radio],
570
- )
571
-
572
- def show_processing_indicator():
573
- return gr.update(visible=True)
574
-
575
- def hide_processing_indicator():
576
- return gr.update(visible=False)
577
-
578
- submit_button.click(
579
- fn=show_processing_indicator,
580
- inputs=None,
581
- outputs=processing_indicator
582
- ).then(
583
- fn=process_all,
584
- inputs=[text_input1, text_input2, text_input3, category_radio],
585
- outputs=[idea_output, generated_image]
586
- ).then(
587
- fn=hide_processing_indicator,
588
- inputs=None,
589
- outputs=processing_indicator
590
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
 
592
  if __name__ == "__main__":
593
  demo.launch(debug=True)
 
12
  import re
13
 
14
  ##############################################################################
15
+ # 1) ZeroGPU Environment Setup + Device and Dtype Configuration
16
  ##############################################################################
17
  try:
18
  import zerogpu
 
34
  print(f"Using device: {device}, dtype: {dtype}")
35
 
36
  ##############################################################################
37
+ # 2) Load Models: Translation Model, Diffusion Pipeline
38
  ##############################################################################
39
  try:
40
  translator = hf_pipeline(
 
71
  MAX_IMAGE_SIZE = 2048
72
 
73
  ##############################################################################
74
+ # Korean detection and input text cleaning functions
75
  ##############################################################################
76
  def contains_korean(text):
77
  for char in text:
 
79
  return True
80
  return False
81
 
 
 
 
82
  def clean_input_text(text):
83
  """
84
+ Allows only Korean, English, numbers, whitespace and common punctuation marks.
85
+ Adjust allowed characters as needed.
86
  """
87
  allowed = re.compile(r'[^γ„±-γ…Žκ°€-힣a-zA-Z0-9\s\.\,\!\?\-\:\;\'\"]')
88
  cleaned_text = allowed.sub('', text)
89
  return cleaned_text
90
 
 
 
 
91
  def log_unexpected_characters(text):
92
  allowed = re.compile(r'[γ„±-γ…Žκ°€-힣a-zA-Z0-9\s\.\,\!\?\-\:\;\'\"]')
93
  unexpected_chars = [char for char in text if not allowed.match(char)]
94
  if unexpected_chars:
95
+ print("Unexpected characters found:", set(unexpected_chars))
96
  else:
97
+ print("No unexpected characters in the input text.")
98
 
99
  ##############################################################################
100
+ # Image Generation Function
101
  ##############################################################################
102
  def generate_design_image(prompt, seed=42, randomize_seed=True, width=1024, height=1024, num_inference_steps=4):
103
  original_prompt = prompt
104
  translated = False
105
 
106
+ # Clean the input text
107
  prompt = clean_input_text(prompt)
108
 
109
+ # Pre-process: if input is too long, trim to 1000 characters
110
  if len(prompt) > 1000:
111
  prompt = prompt[:1000]
112
 
113
  if contains_korean(prompt):
114
+ # When calling translation, add max_length and truncation options to avoid length issues
115
  translation = translator(prompt, max_length=400, truncation=True)
116
  prompt = translation[0]['translation_text']
117
  translated = True
 
132
 
133
  return image
134
 
 
135
  ##############################################################################
136
+ # Logging Setup
137
  ##############################################################################
138
  logging.basicConfig(
139
  level=logging.INFO,
 
146
  logger = logging.getLogger("idea_generator")
147
 
148
  ##############################################################################
149
+ # Gemini API Key
150
  ##############################################################################
151
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
152
  genai.configure(api_key=GEMINI_API_KEY)
153
 
154
  ##############################################################################
155
+ # Optional Transformation Choice Function
156
  ##############################################################################
157
  def choose_alternative(transformation):
158
  if "/" not in transformation:
 
176
  return random.choice([left, right])
177
 
178
  ##############################################################################
179
+ # Transformation Categories Dictionaries
180
  ##############################################################################
181
+ # Korean version
182
  physical_transformation_categories = {
183
  "μ„Όμ„œ κΈ°λŠ₯": [
184
  "μ‹œκ° μ„Όμ„œ/감지", "청각 μ„Όμ„œ/감지", "촉각 μ„Όμ„œ/감지", "미각 μ„Όμ„œ/감지", "후각 μ„Όμ„œ/감지",
 
208
  "광택/윀기 λ³€ν™”", "색쑰/채도 λ³€ν™”", "λ°œκ΄‘/ν˜•κ΄‘", "λΉ› μ‚°λž€ 효과",
209
  "λΉ› 흑수 λ³€ν™”", "반투λͺ… 효과", "그림자 효과 λ³€ν™”", "μžμ™Έμ„  λ°˜μ‘ λ³€ν™”",
210
  "μ•Όκ΄‘ 효과"
211
+ ],
 
 
 
212
  "물질의 μƒνƒœ λ³€ν™”": [
213
  "고체/앑체/기체 μ „ν™˜", "κ²°μ •ν™”/μš©ν•΄", "μ‚°ν™”/뢀식", "딱딱해짐/λΆ€λ“œλŸ¬μ›Œμ§",
214
  "특수 μƒνƒœ μ „ν™˜", "λ¬΄μ •ν˜•/κ²°μ •ν˜• μ „ν™˜", "μ„±λΆ„ 뢄리", "λ―Έμ„Έ μž…μž ν˜•μ„±/λΆ„ν•΄",
 
217
  "건쑰/슡윀", "팽윀/μˆ˜μΆ•", "동결/해동", "풍화/침식", "μΆ©μ „/λ°©μ „",
218
  "κ²°ν•©/뢄리", "발효/λΆ€νŒ¨"
219
  ],
 
220
  "μ›€μ§μž„ νŠΉμ„± λ³€ν™”": [
221
  "가속/감속", "일정 속도 μœ μ§€", "진동/진동 κ°μ†Œ", "λΆ€λ”ͺ힘/νŠ•κΉ€",
222
  "νšŒμ „ 속도 증가/κ°μ†Œ", "νšŒμ „ λ°©ν–₯ λ³€ν™”", "λΆˆκ·œμΉ™ μ›€μ§μž„", "λ©ˆμ·„λ‹€ λ―Έλ„λŸ¬μ§€λŠ” ν˜„μƒ",
 
263
  "진동 νŒ¨ν„΄ λ³€ν™”", "타악 효과", "음ν–₯ ν”Όλ“œλ°±", "음ν–₯ 차폐/증폭",
264
  "μ†Œλ¦¬ μ§€ν–₯μ„±", "음ν–₯ μ™œκ³‘", "λΉ„νŠΈ 생성", "ν•˜λͺ¨λ‹‰μŠ€ 생성", "주파수 λ³€μ‘°",
265
  "음ν–₯ 좩격파", "음ν–₯ 필터링"
266
+ ]
267
+ }
268
+
269
+ # English version
270
+ physical_transformation_categories_en = {
271
+ "Sensor Functions": [
272
+ "Visual sensor/detection", "Auditory sensor/detection", "Tactile sensor/detection", "Taste sensor/detection", "Olfactory sensor/detection",
273
+ "Temperature sensor/detection", "Humidity sensor/detection", "Pressure sensor/detection", "Acceleration sensor/detection", "Rotational sensor/detection",
274
+ "Proximity sensor/detection", "Position sensor/detection", "Motion sensor/detection", "Gas sensor/detection", "Infrared sensor/detection",
275
+ "Ultraviolet sensor/detection", "Radiation sensor/detection", "Magnetic sensor/detection", "Electric field sensor/detection", "Chemical sensor/detection",
276
+ "Biosignal sensor/detection", "Vibration sensor/detection", "Noise sensor/detection", "Light intensity sensor/detection", "Light wavelength sensor/detection",
277
+ "Tilt sensor/detection", "pH sensor/detection", "Current sensor/detection", "Voltage sensor/detection", "Image sensor/detection",
278
+ "Distance sensor/detection", "Depth sensor/detection", "Gravity sensor/detection", "Speed sensor/detection", "Flow sensor/detection",
279
+ "Water level sensor/detection", "Turbidity sensor/detection", "Salinity sensor/detection", "Metal detection", "Piezoelectric sensor/detection",
280
+ "Photovoltaic sensor/detection", "Thermocouple sensor/detection", "Hall effect sensor/detection", "Ultrasonic sensor/detection", "Radar sensor/detection",
281
+ "Lidar sensor/detection", "Touch sensor/detection", "Gesture sensor/detection", "Heart rate sensor/detection", "Blood pressure sensor/detection"
282
  ],
283
+ "Size and Shape Change": [
284
+ "Volume increase/decrease", "Length increase/decrease", "Width increase/decrease", "Height increase/decrease",
285
+ "Density change", "Weight increase/decrease", "Shape deformation", "State change", "Uneven deformation",
286
+ "Complex shape deformation", "Twisting/entwining", "Non-uniform expansion/contraction", "Rounded/sharpened edges",
287
+ "Cracking/splitting", "Fragmentation", "Water resistance", "Dust resistance", "Denting/recovery",
288
+ "Folding/unfolding", "Compression/expansion", "Stretching/contraction", "Wrinkling/flattening", "Crushing/hardening",
289
+ "Rolling/unrolling", "Bending/curving"
290
  ],
291
+ "Surface and Appearance Change": [
292
+ "Color change", "Texture change", "Transparency change", "Glossy/matte change",
293
+ "Light reflection variation", "Pattern change", "Angle-dependent color change", "Light-induced color change",
294
+ "Temperature-dependent color change", "Holographic effect", "Angle-specific light reflection", "Surface shape alteration",
295
+ "Nano-scale surface structure change", "Self-cleaning effect", "Stain/pattern formation", "Blurriness/clarity change",
296
+ "Luster/shine change", "Hue/saturation change", "Luminescence/fluorescence", "Light scattering effect",
297
+ "Light absorption change", "Translucency effect", "Shadow effect change", "UV response change",
298
+ "Glow effect"
299
  ],
300
+ "Material State Change": [
301
+ "Solid/liquid/gas transition", "Crystallization/dissolution", "Oxidation/corrosion", "Hardening/softening",
302
+ "Special state transition", "Amorphous/crystalline transition", "Component separation", "Particle formation/disintegration",
303
+ "Gel formation/dissolution", "Metastable state change", "Molecular self-assembly/disintegration", "Delayed state change",
304
+ "Melting", "Solidification", "Evaporation/condensation", "Sublimation/deposition", "Precipitation/suspension", "Dispersion/aggregation",
305
+ "Drying/moistening", "Swelling/shrinkage", "Freezing/thawing", "Weathering/erosion", "Charging/discharging",
306
+ "Bonding/separation", "Fermentation/decay"
307
  ],
308
+ "Movement Characteristics Change": [
309
+ "Acceleration/deceleration", "Maintaining constant speed", "Vibration/vibration reduction", "Collision/bouncing",
310
+ "Increase/decrease in rotational speed", "Change in rotational direction", "Irregular movement", "Stop-and-slide phenomenon",
311
+ "Resonance/anti-resonance", "Resistance/lift change in fluid", "Change in movement resistance", "Complex vibrational movement",
312
+ "Movement in special fluid", "Rotational-translational movement", "Inertial stoppage", "Shock absorption",
313
+ "Shock transfer", "Conservation of momentum", "Friction change", "Overcoming inertia", "Unstable equilibrium",
314
+ "Dynamic stability", "Damping of oscillation", "Path predictability", "Evasive movement"
315
+ ],
316
+ "Structural Change": [
317
+ "Addition/removal of components", "Assembly/disassembly", "Folding/unfolding", "Deformation/recovery", "Optimal structural change",
318
+ "Self-rearrangement", "Natural pattern formation/disappearance", "Regular pattern change", "Modular transformation",
319
+ "Increased structural complexity", "Memory of original shape effect", "Shape change over time", "Partial removal",
320
+ "Partial replacement", "Bonding", "Separation", "Division/integration", "Overlaying", "Internal structure change",
321
+ "External structure change", "Shift of center axis", "Balance point change", "Hierarchical structure change", "Support structure change",
322
+ "Stress distribution structure", "Shock absorption structure", "Grid/matrix structure change", "Interconnectivity change"
323
+ ],
324
+ "Spatial Movement": [
325
+ "Forward/backward movement", "Left/right movement", "Up/down movement", "Vertical axis rotation (nodding)",
326
+ "Horizontal axis rotation (shaking head)", "Longitudinal axis rotation (tilting sideways)", "Circular motion", "Spiral movement",
327
+ "Slipping due to inertia", "Change of rotation axis", "Irregular rotation", "Shaking movement", "Parabolic motion",
328
+ "Zero-gravity floating", "Floating on water surface", "Jump/leap", "Sliding", "Rolling", "Free fall",
329
+ "Reciprocating motion", "Elastic bouncing", "Penetration", "Evasive movement", "Zigzag movement", "Swinging movement"
330
+ ],
331
+ "Time-Related Change": [
332
+ "Aging/weathering", "Wear/corrosion", "Fading/discoloration", "Damage/recovery", "Lifecycle change",
333
+ "Adaptation through user interaction", "Learning-based shape optimization", "Property change over time",
334
+ "Collective memory effect", "Cultural significance change", "Delayed response", "History-dependent change",
335
+ "Gradual time change", "Evolutionary change", "Periodic regeneration", "Seasonal adaptation",
336
+ "Circadian rhythm change", "Lifecycle stage", "Growth/decline", "Self-repair/regeneration",
337
+ "Natural cycle adaptation", "Persistence/transience", "Memory effect", "Delayed effect", "Cumulative effect"
338
+ ],
339
+ "Light and Visual Effects": [
340
+ "Illumination/shutdown", "Light transmission/blocking", "Light scattering/concentration", "Color spectrum change", "Light diffraction",
341
+ "Light interference", "Hologram creation", "Laser effect", "Light polarization", "Fluorescence/phosphorescence",
342
+ "UV/IR emission", "Optical illusion", "Light refraction", "Shadow creation/removal",
343
+ "Chromatic aberration", "Rainbow effect", "Glow effect", "Flash effect", "Lighting pattern",
344
+ "Beam effect", "Light filter effect", "Change in light direction", "Projection effect", "Light detection/response",
345
+ "Luminance change"
346
  ],
347
+ "Sound and Vibration Effects": [
348
+ "Sound generation/cessation", "Pitch change", "Volume change", "Timbre change",
349
+ "Resonance/antiresonance", "Acoustic vibration", "Ultrasonic/infrasonic emission", "Sound concentration/distribution",
350
+ "Sound reflection/absorption", "Acoustic Doppler effect", "Sound wave interference", "Acoustic resonance",
351
+ "Vibration pattern change", "Percussive effect", "Audio feedback", "Sound shielding/amplification",
352
+ "Directional sound", "Sound distortion", "Beat generation", "Harmonics generation", "Frequency modulation",
353
+ "Acoustic shockwave", "Sound filtering"
354
+ ],
355
+ "Thermal Changes": [
356
+ "Temperature rise/fall", "Thermal expansion/contraction", "Heat transfer/blocking", "Pressure increase/decrease",
357
+ "Magnetization due to heat change", "Entropy change", "Thermoelectric effect", "Magnetic-induced thermal change",
358
+ "Heat storage/release during phase change", "Thermal stress buildup/release", "Impact of rapid temperature change",
359
+ "Radiative cooling/heating", "Exothermic/endothermic", "Heat distribution change", "Heat reflection/absorption",
360
+ "Cooling condensation", "Thermal activation", "Thermal discoloration", "Coefficient of thermal expansion change", "Thermal stability change",
361
+ "Heat resistance/cold resistance", "Self-heating", "Thermal equilibrium/imbalance", "Thermal deformation", "Heat dispersion/concentration"
362
+ ],
363
+ "Electrical and Magnetic Changes": [
364
+ "Magnetism creation/cessation", "Charge increase/decrease", "Electric field creation/cessation", "Magnetic field creation/cessation",
365
+ "Superconducting transition", "Ferroelectric property change", "Quantum state change", "Plasma formation/cessation",
366
+ "Spin wave transmission", "Electricity generation by light", "Electricity generation by pressure", "Current change in magnetic field",
367
+ "Electrical resistance change", "Electrical conductivity change", "Static electricity generation/discharge", "Electromagnetic induction",
368
+ "Electromagnetic wave emission/absorption", "Capacitance change", "Magnetic hysteresis", "Electrical polarization",
369
+ "Electron flow direction change", "Electrical resonance", "Electrical shielding/exposure", "Magnetic shielding/exposure",
370
+ "Magnetic field alignment"
371
+ ],
372
+ "Chemical Change": [
373
+ "Surface coating change", "Material composition change", "Chemical reaction change", "Catalytic action start/stop",
374
+ "Light-induced chemical reaction", "Electricity-induced chemical reaction", "Monolayer formation", "Molecular-level structural change",
375
+ "Biomimetic surface change", "Environmentally responsive material change", "Periodic chemical reaction", "Oxidation", "Reduction",
376
+ "Polymerization", "Water splitting", "Compound formation", "Radiation effects", "Acid-base reaction", "Neutralization reaction",
377
+ "Ionization", "Chemical adsorption/desorption", "Catalytic efficiency change", "Enzyme activity change", "Colorimetric reaction",
378
+ "pH change", "Chemical equilibrium shift", "Bond formation/breakage", "Solubility change"
379
+ ],
380
+ "Biological Change": [
381
+ "Growth/shrinkage", "Cell division/death", "Bioluminescence", "Metabolic change", "Immune response",
382
+ "Hormone secretion", "Neural response", "Genetic expression", "Adaptation/evolution", "Circadian rhythm change",
383
+ "Regeneration/healing", "Aging/maturation", "Biomimetic change", "Biofilm formation", "Biological degradation",
384
+ "Enzyme activation/inactivation", "Biological signaling", "Stress response", "Thermoregulation", "Biological clock change",
385
+ "Extracellular matrix change", "Biomechanical response", "Cell motility", "Cell polarity change", "Nutritional status change"
386
+ ],
387
+ "Environmental Interaction": [
388
+ "Temperature response", "Humidity response", "Pressure response", "Gravity response", "Magnetic field response",
389
+ "Light response", "Sound response", "Chemical detection", "Mechanical stimulus detection", "Electrical stimulus response",
390
+ "Radiation response", "Vibration detection", "pH response", "Solvent response", "Gas exchange",
391
+ "Pollution response", "Weather response", "Seasonal response", "Circadian response", "Ecosystem interaction",
392
+ "Symbiotic/competitive interaction", "Predator/prey relationship", "Swarm formation", "Territorial behavior", "Migration/settlement pattern"
393
  ]
 
394
  }
395
 
396
  ##############################################################################
397
+ # Gemini API Call Function (Language Independent)
398
  ##############################################################################
399
  def query_gemini_api(prompt):
400
  try:
 
424
  return f"An error occurred while calling the API: {str(e)}"
425
 
426
  ##############################################################################
427
+ # Description Expansion Functions (LLM) - Korean and English Versions
428
  ##############################################################################
429
  def enhance_with_llm(base_description, obj_name, category):
430
  prompt = f"""
 
437
  """
438
  return query_gemini_api(prompt)
439
 
440
+ def enhance_with_llm_en(base_description, obj_name, category):
441
+ prompt = f"""
442
+ Below is a brief description related to '{category}' for '{obj_name}':
443
+ "{base_description}"
444
+ Please expand the above content into a more detailed explanation, focusing on:
445
+ 1) Creative transformation of the model/concept/shape,
446
+ 2) Innovative aspects and functionality,
447
+ in 3-4 sentences.
448
+ """
449
+ return query_gemini_api(prompt)
450
+
451
  ##############################################################################
452
+ # Transformation Idea Generation Functions for Both Languages
453
  ##############################################################################
454
+ def generate_single_object_transformation_for_category_lang(obj, selected_category, categories_dict, lang="ko"):
455
+ transformations = categories_dict.get(selected_category)
456
  if not transformations:
457
  return {}
458
  transformation = choose_alternative(random.choice(transformations))
459
+ if lang == "ko":
460
+ base_description = f"{obj}이(κ°€) {transformation} ν˜„μƒμ„ 보인닀"
461
+ else:
462
+ base_description = f"{obj} exhibits {transformation}"
463
  return {selected_category: {"base": base_description, "enhanced": None}}
464
 
465
+ def generate_two_objects_interaction_for_category_lang(obj1, obj2, selected_category, categories_dict, lang="ko"):
466
+ transformations = categories_dict.get(selected_category)
467
  if not transformations:
468
  return {}
469
  transformation = choose_alternative(random.choice(transformations))
470
+ if lang == "ko":
471
+ template = random.choice([
472
+ "{obj1}이(κ°€) {obj2}에 κ²°ν•©ν•˜μ—¬ {change}κ°€ λ°œμƒν–ˆλ‹€",
473
+ "{obj1}κ³Ό(와) {obj2}이(κ°€) μΆ©λŒν•˜λ©΄μ„œ {change}κ°€ 일어났닀"
474
+ ])
475
+ else:
476
+ template = random.choice([
477
+ "{obj1} combined with {obj2} resulted in {change}",
478
+ "A collision between {obj1} and {obj2} led to {change}"
479
+ ])
480
  base_description = template.format(obj1=obj1, obj2=obj2, change=transformation)
481
  return {selected_category: {"base": base_description, "enhanced": None}}
482
 
483
+ def generate_three_objects_interaction_for_category_lang(obj1, obj2, obj3, selected_category, categories_dict, lang="ko"):
484
+ transformations = categories_dict.get(selected_category)
485
  if not transformations:
486
  return {}
487
  transformation = choose_alternative(random.choice(transformations))
488
+ if lang == "ko":
489
+ template = random.choice([
490
+ "{obj1}, {obj2}, {obj3}이(κ°€) μ‚Όκ°ν˜• ꡬ쑰둜 κ²°ν•©ν•˜μ—¬ {change}κ°€ λ°œμƒν–ˆλ‹€",
491
+ "{obj1}이(κ°€) {obj2}와(κ³Ό) {obj3} μ‚¬μ΄μ—μ„œ 맀개체 역할을 ν•˜λ©° {change}λ₯Ό μ΄‰μ§„ν–ˆλ‹€"
492
+ ])
493
+ else:
494
+ template = random.choice([
495
+ "{obj1}, {obj2}, and {obj3} formed a triangular structure resulting in {change}",
496
+ "{obj1} acted as an intermediary between {obj2} and {obj3}, facilitating {change}"
497
+ ])
498
  base_description = template.format(obj1=obj1, obj2=obj2, obj3=obj3, change=transformation)
499
  return {selected_category: {"base": base_description, "enhanced": None}}
500
 
501
+ def enhance_descriptions_lang(results, objects, lang="ko"):
502
+ obj_name = " 및 ".join([obj for obj in objects if obj]) if lang=="ko" else " and ".join([obj for obj in objects if obj])
 
 
 
503
  for category, result in results.items():
504
+ if lang == "ko":
505
+ result["enhanced"] = enhance_with_llm(result["base"], obj_name, category)
506
+ else:
507
+ result["enhanced"] = enhance_with_llm_en(result["base"], obj_name, category)
508
  return results
509
 
510
+ def generate_transformations_lang(text1, text2, text3, selected_category, categories_dict, lang="ko"):
 
 
 
511
  if text2 and text3:
512
+ results = generate_three_objects_interaction_for_category_lang(text1, text2, text3, selected_category, categories_dict, lang)
513
  objects = [text1, text2, text3]
514
  elif text2:
515
+ results = generate_two_objects_interaction_for_category_lang(text1, text2, selected_category, categories_dict, lang)
516
  objects = [text1, text2]
517
  else:
518
+ results = generate_single_object_transformation_for_category_lang(text1, selected_category, categories_dict, lang)
519
  objects = [text1]
520
+ return enhance_descriptions_lang(results, objects, lang)
521
 
522
+ def format_results_lang(results, lang="ko"):
 
 
 
523
  formatted = ""
524
+ if lang == "ko":
525
+ for category, result in results.items():
526
+ formatted += f"## {category}\n**κΈ°λ³Έ 아이디어**: {result['base']}\n\n**ν™•μž₯된 아이디어**: {result['enhanced']}\n\n---\n\n"
527
+ else:
528
+ for category, result in results.items():
529
+ formatted += f"## {category}\n**Base Idea**: {result['base']}\n\n**Expanded Idea**: {result['enhanced']}\n\n---\n\n"
530
  return formatted
531
 
532
+ def process_inputs_lang(text1, text2, text3, selected_category, categories_dict, lang="ko", progress=gr.Progress()):
 
 
 
533
  text1 = text1.strip() if text1 else None
534
  text2 = text2.strip() if text2 else None
535
  text3 = text3.strip() if text3 else None
536
 
537
  if not text1:
538
+ return "였λ₯˜: μ΅œμ†Œ ν•˜λ‚˜μ˜ ν‚€μ›Œλ“œλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”." if lang=="ko" else "Error: Please enter at least one keyword."
539
 
540
+ if lang == "ko":
541
+ progress(0.05, desc="아이디어 생성 μ€€λΉ„ 쀑...")
542
+ time.sleep(0.3)
543
+ progress(0.1, desc="창의적인 아이디어 생성 μ‹œμž‘...")
544
+ else:
545
+ progress(0.05, desc="Preparing idea generation...")
546
+ time.sleep(0.3)
547
+ progress(0.1, desc="Generating creative idea...")
548
 
549
+ results = generate_transformations_lang(text1, text2, text3, selected_category, categories_dict, lang)
550
 
551
+ if lang == "ko":
552
+ progress(0.8, desc="κ²°κ³Ό ν¬λ§·νŒ… 쀑...")
553
+ formatted = format_results_lang(results, lang)
554
+ progress(1.0, desc="μ™„λ£Œ!")
555
+ else:
556
+ progress(0.8, desc="Formatting results...")
557
+ formatted = format_results_lang(results, lang)
558
+ progress(1.0, desc="Done!")
559
  return formatted
560
 
561
+ def process_all_lang(text1, text2, text3, selected_category, categories_dict, lang="ko", progress=gr.Progress()):
562
+ idea_result = process_inputs_lang(text1, text2, text3, selected_category, categories_dict, lang, progress)
 
 
 
563
  image_result = generate_design_image(
564
  idea_result,
565
  seed=42,
 
571
  return idea_result, image_result
572
 
573
  ##############################################################################
574
+ # Warning Message Function for API Key (Language Specific)
575
  ##############################################################################
576
+ def get_warning_message_lang(lang="ko"):
577
  if not GEMINI_API_KEY:
578
+ 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."
579
  return ""
580
 
581
+
582
  ##############################################################################
583
+ # Gradio UI with Two Tabs: English (Main Home) and Korean
584
  ##############################################################################
585
  with gr.Blocks(
586
+ title="Idea Transformer",
587
  theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")
588
  ) as demo:
589
 
 
625
  </style>
626
  """)
627
 
628
+ with gr.Tabs():
629
+ with gr.Tab(label="English"):
630
+ gr.Markdown("# πŸš€ Idea Transformer")
631
+ 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.")
632
+
633
+ warning_en = gr.Markdown(get_warning_message_lang("en"))
634
+
635
+ with gr.Row():
636
+ with gr.Column(scale=1):
637
+ text_input1_en = gr.Textbox(label="Keyword 1 (required)", placeholder="e.g., Smartphone")
638
+ text_input2_en = gr.Textbox(label="Keyword 2 (optional)", placeholder="e.g., Artificial Intelligence")
639
+ text_input3_en = gr.Textbox(label="Keyword 3 (optional)", placeholder="e.g., Healthcare")
640
+ category_radio_en = gr.Radio(
641
+ label="Select Category",
642
+ choices=list(physical_transformation_categories_en.keys()),
643
+ value=list(physical_transformation_categories_en.keys())[0],
644
+ info="Select a category."
645
+ )
646
+ status_msg_en = gr.Markdown("πŸ’‘ Click the 'Generate Idea' button to create an idea and design image based on the selected category.")
647
+
648
+ processing_indicator_en = gr.HTML("""
649
+ <div style="display: flex; justify-content: center; align-items: center; margin: 10px 0;">
650
+ <div style="border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite;"></div>
651
+ <p style="margin-left: 10px; font-weight: bold; color: #3498db;">Processing...</p>
652
+ </div>
653
+ <style>
654
+ @keyframes spin {
655
+ 0% { transform: rotate(0deg); }
656
+ 100% { transform: rotate(360deg); }
657
+ }
658
+ </style>
659
+ """, visible=False)
660
+
661
+ submit_button_en = gr.Button("Generate Idea", variant="primary")
662
+
663
+ with gr.Column(scale=2):
664
+ idea_output_en = gr.Markdown(label="Idea Output")
665
+ generated_image_en = gr.Image(label="Generated Design Image", type="pil")
666
+
667
+ gr.Examples(
668
+ examples=[
669
+ ["Smartphone", "", "", "Sensor Functions"],
670
+ ["Car", "", "", "Size and Shape Change"],
671
+ ["Car", "Artificial Intelligence", "", "Surface and Appearance Change"],
672
+ ["Drone", "Artificial Intelligence", "", "Material State Change"],
673
+ ["Sneakers", "Wearable", "Health", "Structural Change"],
674
+ ],
675
+ inputs=[text_input1_en, text_input2_en, text_input3_en, category_radio_en],
676
  )
 
677
 
678
+ def show_processing_indicator_en():
679
+ return gr.update(visible=True)
680
+
681
+ def hide_processing_indicator_en():
682
+ return gr.update(visible=False)
 
 
 
 
 
 
 
683
 
684
+ submit_button_en.click(
685
+ fn=show_processing_indicator_en,
686
+ inputs=None,
687
+ outputs=processing_indicator_en
688
+ ).then(
689
+ fn=process_all_lang,
690
+ inputs=[text_input1_en, text_input2_en, text_input3_en, category_radio_en, gr.State(physical_transformation_categories_en), gr.State("en")],
691
+ outputs=[idea_output_en, generated_image_en]
692
+ ).then(
693
+ fn=hide_processing_indicator_en,
694
+ inputs=None,
695
+ outputs=processing_indicator_en
696
+ )
697
 
698
+ with gr.Tab(label="ν•œκ΅­μ–΄"):
699
+ gr.Markdown("# πŸš€ 아이디어 트랜슀포머")
700
+ gr.Markdown("μž…λ ₯ν•œ **ν‚€μ›Œλ“œ**(μ΅œλŒ€ 3개)와 **μΉ΄ν…Œκ³ λ¦¬**λ₯Ό λ°”νƒ•μœΌλ‘œ, 창의적인 λͺ¨λΈ/컨셉/ν˜•μƒ λ³€ν™” 아이디어λ₯Ό μƒμ„±ν•˜κ³ , ν•΄λ‹Ή ν™•μž₯ 아이디어λ₯Ό ν”„λ‘¬ν”„νŠΈλ‘œ ν•˜μ—¬ λ””μžμΈ 이미지λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.")
701
+
702
+ warning_ko = gr.Markdown(get_warning_message_lang("ko"))
703
+
704
+ with gr.Row():
705
+ with gr.Column(scale=1):
706
+ text_input1_ko = gr.Textbox(label="ν‚€μ›Œλ“œ 1 (ν•„μˆ˜)", placeholder="예: 슀마트폰")
707
+ text_input2_ko = gr.Textbox(label="ν‚€μ›Œλ“œ 2 (선택)", placeholder="예: 인곡지λŠ₯")
708
+ text_input3_ko = gr.Textbox(label="ν‚€μ›Œλ“œ 3 (선택)", placeholder="예: ν—¬μŠ€μΌ€μ–΄")
709
+ category_radio_ko = gr.Radio(
710
+ label="μΉ΄ν…Œκ³ λ¦¬ 선택",
711
+ choices=list(physical_transformation_categories.keys()),
712
+ value=list(physical_transformation_categories.keys())[0],
713
+ info="좜λ ₯ν•  μΉ΄ν…Œκ³ λ¦¬λ₯Ό μ„ νƒν•˜μ„Έμš”."
714
+ )
715
+ status_msg_ko = gr.Markdown("πŸ’‘ '아이디어 μƒμ„±ν•˜κΈ°' λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ μ„ νƒν•œ μΉ΄ν…Œκ³ λ¦¬μ— ν•΄λ‹Ήν•˜λŠ” 아이디어와 λ””μžμΈ 이미지가 μƒμ„±λ©λ‹ˆλ‹€.")
716
+
717
+ processing_indicator_ko = gr.HTML("""
718
+ <div style="display: flex; justify-content: center; align-items: center; margin: 10px 0;">
719
+ <div style="border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite;"></div>
720
+ <p style="margin-left: 10px; font-weight: bold; color: #3498db;">처리 μ€‘μž…λ‹ˆλ‹€...</p>
721
+ </div>
722
+ <style>
723
+ @keyframes spin {
724
+ 0% { transform: rotate(0deg); }
725
+ 100% { transform: rotate(360deg); }
726
+ }
727
+ </style>
728
+ """, visible=False)
729
+
730
+ submit_button_ko = gr.Button("아이디어 μƒμ„±ν•˜κΈ°", variant="primary")
731
+
732
+ with gr.Column(scale=2):
733
+ idea_output_ko = gr.Markdown(label="아이디어 κ²°κ³Ό")
734
+ generated_image_ko = gr.Image(label="μƒμ„±λœ λ””μžμΈ 이미지", type="pil")
735
+
736
+ gr.Examples(
737
+ examples=[
738
+ ["슀마트폰", "", "", "μ„Όμ„œ κΈ°λŠ₯"],
739
+ ["μžλ™μ°¨", "", "", "크기와 ν˜•νƒœ λ³€ν™”"],
740
+ ["μžλ™μ°¨", "인곡지λŠ₯", "", "ν‘œλ©΄ 및 μ™Έκ΄€ λ³€ν™”"],
741
+ ["λ“œλ‘ ", "인곡지λŠ₯", "", "물질의 μƒνƒœ λ³€ν™”"],
742
+ ["μš΄λ™ν™”", "μ›¨μ–΄λŸ¬λΈ”", "건강", "ꡬ쑰적 λ³€ν™”"],
743
+ ],
744
+ inputs=[text_input1_ko, text_input2_ko, text_input3_ko, category_radio_ko],
745
+ )
746
+
747
+ def show_processing_indicator_ko():
748
+ return gr.update(visible=True)
749
+
750
+ def hide_processing_indicator_ko():
751
+ return gr.update(visible=False)
752
+
753
+ submit_button_ko.click(
754
+ fn=show_processing_indicator_ko,
755
+ inputs=None,
756
+ outputs=processing_indicator_ko
757
+ ).then(
758
+ fn=process_all_lang,
759
+ inputs=[text_input1_ko, text_input2_ko, text_input3_ko, category_radio_ko, gr.State(physical_transformation_categories), gr.State("ko")],
760
+ outputs=[idea_output_ko, generated_image_ko]
761
+ ).then(
762
+ fn=hide_processing_indicator_ko,
763
+ inputs=None,
764
+ outputs=processing_indicator_ko
765
+ )
766
 
767
  if __name__ == "__main__":
768
  demo.launch(debug=True)