eeuuia commited on
Commit
dac32ed
·
verified ·
1 Parent(s): af2eb5c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -55
app.py CHANGED
@@ -1,35 +1,54 @@
1
  # FILE: app.py
2
  # DESCRIPTION: Final Gradio web interface for the ADUC-SDR Video Suite.
3
- # Features a unified workflow, advanced LTX controls, and a clean, modular structure.
 
4
 
5
  import gradio as gr
6
  import traceback
7
  import sys
 
 
8
 
9
  # ==============================================================================
10
- # --- IMPORTAÇÃO DOS SERVIÇOS DE BACKEND ---
11
  # ==============================================================================
12
 
13
  try:
14
- # A UI depende do VideoService para todas as operações LTX.
15
  from api.ltx_server_refactored_complete import video_generation_service
16
 
17
- # A importação do SeedVR permanece opcional.
18
- # from api.seedvr_server import SeedVRServer
19
- # seedvr_inference_server = SeedVRServer()
20
- seedvr_inference_server = None # Desativado para este exemplo
21
- print("Backend services imported successfully.")
 
 
 
 
22
  except ImportError as e:
23
- print(f"FATAL ERROR: Could not import backend services. Details: {e}", file=sys.stderr)
24
- sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
25
  except Exception as e:
26
- print(f"FATAL ERROR: An unexpected error occurred during backend initialization. Details: {e}", file=sys.stderr)
27
  sys.exit(1)
28
 
29
  # ==============================================================================
30
  # --- FUNÇÕES WRAPPER (PONTE ENTRE UI E BACKEND) ---
31
  # ==============================================================================
32
 
 
33
  def run_generate_base_video(
34
  generation_mode: str, prompt: str, neg_prompt: str, start_img: str,
35
  height: int, width: int, duration: float,
@@ -37,12 +56,9 @@ def run_generate_base_video(
37
  fp_num_inference_steps: int, fp_skip_initial_steps: int, fp_skip_final_steps: int,
38
  progress=gr.Progress(track_tqdm=True)
39
  ) -> tuple:
40
- """
41
- Wrapper que coleta todos os dados da UI, os empacota e chama a função de geração
42
- unificada do backend.
43
- """
44
  try:
45
- print(f"[UI] Request received. Selected mode: {generation_mode}")
46
 
47
  initial_conditions = []
48
  if start_img:
@@ -52,7 +68,6 @@ def run_generate_base_video(
52
  items_list, height, width, num_frames_estimate
53
  )
54
 
55
- # Agrupa todas as configurações LTX em um único dicionário para o backend
56
  ltx_configs = {
57
  "guidance_preset": fp_guidance_preset,
58
  "guidance_scale_list": fp_guidance_scale_list,
@@ -63,43 +78,70 @@ def run_generate_base_video(
63
  }
64
 
65
  video_path, tensor_path, final_seed = video_generation_service.generate_low_resolution(
66
- prompt=prompt,
67
- negative_prompt=neg_prompt,
68
  height=height, width=width, duration=duration,
69
- initial_conditions=initial_conditions,
70
- ltx_configs_override=ltx_configs
71
  )
72
 
73
- if not video_path:
74
- raise RuntimeError("Backend failed to return a valid video path.")
75
 
76
  new_state = {"low_res_video": video_path, "low_res_latents": tensor_path, "used_seed": final_seed}
77
-
78
- print(f"[UI] Base video generation successful. Seed used: {final_seed}, Path: {video_path}")
79
  return video_path, new_state, gr.update(visible=True)
80
 
81
  except Exception as e:
82
  error_message = f"❌ An error occurred during base generation:\n{e}"
83
- print(f"{error_message}\nDetails: {traceback.format_exc()}", file=sys.stderr)
84
  raise gr.Error(error_message)
85
 
86
-
87
  def run_ltx_refinement(state: dict, prompt: str, neg_prompt: str, progress=gr.Progress(track_tqdm=True)) -> tuple:
88
- """Wrapper para chamar a função de refinamento/upscale do LTX."""
89
  if not state or not state.get("low_res_latents"):
90
  raise gr.Error("Error: Please generate a base video in Step 1 before refining.")
91
- # (A lógica desta função permanece a mesma)
92
- # ...
93
- return None, state
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
 
96
- def run_seedvr_upscaling(state: dict, resolution: int, batch_size: int, fps: int, progress=gr.Progress(track_tqdm=True)) -> tuple:
97
- """Wrapper para chamar o serviço de upscale do SeedVR."""
 
98
  if not state or not state.get("low_res_video"):
99
  raise gr.Error("Error: Please generate a base video in Step 1 before upscaling.")
100
- # (A lógica desta função permanece a mesma)
101
- # ...
102
- return None, "Not implemented."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # ==============================================================================
105
  # --- CONSTRUÇÃO DA INTERFACE GRADIO ---
@@ -112,7 +154,7 @@ def build_ui():
112
  app_state = gr.State(value={"low_res_video": None, "low_res_latents": None, "used_seed": None})
113
  ui_components = {}
114
 
115
- gr.Markdown("# ADUC-SDR Video Suite - LTX Workflow", elem_id="main-title")
116
 
117
  with gr.Row():
118
  with gr.Column(scale=1):
@@ -120,6 +162,7 @@ def build_ui():
120
  with gr.Column(scale=1):
121
  gr.Markdown("### Etapa 1: Vídeo Base Gerado")
122
  ui_components['low_res_video_output'] = gr.Video(label="O resultado aparecerá aqui", interactive=False)
 
123
 
124
  _build_postprod_controls(ui_components)
125
  _register_event_handlers(app_state, ui_components)
@@ -129,13 +172,7 @@ def build_ui():
129
  def _build_generation_controls(ui: dict):
130
  """Constrói os componentes da UI para a Etapa 1: Geração."""
131
  gr.Markdown("### Configurações de Geração")
132
-
133
- ui['generation_mode'] = gr.Radio(
134
- label="Modo de Geração",
135
- choices=["Simples (Prompt Único)", "Narrativa (Múltiplos Prompts)"],
136
- value="Narrativa (Múltiplos Prompts)",
137
- info="Simples para uma ação contínua, Narrativa para uma sequência (uma cena por linha)."
138
- )
139
  ui['prompt'] = gr.Textbox(label="Prompt(s)", value="Um leão majestoso caminha pela savana\nEle sobe em uma grande pedra e olha o horizonte", lines=4)
140
  ui['neg_prompt'] = gr.Textbox(label="Negative Prompt", value="blurry, low quality, bad anatomy, deformed", lines=2)
141
  ui['start_image'] = gr.Image(label="Imagem de Início (Opcional)", type="filepath", sources=["upload"])
@@ -149,18 +186,13 @@ def _build_generation_controls(ui: dict):
149
  with gr.Accordion("Opções Avançadas LTX", open=False):
150
  gr.Markdown("#### Configurações de Passos de Inferência (First Pass)")
151
  gr.Markdown("*Deixe o valor padrão (ex: 20) ou 0 para usar a configuração do `config.yaml`.*")
152
-
153
  ui['fp_num_inference_steps'] = gr.Slider(label="Número de Passos", minimum=0, maximum=100, step=1, value=20, info="Padrão LTX: 20.")
154
  ui['fp_skip_initial_steps'] = gr.Slider(label="Pular Passos Iniciais", minimum=0, maximum=100, step=1, value=0)
155
  ui['fp_skip_final_steps'] = gr.Slider(label="Pular Passos Finais", minimum=0, maximum=100, step=1, value=0)
156
 
157
  with gr.Tabs():
158
  with gr.TabItem("Configurações de Guiagem (First Pass)"):
159
- ui['fp_guidance_preset'] = gr.Dropdown(
160
- label="Preset de Guiagem",
161
- choices=["Padrão (Recomendado)", "Agressivo", "Suave", "Customizado"],
162
- value="Padrão (Recomendado)", info="Controla o comportamento da guiagem durante a difusão."
163
- )
164
  with gr.Group(visible=False) as ui['custom_guidance_group']:
165
  gr.Markdown("⚠️ Edite as listas em formato JSON. Ex: `[1.0, 2.5, 3.0]`")
166
  ui['fp_guidance_scale_list'] = gr.Textbox(label="Lista de Guidance Scale", value="[1, 1, 6, 8, 6, 1, 1]")
@@ -182,8 +214,20 @@ def _build_postprod_controls(ui: dict):
182
  ui['ltx_refined_video_output'] = gr.Video(label="Vídeo com Textura Refinada", interactive=False)
183
 
184
  with gr.TabItem("✨ Upscaler de Resolução (SeedVR)"):
185
- # (A UI do SeedVR permanece a mesma, desativada se o servidor não estiver disponível)
186
- pass
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
  def _register_event_handlers(app_state: gr.State, ui: dict):
189
  """Registra todos os manipuladores de eventos do Gradio."""
@@ -193,6 +237,9 @@ def _register_event_handlers(app_state: gr.State, ui: dict):
193
 
194
  ui['fp_guidance_preset'].change(fn=toggle_custom_guidance, inputs=ui['fp_guidance_preset'], outputs=ui['custom_guidance_group'])
195
 
 
 
 
196
  gen_inputs = [
197
  ui['generation_mode'], ui['prompt'], ui['neg_prompt'], ui['start_image'],
198
  ui['height'], ui['width'], ui['duration'],
@@ -200,19 +247,30 @@ def _register_event_handlers(app_state: gr.State, ui: dict):
200
  ui['fp_num_inference_steps'], ui['fp_skip_initial_steps'], ui['fp_skip_final_steps'],
201
  ]
202
  gen_outputs = [ui['low_res_video_output'], app_state, ui['post_prod_group']]
203
- ui['generate_low_btn'].click(fn=run_generate_base_video, inputs=gen_inputs, outputs=gen_outputs)
 
 
 
 
 
204
 
205
  refine_inputs = [app_state, ui['prompt'], ui['neg_prompt']]
206
  refine_outputs = [ui['ltx_refined_video_output'], app_state]
207
  ui['ltx_refine_btn'].click(fn=run_ltx_refinement, inputs=refine_inputs, outputs=refine_outputs)
208
 
209
- # (Handlers para o SeedVR, se ativados)
 
 
 
210
 
211
  # ==============================================================================
212
  # --- PONTO DE ENTRADA DA APLICAÇÃO ---
213
  # ==============================================================================
214
 
215
  if __name__ == "__main__":
 
 
 
216
  print("Building Gradio UI...")
217
  gradio_app = build_ui()
218
  print("Launching Gradio app...")
@@ -220,4 +278,4 @@ if __name__ == "__main__":
220
  server_name=os.getenv("GRADIO_SERVER_NAME", "0.0.0.0"),
221
  server_port=int(os.getenv("GRADIO_SERVER_PORT", "7860")),
222
  show_error=True
223
- )
 
1
  # FILE: app.py
2
  # DESCRIPTION: Final Gradio web interface for the ADUC-SDR Video Suite.
3
+ # Features a unified LTX workflow, advanced controls, integrated SeedVR upscaling,
4
+ # and detailed debug logging.
5
 
6
  import gradio as gr
7
  import traceback
8
  import sys
9
+ import os
10
+ import logging
11
 
12
  # ==============================================================================
13
+ # --- IMPORTAÇÃO DOS SERVIÇOS DE BACKEND E UTILS ---
14
  # ==============================================================================
15
 
16
  try:
17
+ # Serviço principal para geração LTX
18
  from api.ltx_server_refactored_complete import video_generation_service
19
 
20
+ # Nosso decorador de logging para depuração
21
+ from api.utils.debug_utils import log_function_io
22
+
23
+ # Serviço especialista para upscaling de resolução (SeedVR)
24
+ from api.seedvr_server import SeedVRServer
25
+ seedvr_inference_server = SeedVRServer()
26
+
27
+ logging.info("All backend services (LTX, SeedVR) and debug utils imported successfully.")
28
+
29
  except ImportError as e:
30
+ # Define um fallback para o decorador para que a UI não quebre se o utilitário não for encontrado
31
+ def log_function_io(func):
32
+ return func
33
+ logging.warning(f"Could not import a module, debug logger might be disabled. SeedVR might be unavailable. Details: {e}")
34
+ # Se o serviço LTX principal falhar, é um erro fatal
35
+ if 'video_generation_service' not in locals():
36
+ logging.critical(f"FATAL: Main LTX service failed to import.", exc_info=True)
37
+ sys.exit(1)
38
+ # Se apenas o SeedVR falhar, a aplicação pode continuar com ele desativado
39
+ if 'seedvr_inference_server' not in locals():
40
+ seedvr_inference_server = None
41
+ logging.warning("SeedVR server could not be initialized. The SeedVR upscaling tab will be disabled.")
42
+
43
  except Exception as e:
44
+ logging.critical(f"FATAL ERROR: An unexpected error occurred during backend initialization. Details: {e}", exc_info=True)
45
  sys.exit(1)
46
 
47
  # ==============================================================================
48
  # --- FUNÇÕES WRAPPER (PONTE ENTRE UI E BACKEND) ---
49
  # ==============================================================================
50
 
51
+ @log_function_io
52
  def run_generate_base_video(
53
  generation_mode: str, prompt: str, neg_prompt: str, start_img: str,
54
  height: int, width: int, duration: float,
 
56
  fp_num_inference_steps: int, fp_skip_initial_steps: int, fp_skip_final_steps: int,
57
  progress=gr.Progress(track_tqdm=True)
58
  ) -> tuple:
59
+ """Wrapper para a geração do vídeo base LTX."""
 
 
 
60
  try:
61
+ logging.info(f"[UI] Request received. Selected mode: {generation_mode}")
62
 
63
  initial_conditions = []
64
  if start_img:
 
68
  items_list, height, width, num_frames_estimate
69
  )
70
 
 
71
  ltx_configs = {
72
  "guidance_preset": fp_guidance_preset,
73
  "guidance_scale_list": fp_guidance_scale_list,
 
78
  }
79
 
80
  video_path, tensor_path, final_seed = video_generation_service.generate_low_resolution(
81
+ prompt=prompt, negative_prompt=neg_prompt,
 
82
  height=height, width=width, duration=duration,
83
+ initial_conditions=initial_conditions, ltx_configs_override=ltx_configs
 
84
  )
85
 
86
+ if not video_path: raise RuntimeError("Backend failed to return a valid video path.")
 
87
 
88
  new_state = {"low_res_video": video_path, "low_res_latents": tensor_path, "used_seed": final_seed}
89
+ logging.info(f"[UI] Base video generation successful. Seed used: {final_seed}, Path: {video_path}")
 
90
  return video_path, new_state, gr.update(visible=True)
91
 
92
  except Exception as e:
93
  error_message = f"❌ An error occurred during base generation:\n{e}"
94
+ logging.error(f"{error_message}\nDetails: {traceback.format_exc()}", exc_info=True)
95
  raise gr.Error(error_message)
96
 
97
+ @log_function_io
98
  def run_ltx_refinement(state: dict, prompt: str, neg_prompt: str, progress=gr.Progress(track_tqdm=True)) -> tuple:
99
+ """Wrapper para o refinamento de textura LTX."""
100
  if not state or not state.get("low_res_latents"):
101
  raise gr.Error("Error: Please generate a base video in Step 1 before refining.")
102
+
103
+ try:
104
+ logging.info(f"[UI] Requesting LTX refinement for latents: {state.get('low_res_latents')}")
105
+ video_path, tensor_path = video_generation_service.generate_upscale_denoise(
106
+ latents_path=state["low_res_latents"],
107
+ prompt=prompt,
108
+ negative_prompt=neg_prompt,
109
+ seed=state["used_seed"]
110
+ )
111
+ state["refined_video_ltx"] = video_path
112
+ state["refined_latents_ltx"] = tensor_path
113
+ logging.info(f"[UI] LTX refinement successful. Path: {video_path}")
114
+ return video_path, state
115
+ except Exception as e:
116
+ error_message = f"❌ An error occurred during LTX Refinement:\n{e}"
117
+ logging.error(f"{error_message}\nDetails: {traceback.format_exc()}", exc_info=True)
118
+ raise gr.Error(error_message)
119
 
120
 
121
+ @log_function_io
122
+ def run_seedvr_upscaling(state: dict, seed: int, resolution: int, batch_size: int, fps: int, progress=gr.Progress(track_tqdm=True)) -> tuple:
123
+ """Wrapper para o upscale de resolução SeedVR."""
124
  if not state or not state.get("low_res_video"):
125
  raise gr.Error("Error: Please generate a base video in Step 1 before upscaling.")
126
+ if not seedvr_inference_server:
127
+ raise gr.Error("Error: The SeedVR upscaling server is not available.")
128
+
129
+ try:
130
+ logging.info(f"[UI] Requesting SeedVR upscaling for video: {state.get('low_res_video')}")
131
+ def progress_wrapper(p, desc=""): progress(p, desc=desc)
132
+
133
+ output_filepath = seedvr_inference_server.run_inference(
134
+ file_path=state["low_res_video"], seed=int(seed), resolution=int(resolution),
135
+ batch_size=int(batch_size), fps=float(fps), progress=progress_wrapper
136
+ )
137
+
138
+ status_message = f"✅ Upscaling complete!\nSaved to: {output_filepath}"
139
+ logging.info(f"[UI] SeedVR upscaling successful. Path: {output_filepath}")
140
+ return gr.update(value=output_filepath), gr.update(value=status_message)
141
+ except Exception as e:
142
+ error_message = f"❌ An error occurred during SeedVR Upscaling:\n{e}"
143
+ logging.error(f"{error_message}\nDetails: {traceback.format_exc()}", exc_info=True)
144
+ return None, gr.update(value=error_message)
145
 
146
  # ==============================================================================
147
  # --- CONSTRUÇÃO DA INTERFACE GRADIO ---
 
154
  app_state = gr.State(value={"low_res_video": None, "low_res_latents": None, "used_seed": None})
155
  ui_components = {}
156
 
157
+ gr.Markdown("# ADUC-SDR Video Suite - LTX & SeedVR Workflow", elem_id="main-title")
158
 
159
  with gr.Row():
160
  with gr.Column(scale=1):
 
162
  with gr.Column(scale=1):
163
  gr.Markdown("### Etapa 1: Vídeo Base Gerado")
164
  ui_components['low_res_video_output'] = gr.Video(label="O resultado aparecerá aqui", interactive=False)
165
+ ui_components['used_seed_display'] = gr.Textbox(label="Seed Utilizada", interactive=False)
166
 
167
  _build_postprod_controls(ui_components)
168
  _register_event_handlers(app_state, ui_components)
 
172
  def _build_generation_controls(ui: dict):
173
  """Constrói os componentes da UI para a Etapa 1: Geração."""
174
  gr.Markdown("### Configurações de Geração")
175
+ ui['generation_mode'] = gr.Radio(label="Modo de Geração", choices=["Simples (Prompt Único)", "Narrativa (Múltiplos Prompts)"], value="Narrativa (Múltiplos Prompts)", info="Simples para uma ação contínua, Narrativa para uma sequência (uma cena por linha).")
 
 
 
 
 
 
176
  ui['prompt'] = gr.Textbox(label="Prompt(s)", value="Um leão majestoso caminha pela savana\nEle sobe em uma grande pedra e olha o horizonte", lines=4)
177
  ui['neg_prompt'] = gr.Textbox(label="Negative Prompt", value="blurry, low quality, bad anatomy, deformed", lines=2)
178
  ui['start_image'] = gr.Image(label="Imagem de Início (Opcional)", type="filepath", sources=["upload"])
 
186
  with gr.Accordion("Opções Avançadas LTX", open=False):
187
  gr.Markdown("#### Configurações de Passos de Inferência (First Pass)")
188
  gr.Markdown("*Deixe o valor padrão (ex: 20) ou 0 para usar a configuração do `config.yaml`.*")
 
189
  ui['fp_num_inference_steps'] = gr.Slider(label="Número de Passos", minimum=0, maximum=100, step=1, value=20, info="Padrão LTX: 20.")
190
  ui['fp_skip_initial_steps'] = gr.Slider(label="Pular Passos Iniciais", minimum=0, maximum=100, step=1, value=0)
191
  ui['fp_skip_final_steps'] = gr.Slider(label="Pular Passos Finais", minimum=0, maximum=100, step=1, value=0)
192
 
193
  with gr.Tabs():
194
  with gr.TabItem("Configurações de Guiagem (First Pass)"):
195
+ ui['fp_guidance_preset'] = gr.Dropdown(label="Preset de Guiagem", choices=["Padrão (Recomendado)", "Agressivo", "Suave", "Customizado"], value="Padrão (Recomendado)", info="Controla o comportamento da guiagem durante a difusão.")
 
 
 
 
196
  with gr.Group(visible=False) as ui['custom_guidance_group']:
197
  gr.Markdown("⚠️ Edite as listas em formato JSON. Ex: `[1.0, 2.5, 3.0]`")
198
  ui['fp_guidance_scale_list'] = gr.Textbox(label="Lista de Guidance Scale", value="[1, 1, 6, 8, 6, 1, 1]")
 
214
  ui['ltx_refined_video_output'] = gr.Video(label="Vídeo com Textura Refinada", interactive=False)
215
 
216
  with gr.TabItem("✨ Upscaler de Resolução (SeedVR)"):
217
+ is_seedvr_available = seedvr_inference_server is not None
218
+ if not is_seedvr_available:
219
+ gr.Markdown("🔴 **AVISO: O serviço SeedVR não está disponível. A aba de upscale de resolução está desativada.**")
220
+
221
+ with gr.Row():
222
+ with gr.Column(scale=1):
223
+ ui['seedvr_seed'] = gr.Slider(minimum=0, maximum=999999, value=42, step=1, label="Seed")
224
+ ui['seedvr_resolution'] = gr.Slider(minimum=720, maximum=2160, value=1080, step=8, label="Resolução Vertical Alvo")
225
+ ui['seedvr_batch_size'] = gr.Slider(minimum=1, maximum=16, value=4, step=1, label="Batch Size por GPU")
226
+ ui['seedvr_fps'] = gr.Number(label="FPS de Saída (0 = original)", value=0)
227
+ ui['run_seedvr_btn'] = gr.Button("2. Iniciar Upscaling SeedVR", variant="primary", interactive=is_seedvr_available)
228
+ with gr.Column(scale=1):
229
+ ui['seedvr_video_output'] = gr.Video(label="Vídeo com Upscale SeedVR", interactive=False)
230
+ ui['seedvr_status_box'] = gr.Textbox(label="Status do SeedVR", value="Aguardando...", lines=3, interactive=False)
231
 
232
  def _register_event_handlers(app_state: gr.State, ui: dict):
233
  """Registra todos os manipuladores de eventos do Gradio."""
 
237
 
238
  ui['fp_guidance_preset'].change(fn=toggle_custom_guidance, inputs=ui['fp_guidance_preset'], outputs=ui['custom_guidance_group'])
239
 
240
+ def update_seed_display(state):
241
+ return state.get("used_seed", "N/A")
242
+
243
  gen_inputs = [
244
  ui['generation_mode'], ui['prompt'], ui['neg_prompt'], ui['start_image'],
245
  ui['height'], ui['width'], ui['duration'],
 
247
  ui['fp_num_inference_steps'], ui['fp_skip_initial_steps'], ui['fp_skip_final_steps'],
248
  ]
249
  gen_outputs = [ui['low_res_video_output'], app_state, ui['post_prod_group']]
250
+
251
+ (
252
+ ui['generate_low_btn']
253
+ .click(fn=run_generate_base_video, inputs=gen_inputs, outputs=gen_outputs)
254
+ .then(fn=update_seed_display, inputs=[app_state], outputs=[ui['used_seed_display']])
255
+ )
256
 
257
  refine_inputs = [app_state, ui['prompt'], ui['neg_prompt']]
258
  refine_outputs = [ui['ltx_refined_video_output'], app_state]
259
  ui['ltx_refine_btn'].click(fn=run_ltx_refinement, inputs=refine_inputs, outputs=refine_outputs)
260
 
261
+ if 'run_seedvr_btn' in ui:
262
+ seedvr_inputs = [app_state, ui['seedvr_seed'], ui['seedvr_resolution'], ui['seedvr_batch_size'], ui['seedvr_fps']]
263
+ seedvr_outputs = [ui['seedvr_video_output'], ui['seedvr_status_box']]
264
+ ui['run_seedvr_btn'].click(fn=run_seedvr_upscaling, inputs=seedvr_inputs, outputs=seedvr_outputs)
265
 
266
  # ==============================================================================
267
  # --- PONTO DE ENTRADA DA APLICAÇÃO ---
268
  # ==============================================================================
269
 
270
  if __name__ == "__main__":
271
+ log_level = os.environ.get("ADUC_LOG_LEVEL", "INFO").upper()
272
+ logging.basicConfig(level=log_level, format='[%(levelname)s] [%(name)s] %(message)s')
273
+
274
  print("Building Gradio UI...")
275
  gradio_app = build_ui()
276
  print("Launching Gradio app...")
 
278
  server_name=os.getenv("GRADIO_SERVER_NAME", "0.0.0.0"),
279
  server_port=int(os.getenv("GRADIO_SERVER_PORT", "7860")),
280
  show_error=True
281
+ )