ssboost commited on
Commit
5b349d3
ยท
verified ยท
1 Parent(s): dbb4c76

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +385 -1
app.py CHANGED
@@ -1,2 +1,386 @@
1
  import os
2
- exec(os.environ.get('APP'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import sys
3
+ import logging
4
+ import tempfile
5
+ import traceback
6
+ from typing import List, Tuple, Optional, Any
7
+ import gradio as gr
8
+ from gradio_client import Client, handle_file
9
+ from dotenv import load_dotenv
10
+
11
+ # .env ํŒŒ์ผ ๋กœ๋“œ
12
+ load_dotenv()
13
+
14
+ # ๋กœ๊น… ์„ค์ • (API ์—”๋“œํฌ์ธํŠธ ์ •๋ณด๋Š” ๋กœ๊ทธ์— ๋‚จ๊ธฐ์ง€ ์•Š์Œ)
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler("app.log"),
20
+ logging.StreamHandler(sys.stdout)
21
+ ]
22
+ )
23
+ logger = logging.getLogger("image-enhancer-control-tower")
24
+
25
+ class GradioClientController:
26
+ """ํ—ˆ๊น…ํŽ˜์ด์Šค ๊ทธ๋ผ๋””์˜ค API ํด๋ผ์ด์–ธํŠธ ์ปจํŠธ๋กค๋Ÿฌ"""
27
+
28
+ def __init__(self):
29
+ self.client = None
30
+ self._initialize_client()
31
+
32
+ def _initialize_client(self):
33
+ """ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” (์—”๋“œํฌ์ธํŠธ ์ •๋ณด๋Š” ๋กœ๊ทธ์— ๋‚จ๊ธฐ์ง€ ์•Š์Œ)"""
34
+ try:
35
+ api_endpoint = os.environ.get("API_ENDPOINT")
36
+ if not api_endpoint:
37
+ logger.error("API_ENDPOINT ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
38
+ raise ValueError("API_ENDPOINT ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.")
39
+
40
+ self.client = Client(api_endpoint)
41
+ logger.info("API ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
42
+
43
+ except Exception as e:
44
+ logger.error(f"ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์‹คํŒจ: {e}")
45
+ self.client = None
46
+
47
+ def update_dropdowns(self, bg_type: str) -> Tuple:
48
+ """๋ฐฐ๊ฒฝ ์œ ํ˜•์— ๋”ฐ๋ฅธ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ"""
49
+ try:
50
+ if not self.client:
51
+ logger.error("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
52
+ return tuple([gr.update() for _ in range(7)])
53
+
54
+ result = self.client.predict(
55
+ bg_type=bg_type,
56
+ api_name="/update_dropdowns"
57
+ )
58
+
59
+ logger.info(f"๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ ์™„๋ฃŒ: {bg_type}")
60
+
61
+ # ๊ฒฐ๊ณผ๋ฅผ Gradio ์—…๋ฐ์ดํŠธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
62
+ updates = []
63
+ for i, choices in enumerate(result):
64
+ if i == 0: # ์‹ฌํ”Œ ๋ฐฐ๊ฒฝ
65
+ updates.append(gr.update(visible=(bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
66
+ elif i == 1: # ์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ
67
+ updates.append(gr.update(visible=(bg_type == "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
68
+ elif i == 2: # ์ž์—ฐ ํ™˜๊ฒฝ
69
+ updates.append(gr.update(visible=(bg_type == "์ž์—ฐ ํ™˜๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
70
+ elif i == 3: # ์‹ค๋‚ด ํ™˜๊ฒฝ
71
+ updates.append(gr.update(visible=(bg_type == "์‹ค๋‚ด ํ™˜๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
72
+ elif i == 4: # ํŠน์ˆ˜๋ฐฐ๊ฒฝ
73
+ updates.append(gr.update(visible=(bg_type == "ํŠน์ˆ˜๋ฐฐ๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
74
+ elif i == 5: # ์ฃผ์–ผ๋ฆฌ
75
+ updates.append(gr.update(visible=(bg_type == "์ฃผ์–ผ๋ฆฌ"), choices=choices, value=choices[0] if choices else None))
76
+ elif i == 6: # ํŠน์ˆ˜ํšจ๊ณผ
77
+ updates.append(gr.update(visible=(bg_type == "ํŠน์ˆ˜ํšจ๊ณผ"), choices=choices, value=choices[0] if choices else None))
78
+
79
+ return tuple(updates)
80
+
81
+ except Exception as e:
82
+ logger.error(f"๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ ์˜ค๋ฅ˜: {e}")
83
+ return tuple([gr.update() for _ in range(7)])
84
+
85
+ def generate_prompt_only(self, password: str, bg_type: str, simple: str, studio: str,
86
+ nature: str, indoor: str, special: str, jewelry: str,
87
+ special_effects: str, request_text: str, aspect_ratio: str) -> str:
88
+ """ํ”„๋กฌํ”„ํŠธ๋งŒ ์ƒ์„ฑ"""
89
+ try:
90
+ if not self.client:
91
+ logger.error("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
92
+ return "ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜"
93
+
94
+ result = self.client.predict(
95
+ password=password,
96
+ bg_type=bg_type,
97
+ simple=simple,
98
+ studio=studio,
99
+ nature=nature,
100
+ indoor=indoor,
101
+ special=special,
102
+ jewelry=jewelry,
103
+ special_effects=special_effects,
104
+ request_text=request_text,
105
+ aspect_ratio=aspect_ratio,
106
+ api_name="/generate_prompt_with_password_check"
107
+ )
108
+
109
+ logger.info("ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์™„๋ฃŒ")
110
+ return result
111
+
112
+ except Exception as e:
113
+ logger.error(f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์˜ค๋ฅ˜: {e}")
114
+ return f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
115
+
116
+ def process_image(self, password: str, image, bg_type: str, simple: str, studio: str,
117
+ nature: str, indoor: str, special: str, jewelry: str, special_effects: str,
118
+ request_text: str, quality_level: str, aspect_ratio: str,
119
+ output_format: str, enable_enhancement: bool) -> Tuple:
120
+ """์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ (ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„ )"""
121
+ try:
122
+ if not self.client:
123
+ logger.error("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
124
+ return ([], None, [], None, "", "", "ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜")
125
+
126
+ # ์ด๋ฏธ์ง€๋ฅผ ์ž„์‹œ ํŒŒ์ผ๋กœ ์ €์žฅ
127
+ temp_path = None
128
+ if image is not None:
129
+ temp_path = tempfile.mktemp(suffix='.png')
130
+ image.save(temp_path)
131
+
132
+ # API ํ˜ธ์ถœ
133
+ result = self.client.predict(
134
+ password=password,
135
+ param_1=handle_file(temp_path) if temp_path else None,
136
+ param_2=bg_type,
137
+ param_3=simple,
138
+ param_4=studio,
139
+ param_5=nature,
140
+ param_6=indoor,
141
+ param_7=special,
142
+ param_8=jewelry,
143
+ param_9=special_effects,
144
+ param_10=request_text,
145
+ param_11=quality_level,
146
+ param_12=aspect_ratio,
147
+ param_13=output_format,
148
+ param_14=enable_enhancement,
149
+ api_name="/check_password"
150
+ )
151
+
152
+ # ์ž„์‹œ ํŒŒ์ผ ์ •๋ฆฌ
153
+ if temp_path and os.path.exists(temp_path):
154
+ try:
155
+ os.remove(temp_path)
156
+ except:
157
+ pass
158
+
159
+ logger.info("์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์™„๋ฃŒ")
160
+
161
+ # ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜: (original_output, original_download, enhanced_output, enhanced_download, prompt_output, info, error)
162
+ return result
163
+
164
+ except Exception as e:
165
+ logger.error(f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์˜ค๋ฅ˜: {e}")
166
+ # ์ž„์‹œ ํŒŒ์ผ ์ •๋ฆฌ
167
+ if 'temp_path' in locals() and temp_path and os.path.exists(temp_path):
168
+ try:
169
+ os.remove(temp_path)
170
+ except:
171
+ pass
172
+ return ([], None, [], None, "", "", f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์˜ค๋ฅ˜: {str(e)}")
173
+
174
+ # ์ „์—ญ ํด๋ผ์ด์–ธํŠธ ์ปจํŠธ๋กค๋Ÿฌ ์ธ์Šคํ„ด์Šค
175
+ controller = GradioClientController()
176
+
177
+ def create_gradio_interface():
178
+ """Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ"""
179
+ try:
180
+ logger.info("Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ์‹œ์ž‘")
181
+
182
+ # ๋ฐฐ๊ฒฝ ์œ ํ˜• ์„ ํƒ์ง€ (ํ•˜๋“œ์ฝ”๋”ฉ)
183
+ background_types = ["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "ํŠน์ˆ˜๋ฐฐ๊ฒฝ", "์ฃผ์–ผ๋ฆฌ", "ํŠน์ˆ˜ํšจ๊ณผ"]
184
+
185
+ with gr.Blocks(title="AI ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„ ") as app:
186
+ gr.Markdown("# AI ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„  ๋„๊ตฌ")
187
+
188
+ # ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํ•„๋“œ
189
+ password_box = gr.Textbox(
190
+ label="๋น„๋ฐ€๋ฒˆํ˜ธ",
191
+ type="password",
192
+ placeholder="์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”",
193
+ interactive=True
194
+ )
195
+
196
+ # ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„  ์ธํ„ฐํŽ˜์ด์Šค
197
+ with gr.Row():
198
+ with gr.Column():
199
+ # ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
200
+ image = gr.Image(label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="pil")
201
+
202
+ with gr.Row():
203
+ with gr.Column():
204
+ background_type = gr.Radio(
205
+ choices=background_types,
206
+ label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
207
+ value="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"
208
+ )
209
+
210
+ # ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ๋“ค (์ดˆ๊ธฐ์—๋Š” ๋นˆ ์ƒํƒœ)
211
+ simple_dropdown = gr.Dropdown(
212
+ choices=[],
213
+ label="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ ์„ ํƒ",
214
+ visible=True,
215
+ interactive=True
216
+ )
217
+
218
+ studio_dropdown = gr.Dropdown(
219
+ choices=[],
220
+ label="์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ ์„ ํƒ",
221
+ visible=False,
222
+ interactive=True
223
+ )
224
+
225
+ nature_dropdown = gr.Dropdown(
226
+ choices=[],
227
+ label="์ž์—ฐ ํ™˜๊ฒฝ ์„ ํƒ",
228
+ visible=False,
229
+ interactive=True
230
+ )
231
+
232
+ indoor_dropdown = gr.Dropdown(
233
+ choices=[],
234
+ label="์‹ค๋‚ด ํ™˜๊ฒฝ ์„ ํƒ",
235
+ visible=False,
236
+ interactive=True
237
+ )
238
+
239
+ special_dropdown = gr.Dropdown(
240
+ choices=[],
241
+ label="ํŠน์ˆ˜๋ฐฐ๊ฒฝ ์„ ํƒ",
242
+ visible=False,
243
+ interactive=True
244
+ )
245
+
246
+ jewelry_dropdown = gr.Dropdown(
247
+ choices=[],
248
+ label="์ฃผ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ ์„ ํƒ",
249
+ visible=False,
250
+ interactive=True
251
+ )
252
+
253
+ special_effects_dropdown = gr.Dropdown(
254
+ choices=[],
255
+ label="ํŠน์ˆ˜ํšจ๊ณผ ๋ฐฐ๊ฒฝ ์„ ํƒ",
256
+ visible=False,
257
+ interactive=True
258
+ )
259
+
260
+ # ๋“œ๋กญ๋‹ค์šด ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ
261
+ background_type.change(
262
+ fn=controller.update_dropdowns,
263
+ inputs=[background_type],
264
+ outputs=[simple_dropdown, studio_dropdown, nature_dropdown,
265
+ indoor_dropdown, special_dropdown, jewelry_dropdown, special_effects_dropdown]
266
+ )
267
+
268
+ # ์š”์ฒญ์‚ฌํ•ญ ์ž…๋ ฅ
269
+ request_text = gr.Textbox(
270
+ label="์š”์ฒญ์‚ฌํ•ญ",
271
+ placeholder="์ƒํ’ˆ ์ด๋ฏธ์ง€์— ์ ์šฉํ•  ์Šคํƒ€์ผ, ๋ถ„์œ„๊ธฐ, ํŠน๋ณ„ ์š”์ฒญ์‚ฌํ•ญ ๋“ฑ์„ ์ž…๋ ฅํ•˜์„ธ์š”.",
272
+ lines=3
273
+ )
274
+
275
+ # ์ƒˆ๋กœ์šด ์˜ต์…˜๋“ค
276
+ quality_level = gr.Radio(
277
+ label="ํ’ˆ์งˆ ๋ ˆ๋ฒจ",
278
+ choices=["gpt", "flux"],
279
+ value="flux",
280
+ info="GPT: GPT ๋ชจ๋ธ (๊ณ ํ’ˆ์งˆ), ์ผ๋ฐ˜: Flux ๋ชจ๋ธ (๋น ๋ฅธ ์ฒ˜๋ฆฌ + ๊ธฐ๋ณธ ํ™”์งˆ๊ฐœ์„ )"
281
+ )
282
+
283
+ aspect_ratio = gr.Dropdown(
284
+ label="์ข…ํšก๋น„",
285
+ choices=["1:1", "3:2", "2:3"],
286
+ value="1:1"
287
+ )
288
+
289
+ output_format = gr.Dropdown(
290
+ label="์ด๋ฏธ์ง€ ํ˜•์‹",
291
+ choices=["jpg", "png"],
292
+ value="jpg"
293
+ )
294
+
295
+ # ํ™”์งˆ ๊ฐœ์„  ์˜ต์…˜
296
+ enable_enhancement = gr.Checkbox(
297
+ label="์ถ”๊ฐ€ ํ™”์งˆ ๊ฐœ์„ ",
298
+ value=False,
299
+ info="GPT: 1ํšŒ ํ™”์งˆ๊ฐœ์„ , Flux: 2์ฐจ ํ™”์งˆ๊ฐœ์„  (๊ธฐ๋ณธ 1ํšŒ + ์ถ”๊ฐ€ 1ํšŒ)"
300
+ )
301
+
302
+ # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ
303
+ generate_prompt_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ๋งŒ ์ƒ์„ฑ")
304
+
305
+ # ํŽธ์ง‘ ๋ฒ„ํŠผ
306
+ edit_btn = gr.Button("์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„ ")
307
+
308
+ with gr.Column():
309
+ with gr.Row():
310
+ with gr.Column():
311
+ gr.Markdown("## ํŽธ์ง‘๋œ ์ด๋ฏธ์ง€")
312
+ original_output = gr.Gallery(label="ํŽธ์ง‘ ๊ฒฐ๊ณผ", preview=True)
313
+ original_download = gr.File(label="ํŽธ์ง‘ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ", interactive=False)
314
+
315
+ with gr.Column():
316
+ gr.Markdown("## ํ™”์งˆ ๊ฐœ์„ ๋œ ์ด๋ฏธ์ง€")
317
+ enhanced_output = gr.Gallery(label="ํ™”์งˆ ๊ฐœ์„  ๊ฒฐ๊ณผ", preview=True)
318
+ enhanced_download = gr.File(label="๊ฐœ์„  ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ", interactive=False)
319
+
320
+ # ํ”„๋กฌํ”„ํŠธ ์ถœ๋ ฅ
321
+ prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ", lines=10, interactive=False)
322
+ info = gr.Textbox(label="์ฒ˜๋ฆฌ ์ •๋ณด", interactive=False)
323
+ error = gr.Textbox(label="์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€", interactive=False, visible=True)
324
+
325
+ # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
326
+ generate_prompt_btn.click(
327
+ fn=controller.generate_prompt_only,
328
+ inputs=[
329
+ password_box,
330
+ background_type,
331
+ simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, special_dropdown,
332
+ jewelry_dropdown, special_effects_dropdown,
333
+ request_text, aspect_ratio
334
+ ],
335
+ outputs=[prompt_output]
336
+ )
337
+
338
+ # ํŽธ์ง‘ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
339
+ edit_btn.click(
340
+ fn=controller.process_image,
341
+ inputs=[
342
+ password_box,
343
+ image, background_type,
344
+ simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, special_dropdown,
345
+ jewelry_dropdown, special_effects_dropdown,
346
+ request_text, quality_level, aspect_ratio, output_format, enable_enhancement
347
+ ],
348
+ outputs=[
349
+ original_output, original_download,
350
+ enhanced_output, enhanced_download,
351
+ prompt_output, info, error
352
+ ]
353
+ )
354
+
355
+ # ์ดˆ๊ธฐ ๋“œ๋กญ๋‹ค์šด ๋กœ๋“œ
356
+ app.load(
357
+ fn=controller.update_dropdowns,
358
+ inputs=[background_type],
359
+ outputs=[simple_dropdown, studio_dropdown, nature_dropdown,
360
+ indoor_dropdown, special_dropdown, jewelry_dropdown, special_effects_dropdown]
361
+ )
362
+
363
+ logger.info("Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ์™„๋ฃŒ")
364
+ return app
365
+
366
+ except Exception as e:
367
+ logger.error(f"Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ์˜ค๋ฅ˜: {e}")
368
+ logger.error(traceback.format_exc())
369
+ raise
370
+
371
+ # ์•ฑ ์‹คํ–‰
372
+ if __name__ == "__main__":
373
+ try:
374
+ logger.info("์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘")
375
+
376
+ # imgs ๋””๋ ‰ํ† ๋ฆฌ ํ™•์ธ/์ƒ์„ฑ
377
+ os.makedirs("imgs", exist_ok=True)
378
+ logger.info("์ด๋ฏธ์ง€ ๋””๋ ‰ํ† ๋ฆฌ ์ค€๋น„ ์™„๋ฃŒ")
379
+
380
+ app = create_gradio_interface()
381
+ logger.info("Gradio ์•ฑ ์‹œ์ž‘")
382
+ app.launch(share=True)
383
+
384
+ except Exception as e:
385
+ logger.error(f"์•ฑ ์‹คํ–‰ ์˜ค๋ฅ˜: {e}")
386
+ logger.error(traceback.format_exc())