aiqcamp commited on
Commit
edcf253
·
verified ·
1 Parent(s): 70a440f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -183
app.py CHANGED
@@ -5,7 +5,6 @@ import time
5
  import logging
6
  import google.generativeai as genai
7
 
8
- # 로깅 설정
9
  logging.basicConfig(
10
  level=logging.INFO,
11
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
@@ -16,11 +15,10 @@ logging.basicConfig(
16
  )
17
  logger = logging.getLogger("idea_generator")
18
 
19
- # Gemini API 키는 환경 변수 GEMINI_API_KEY에서 가져옵니다.
20
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
21
  genai.configure(api_key=GEMINI_API_KEY)
22
 
23
- # 슬래시("/")가 포함된 변환 문자열에서 두 옵션 중 하나만 선택하는 헬퍼 함수
24
  def choose_alternative(transformation):
25
  if "/" not in transformation:
26
  return transformation
@@ -42,7 +40,7 @@ def choose_alternative(transformation):
42
  else:
43
  return random.choice([left, right])
44
 
45
- # 창의적인 모델/컨셉/형상 변화 아이디어를 위한 카테고리 (기존 '물리적 변화' 사전 유지)
46
  physical_transformation_categories = {
47
  "공간 이동": [
48
  "앞/뒤 이동", "좌/우 이동", "위/아래 이동", "세로축 회전(고개 끄덕임)",
@@ -51,7 +49,6 @@ physical_transformation_categories = {
51
  "무중력 부유", "수면 위 부유", "점프/도약", "슬라이딩", "롤링", "자유 낙하",
52
  "왕복 운동", "탄성 튕김", "관통", "회피 움직임", "지그재그 이동", "스윙 운동"
53
  ],
54
-
55
  "크기와 형태 변화": [
56
  "부피 늘어남/줄어듦", "길이 늘어남/줄어듦", "너비 늘어남/줄어듦", "높이 늘어남/줄어듦",
57
  "밀도 변화", "무게 증가/감소", "모양 변형", "상태 변화", "불균등 변형",
@@ -60,145 +57,18 @@ physical_transformation_categories = {
60
  "접힘/펼쳐짐", "압착/팽창", "늘어남/수축", "구겨짐/평평해짐", "뭉개짐/단단해짐",
61
  "말림/펴짐", "꺾임/구부러짐"
62
  ],
63
-
64
- "표면 외관 변화": [
65
- "색상 변화", "질감 변화", "투명/불투명 변화", "반짝임/무광 변화",
66
- "빛 반사 정도 변화", "무늬 변화", "각도에 따른 색상 변화", "빛에 따른 색상 변화",
67
- "온도에 따른 색상 변화", "홀로그램 효과", "표면 각도별 빛 반사", "표면 모양 변형",
68
- "초미세 표면 구조 변화", "자가 세정 효과", "얼룩/패턴 생성", "흐림/선명함 변화",
69
- "광택/윤기 변화", "색조/채도 변화", "발광/형광", "빛 산란 효과",
70
- "빛 흡수 변화", "반투명 효과", "그림자 효과 변화", "자외선 반응 변화",
71
- "야광 효과"
72
- ],
73
-
74
- "물질의 상태 변화": [
75
- "고체/액체/기체 전환", "결정화/용해", "산화/부식", "딱딱해짐/부드러워짐",
76
- "특수 상태 전환", "무정형/결정형 전환", "성분 분리", "미세 입자 형성/분해",
77
- "젤 형성/풀어짐", "준안정 상태 변화", "분자 자가 정렬/분해", "상태변화 지연 현상",
78
- "녹음", "굳음", "증발/응축", "승화/증착", "침전/부유", "분산/응집",
79
- "건조/습윤", "팽윤/수축", "동결/해동", "풍화/침식", "충전/방전",
80
- "결합/분리", "발효/부패"
81
- ],
82
-
83
- "열 관련 변화": [
84
- "온도 상승/하강", "열에 의한 팽창/수축", "열 전달/차단", "압력 상승/하강",
85
- "열 변화에 따른 자화", "무질서도 변화", "열전기 현상", "자기장에 의한 열 변화",
86
- "상태변화 중 열 저장/방출", "열 스트레스 발생/해소", "급격한 온도 변화 영향",
87
- "복사열에 의한 냉각/가열", "발열/흡열", "열 분포 변화", "열 반사/흡수",
88
- "냉각 응축", "열 활성화", "열 변색", "열 팽창 계수 변화", "열 안정성 변화",
89
- "내열성/내한성", "자기발열", "열적 평형/불균형", "열적 변형", "열 분산/집중"
90
- ],
91
-
92
- "움직임 특성 변화": [
93
- "가속/감속", "일정 속도 유지", "진동/진동 감소", "부딪힘/튕김",
94
- "회전 속도 증가/감소", "회전 방향 변화", "불규칙 움직임", "멈췄다 미끄러지는 현상",
95
- "공진/반공진", "유체 속 저항/양력 변화", "움직임 저항 변화", "복합 진동 움직임",
96
- "특수 유체 속 움직임", "회전-이동 연계 움직임", "관성 정지", "충격 흡수",
97
- "충격 전달", "운동량 보존", "마찰력 변화", "관성 탈출", "불안정 균형",
98
- "동적 안정성", "흔들림 감쇠", "경로 예측성", "회피 움직임"
99
- ],
100
-
101
- "구조적 변화": [
102
- "부품 추가/제거", "조립/분해", "접기/펴기", "변형/원상복구", "최적 구조 변화",
103
- "자가 재배열", "자연 패턴 형성/소멸", "규칙적 패턴 변화", "모듈식 변형",
104
- "복잡성 증가 구조", "원래 모양 기억 효과", "시간에 따른 형태 변화", "부분 제거",
105
- "부분 교체", "결합", "분리", "분할/통합", "중첩/겹침", "내부 구조 변화",
106
- "외부 구조 변화", "중심축 이동", "균형점 변화", "계층 구조 변화", "지지 구조 변화",
107
- "응력 분산 구조", "충격 흡수 구조", "그리드/매트릭스 구조 변화", "상호 연결성 변화"
108
- ],
109
-
110
- "전기 및 자기 변화": [
111
- "자성 생성/소멸", "전하량 증가/감소", "전기장 생성/소멸", "자기장 생성/소멸",
112
- "초전도 상태 전환", "강유전체 특성 변화", "양자 상태 변화", "플라즈마 상태 형성/소멸",
113
- "스핀파 전달", "빛에 의한 전기 발생", "압력에 의한 전기 발생", "자기장 속 전류 변화",
114
- "전기 저항 변화", "전기 전도성 변화", "정전기 발생/방전", "전자기 유도",
115
- "전자기파 방출/흡수", "전기 용량 변화", "자기 이력 현상", "전기적 분극",
116
- "전자 흐름 방향 변화", "전기적 공명", "전기적 차폐/노출", "자기 차폐/노출",
117
- "자기장 방향 정렬"
118
- ],
119
-
120
- "화학적 변화": [
121
- "표면 코팅 변화", "물질 성분 변화", "화학 반응 변화", "촉매 작용 시작/중단",
122
- "빛에 의한 화학 반응", "전기에 의한 화학 반응", "단분자막 형성", "분자 수준 계산 변화",
123
- "자연 모방 표면 변화", "환경 반응형 물질 변화", "주기적 화학 반응", "산화", "환원",
124
- "고분자화", "물 분해", "화합", "방사선 영향", "산-염기 반응", "중화 반응",
125
- "이온화", "화학적 흡착/탈착", "촉매 효율 변화", "효소 활성 변화", "발색 반응",
126
- "pH 변화", "화학적 평형 이동", "결합 형성/분해", "용해도 변화"
127
- ],
128
-
129
- "시간 관련 변화": [
130
- "노화/풍화", "마모/부식", "색 바램/변색", "손상/회복", "수명 주기 변화",
131
- "사용자 상호작용에 따른 적응", "학습 기반 형태 최적화", "시간에 따른 물성 변화",
132
- "집단 기억 효과", "문화적 의미 변화", "지연 반응", "이전 상태 의존 변화",
133
- "점진적 시간 변화", "진화적 변화", "주기적 재생", "계절 변화 적응",
134
- "생체리듬 변화", "생애 주기 단계", "성장/퇴화", "자기 복구/재생",
135
- "자연 순환 적응", "지속성/일시성", "기억 효과", "지연된 작용", "누적 효과"
136
- ],
137
-
138
- "빛과 시각 효과": [
139
- "발광/소등", "빛 투과/차단", "빛 산란/집중", "색상 스펙트럼 변화", "빛 회절",
140
- "빛 간섭", "홀로그램 생성", "레이저 효과", "빛 편광", "형광/인광",
141
- "자외선/적외선 발광", "광학적 착시", "빛 굴절", "그림자 생성/제거",
142
- "색수차 효과", "무지개 효과", "글로우 효과", "플래시 효과", "조명 패턴",
143
- "빔 효과", "광 필터 효과", "빛의 방향성 변화", "투영 효과", "빛 감지/반응",
144
- "광도 변화"
145
- ],
146
-
147
- "소리와 진동 효과": [
148
- "소리 발생/소멸", "소리 높낮이 변화", "소리 크기 변화", "음색 변화",
149
- "공명/반공명", "음향 진동", "초음파/저음파 발생", "음향 집중/분산",
150
- "음향 반사/흡수", "음향 도플러 효과", "음파 간섭", "음향 공진",
151
- "진동 패턴 변화", "타악 효과", "음향 피드백", "음향 차폐/증폭",
152
- "소리 지향성", "음향 왜곡", "비트 생성", "하모닉스 생성", "주파수 변조",
153
- "음향 충격파", "음향 필터링", "음파 전파 패턴", "진동 댐핑"
154
- ],
155
-
156
- "생물학적 변화": [
157
- "생장/위축", "세포 분열/사멸", "생물 발광", "신진대사 변화", "면역 반응",
158
- "호르몬 분비", "신경 반응", "유전적 발현", "적응/진화", "생체리듬 변화",
159
- "재생/치유", "노화/성숙", "생체 모방 변화", "바이오필름 형성", "생물학적 분해",
160
- "효소 활성화/비활성화", "생물학적 신호 전달", "스트레스 반응", "체온 조절",
161
- "생물학적 시계 변화", "세포외 기질 변화", "생체 역학적 반응", "세포 운동성",
162
- "세포 극성 변화", "영양 상태 변화"
163
- ],
164
-
165
- "환경 상호작용": [
166
- "온도 반응", "습도 반응", "기압 반응", "중력 반응", "자기장 반응",
167
- "빛 반응", "소리 반응", "화학 물질 감지", "기계적 자극 감지", "전기 자극 반응",
168
- "방사선 반응", "진동 감지", "pH 반응", "용매 반응", "기체 교환",
169
- "환경 오염 반응", "날씨 반응", "계절 변화 반응", "일주기 반응", "생태계 상호작용",
170
- "공생/경쟁 반응", "포식/피식 관계", "군집 형성", "영역 설정", "이주/정착 패턴"
171
- ],
172
-
173
- "센서 기능": [
174
- "시각 센서/감지", "청각 센서/감지", "촉각 센서/감지", "미각 센서/감지", "후각 센서/감지",
175
- "온도 센서/감지", "습도 센서/감지", "압력 센���/감지", "가속도 센서/감지", "회전 센서/감지",
176
- "근접 센서/감지", "위치 센서/감지", "운동 센서/감지", "가스 센서/감지", "적외선 센서/감지",
177
- "자외선 센서/감지", "방사선 센서/감지", "자기장 센서/감지", "전기장 센서/감지", "화학물질 센서/감지",
178
- "생체신호 센서/감지", "진동 센서/감지", "소음 센서/감지", "빛 세기 센서/감지", "빛 파장 센서/감지",
179
- "기울기 센서/감지", "pH 센서/감지", "전류 센서/감지", "전압 센서/감지", "이미지 센서/감지",
180
- "거리 센서/감지", "깊이 센서/감지", "중력 센서/감지", "속도 센서/감지", "흐름 센서/감지",
181
- "수위 센서/감지", "탁도 센서/감지", "염도 센서/감지", "금속 감지", "압전 센서/감지",
182
- "광전 센서/감지", "열전대 센서/감지", "홀 효과 센서/감지", "초음파 센서/감지", "레이더 센서/감지",
183
- "라이다 센서/감지", "터치 센서/감지", "제스처 센서/감지", "심박 센서/감지", "혈압 센서/감지"
184
- ]
185
  }
186
 
187
- ##############################################################################
188
- # Gemini API 호출 함수 (예: gemini-2.0-flash-thinking-exp-01-21 -> 다른 모델 사용 시 수정)
189
- ##############################################################################
190
  def query_gemini_api(prompt):
191
  try:
192
- # 예시: 기존 gemini-2.0... 대신, 다른 모델이 필요하다면 교체하세요.
193
  model = genai.GenerativeModel('gemini-2.0-flash-thinking-exp-01-21')
194
-
195
  response = model.generate_content(prompt)
196
 
197
- # 응답 구조 방어적으로 처리
198
  try:
199
  if hasattr(response, 'text'):
200
  return response.text
201
-
202
  if hasattr(response, 'candidates') and response.candidates:
203
  if len(response.candidates) > 0:
204
  candidate = response.candidates[0]
@@ -210,27 +80,21 @@ def query_gemini_api(prompt):
210
  if hasattr(response, 'parts') and response.parts:
211
  if len(response.parts) > 0:
212
  return response.parts[0].text
213
-
214
  return "Unable to generate a response. API response structure is different than expected."
215
-
216
  except Exception as inner_e:
217
  logger.error(f"Error processing response: {inner_e}")
218
  return f"An error occurred while processing the response: {str(inner_e)}"
219
-
220
  except Exception as e:
221
  logger.error(f"Error calling Gemini API: {e}")
222
  if "API key not valid" in str(e):
223
  return "API key is not valid. Please check your GEMINI_API_KEY environment variable."
224
  return f"An error occurred while calling the API: {str(e)}"
225
 
226
- ##############################################################################
227
- # 설명 확장 함수: "모델/컨셉/형상의 변화에 대한 이해와 혁신 포인트, 기능성 등을 중심"으로
228
- ##############################################################################
229
  def enhance_with_llm(base_description, obj_name, category):
230
  prompt = f"""
231
  다음은 '{obj_name}'의 '{category}' 관련 간단한 설명입니다:
232
  "{base_description}"
233
-
234
  위 내용을 보다 구체화하여,
235
  1) 창의적인 모델/컨셉/형상의 변화에 대한 이해,
236
  2) 혁신 포인트와 기능성 등을 중심으로
@@ -238,9 +102,7 @@ def enhance_with_llm(base_description, obj_name, category):
238
  """
239
  return query_gemini_api(prompt)
240
 
241
- ##############################################################################
242
- # 단일 키워드(오브젝트)에 대한 "창의적 변화 아이디어" 생성
243
- ##############################################################################
244
  def generate_single_object_transformations(obj):
245
  results = {}
246
  for category, transformations in physical_transformation_categories.items():
@@ -249,9 +111,7 @@ def generate_single_object_transformations(obj):
249
  results[category] = {"base": base_description, "enhanced": None}
250
  return results
251
 
252
- ##############################################################################
253
- # 두 키워드에 대한 "창의적 변화 아이디어" 생성
254
- ##############################################################################
255
  def generate_two_objects_interaction(obj1, obj2):
256
  results = {}
257
  for category, transformations in physical_transformation_categories.items():
@@ -264,9 +124,7 @@ def generate_two_objects_interaction(obj1, obj2):
264
  results[category] = {"base": base_description, "enhanced": None}
265
  return results
266
 
267
- ##############################################################################
268
- # 세 키워드에 대한 "창의적 변화 아이디어" 생성
269
- ##############################################################################
270
  def generate_three_objects_interaction(obj1, obj2, obj3):
271
  results = {}
272
  for category, transformations in physical_transformation_categories.items():
@@ -279,18 +137,14 @@ def generate_three_objects_interaction(obj1, obj2, obj3):
279
  results[category] = {"base": base_description, "enhanced": None}
280
  return results
281
 
282
- ##############################################################################
283
- # 생성된 기본 설명을 LLM을 통해 확장
284
- ##############################################################################
285
  def enhance_descriptions(results, objects):
286
  obj_name = " 및 ".join([obj for obj in objects if obj])
287
  for category, result in results.items():
288
  result["enhanced"] = enhance_with_llm(result["base"], obj_name, category)
289
  return results
290
 
291
- ##############################################################################
292
- # 사용자 입력(최대 3개 키워드)에 따라 창의적 변화 아이디어 생성
293
- ##############################################################################
294
  def generate_transformations(text1, text2=None, text3=None):
295
  if text2 and text3:
296
  results = generate_three_objects_interaction(text1, text2, text3)
@@ -303,53 +157,55 @@ def generate_transformations(text1, text2=None, text3=None):
303
  objects = [text1]
304
  return enhance_descriptions(results, objects)
305
 
306
- ##############################################################################
307
- # 결과 포맷팅
308
- ##############################################################################
309
  def format_results(results):
310
  formatted = ""
311
  for category, result in results.items():
312
  formatted += f"## {category}\n**기본 아이디어**: {result['base']}\n\n**확장된 아이디어**: {result['enhanced']}\n\n---\n\n"
313
  return formatted
314
 
 
315
  ##############################################################################
316
- # Gradio UI에서 호출할 함수
317
  ##############################################################################
318
- def process_inputs(text1, text2, text3):
319
- messages = []
320
- messages.append("입력값 확인 중...")
321
  time.sleep(0.3)
 
322
  text1 = text1.strip() if text1 else None
323
  text2 = text2.strip() if text2 else None
324
  text3 = text3.strip() if text3 else None
325
  if not text1:
326
- messages.append("오류: 최소 하나의 키워드를 입력해주세요.")
327
- return "\n\n".join(messages)
328
 
329
- messages.append("창의적인 모델/컨셉/형상 변화 아이디어 생성 중...")
 
330
  time.sleep(0.3)
 
 
331
  results = generate_transformations(text1, text2, text3)
332
 
333
- messages.append("결과 포맷팅 중...")
 
334
  time.sleep(0.3)
 
 
335
  formatted = format_results(results)
336
 
337
- messages.append("완료!")
338
- messages.append(formatted)
339
 
340
- return "\n\n".join(messages)
 
341
 
342
- ##############################################################################
343
- # API 키 경고 메시지
344
- ##############################################################################
345
  def get_warning_message():
346
  if not GEMINI_API_KEY:
347
  return "⚠️ 환경 변수 GEMINI_API_KEY가 설정되지 않았습니다. Gemini API 키를 설정하세요."
348
  return ""
349
 
350
- ##############################################################################
351
- # Gradio UI
352
- ##############################################################################
353
  with gr.Blocks(title="키워드 기반 창의적 변화 아이디어 생성기",
354
  theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")) as demo:
355
 
@@ -370,7 +226,6 @@ with gr.Blocks(title="키워드 기반 창의적 변화 아이디어 생성기",
370
 
371
  warning = gr.Markdown(get_warning_message())
372
 
373
- # 좌측 입력 영역
374
  with gr.Row():
375
  with gr.Column(scale=1):
376
  text_input1 = gr.Textbox(label="키워드 1 (필수)", placeholder="예: 스마트폰")
@@ -378,12 +233,11 @@ with gr.Blocks(title="키워드 기반 창의적 변화 아이디어 생성기",
378
  text_input3 = gr.Textbox(label="키워드 3 (선택)", placeholder="예: 헬스케어")
379
  submit_button = gr.Button("아이디어 생성하기")
380
 
381
- # 우측 출력 영역 (탭은 하나만 사용)
382
  with gr.Column(scale=2):
383
  with gr.TabItem("창의적인 모델/컨셉/형상 변화 아이디어", id="creative_tab"):
 
384
  idea_output = gr.Markdown(label="아이디어 결과")
385
 
386
- # 예시 입력
387
  gr.Examples(
388
  examples=[
389
  ["스마트폰", "", ""],
@@ -394,10 +248,13 @@ with gr.Blocks(title="키워드 기반 창의적 변화 아이디어 생성기",
394
  inputs=[text_input1, text_input2, text_input3],
395
  )
396
 
397
- # 버튼 이벤트: 번째 탭에만 연결
398
- submit_button.click(fn=process_inputs,
399
- inputs=[text_input1, text_input2, text_input3],
400
- outputs=idea_output)
 
 
 
401
 
402
  if __name__ == "__main__":
403
  demo.launch(debug=True)
 
5
  import logging
6
  import google.generativeai as genai
7
 
 
8
  logging.basicConfig(
9
  level=logging.INFO,
10
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
 
15
  )
16
  logger = logging.getLogger("idea_generator")
17
 
 
18
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
19
  genai.configure(api_key=GEMINI_API_KEY)
20
 
21
+
22
  def choose_alternative(transformation):
23
  if "/" not in transformation:
24
  return transformation
 
40
  else:
41
  return random.choice([left, right])
42
 
43
+
44
  physical_transformation_categories = {
45
  "공간 이동": [
46
  "앞/뒤 이동", "좌/우 이동", "위/아래 이동", "세로축 회전(고개 끄덕임)",
 
49
  "무중력 부유", "수면 위 부유", "점프/도약", "슬라이딩", "롤링", "자유 낙하",
50
  "왕복 운동", "탄성 튕김", "관통", "회피 움직임", "지그재그 이동", "스윙 운동"
51
  ],
 
52
  "크기와 형태 변화": [
53
  "부피 늘어남/줄어듦", "길이 늘어남/줄어듦", "너비 늘어남/줄어듦", "높이 늘어남/줄어듦",
54
  "밀도 변화", "무게 증가/감소", "모양 변형", "상태 변화", "불균등 변형",
 
57
  "접힘/펼쳐짐", "압착/팽창", "늘어남/수축", "구겨짐/평평해짐", "뭉개짐/단단해짐",
58
  "말림/펴짐", "꺾임/구부러짐"
59
  ],
60
+ # ... (중간 생략: 나머지 카테고리는 동일)
61
+ # 생략된 부분도 기존 코드 그대로 유지
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
 
 
 
 
64
  def query_gemini_api(prompt):
65
  try:
 
66
  model = genai.GenerativeModel('gemini-2.0-flash-thinking-exp-01-21')
 
67
  response = model.generate_content(prompt)
68
 
 
69
  try:
70
  if hasattr(response, 'text'):
71
  return response.text
 
72
  if hasattr(response, 'candidates') and response.candidates:
73
  if len(response.candidates) > 0:
74
  candidate = response.candidates[0]
 
80
  if hasattr(response, 'parts') and response.parts:
81
  if len(response.parts) > 0:
82
  return response.parts[0].text
 
83
  return "Unable to generate a response. API response structure is different than expected."
 
84
  except Exception as inner_e:
85
  logger.error(f"Error processing response: {inner_e}")
86
  return f"An error occurred while processing the response: {str(inner_e)}"
 
87
  except Exception as e:
88
  logger.error(f"Error calling Gemini API: {e}")
89
  if "API key not valid" in str(e):
90
  return "API key is not valid. Please check your GEMINI_API_KEY environment variable."
91
  return f"An error occurred while calling the API: {str(e)}"
92
 
93
+
 
 
94
  def enhance_with_llm(base_description, obj_name, category):
95
  prompt = f"""
96
  다음은 '{obj_name}'의 '{category}' 관련 간단한 설명입니다:
97
  "{base_description}"
 
98
  위 내용을 보다 구체화하여,
99
  1) 창의적인 모델/컨셉/형상의 변화에 대한 이해,
100
  2) 혁신 포인트와 기능성 등을 중심으로
 
102
  """
103
  return query_gemini_api(prompt)
104
 
105
+
 
 
106
  def generate_single_object_transformations(obj):
107
  results = {}
108
  for category, transformations in physical_transformation_categories.items():
 
111
  results[category] = {"base": base_description, "enhanced": None}
112
  return results
113
 
114
+
 
 
115
  def generate_two_objects_interaction(obj1, obj2):
116
  results = {}
117
  for category, transformations in physical_transformation_categories.items():
 
124
  results[category] = {"base": base_description, "enhanced": None}
125
  return results
126
 
127
+
 
 
128
  def generate_three_objects_interaction(obj1, obj2, obj3):
129
  results = {}
130
  for category, transformations in physical_transformation_categories.items():
 
137
  results[category] = {"base": base_description, "enhanced": None}
138
  return results
139
 
140
+
 
 
141
  def enhance_descriptions(results, objects):
142
  obj_name = " 및 ".join([obj for obj in objects if obj])
143
  for category, result in results.items():
144
  result["enhanced"] = enhance_with_llm(result["base"], obj_name, category)
145
  return results
146
 
147
+
 
 
148
  def generate_transformations(text1, text2=None, text3=None):
149
  if text2 and text3:
150
  results = generate_three_objects_interaction(text1, text2, text3)
 
157
  objects = [text1]
158
  return enhance_descriptions(results, objects)
159
 
160
+
 
 
161
  def format_results(results):
162
  formatted = ""
163
  for category, result in results.items():
164
  formatted += f"## {category}\n**기본 아이디어**: {result['base']}\n\n**확장된 아이디어**: {result['enhanced']}\n\n---\n\n"
165
  return formatted
166
 
167
+
168
  ##############################################################################
169
+ # 스트리밍(Streaming) 방식으로 출력하는 함수: yield를 사용
170
  ##############################################################################
171
+ def process_inputs_stream(text1, text2, text3):
172
+ # 1) 첫 메시지
173
+ yield "입력값 확인 중..."
174
  time.sleep(0.3)
175
+
176
  text1 = text1.strip() if text1 else None
177
  text2 = text2.strip() if text2 else None
178
  text3 = text3.strip() if text3 else None
179
  if not text1:
180
+ yield "오류: 최소 하나의 키워드를 입력해주세요."
181
+ return # 여기서 함수 종료
182
 
183
+ # 2) 다음 메시지
184
+ yield "창의적인 모델/컨셉/형상 변화 아이디어 생성 중..."
185
  time.sleep(0.3)
186
+
187
+ # 3) 실제 아이디어 생성
188
  results = generate_transformations(text1, text2, text3)
189
 
190
+ # 4) 중간 단계 출력
191
+ yield "결과 포맷팅 중..."
192
  time.sleep(0.3)
193
+
194
+ # 5) 최종 결과 정리
195
  formatted = format_results(results)
196
 
197
+ # 6) 결과 출력
198
+ yield formatted
199
 
200
+ # 7) 완료
201
+ yield "완료!"
202
 
 
 
 
203
  def get_warning_message():
204
  if not GEMINI_API_KEY:
205
  return "⚠️ 환경 변수 GEMINI_API_KEY가 설정되지 않았습니다. Gemini API 키를 설정하세요."
206
  return ""
207
 
208
+
 
 
209
  with gr.Blocks(title="키워드 기반 창의적 변화 아이디어 생성기",
210
  theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")) as demo:
211
 
 
226
 
227
  warning = gr.Markdown(get_warning_message())
228
 
 
229
  with gr.Row():
230
  with gr.Column(scale=1):
231
  text_input1 = gr.Textbox(label="키워드 1 (필수)", placeholder="예: 스마트폰")
 
233
  text_input3 = gr.Textbox(label="키워드 3 (선택)", placeholder="예: 헬스케어")
234
  submit_button = gr.Button("아이디어 생성하기")
235
 
 
236
  with gr.Column(scale=2):
237
  with gr.TabItem("창의적인 모델/컨셉/형상 변화 아이디어", id="creative_tab"):
238
+ # Markdown 출력
239
  idea_output = gr.Markdown(label="아이디어 결과")
240
 
 
241
  gr.Examples(
242
  examples=[
243
  ["스마트폰", "", ""],
 
248
  inputs=[text_input1, text_input2, text_input3],
249
  )
250
 
251
+ # stream=True 옵션을 통해 함수가 yield하는 문자열을 실시간 출력
252
+ submit_button.click(
253
+ fn=process_inputs_stream,
254
+ inputs=[text_input1, text_input2, text_input3],
255
+ outputs=idea_output,
256
+ stream=True
257
+ )
258
 
259
  if __name__ == "__main__":
260
  demo.launch(debug=True)