euIaxs22 commited on
Commit
13e6a77
·
verified ·
1 Parent(s): d1f2745

Update app_vince.py

Browse files
Files changed (1) hide show
  1. app_vince.py +61 -87
app_vince.py CHANGED
@@ -2,57 +2,47 @@
2
  """
3
  VINCIE Service UI (Gradio)
4
 
5
- - Automatic setup runs on app load (no manual setup button).
6
- - Multi-turn editing and multi-concept composition front-end.
7
- - Designed for NVIDIA L40S (SM 8.9) environments aligned with CUDA 12.x.
8
- - Functional reference: ByteDance-Seed/VINCIE.
9
- - Space and Docker developed by Carlex (contact below).
 
10
  """
11
 
12
  import os
 
13
  from pathlib import Path
14
  from typing import List, Tuple, Optional
15
 
16
  import gradio as gr
17
 
18
- # Adapt this import to the project layout.
19
- # Provide a VincieService with:
20
- # - ensure_repo(): clones/updates upstream repo if missing
21
- # - ensure_model(): downloads/validates checkpoints to /app/ckpt/VINCIE-3B
22
- # - multi_turn_edit(image_path: str, turns: List[str], *, cfg_scale: Optional[float], resolution_input: Optional[int], aspect_ratio_input: Optional[str], steps: Optional[int]) -> str
23
- # - multi_concept_compose(files: List[str], descs: List[str], final_prompt: str, *, cfg_scale: Optional[float], resolution_input: Optional[int], aspect_ratio_input: Optional[str], steps: Optional[int]) -> str
24
- from services.vincie import VincieService # change path if needed
25
 
26
- # Instantiate the service (defaults to /app/VINCIE and /app/ckpt/VINCIE-3B)
27
  svc = VincieService()
28
 
 
29
  def setup_auto() -> str:
30
  """
31
- Run an idempotent setup on interface load:
32
- - Ensure the upstream repository is present and ready.
33
- - Ensure the model checkpoint is downloaded and ready.
34
- Returns an English status string for the UI.
35
  """
36
  try:
37
  svc.ensure_repo()
38
  svc.ensure_model()
39
- return (
40
- "Setup completed successfully: repository and checkpoint are ready "
41
- "for inference on an NVIDIA L40S environment."
42
- )
43
  except Exception as e:
44
- return f"Setup encountered an error: {e}"
 
45
 
46
  def _list_media(out_dir: Path, max_images: int = 24) -> Tuple[List[str], Optional[str]]:
47
  """
48
- Enumerate resulting images and the most recent video from an output directory.
49
- Args:
50
- out_dir: Path to the directory where the service wrote its results.
51
- max_images: Upper bound on how many images to surface in the gallery.
52
- Returns:
53
- A tuple (images, video) where:
54
- - images is a list of file paths to images sorted by modified time,
55
- - video is the path to the latest .mp4 if found, otherwise None.
56
  """
57
  img_globs = ("*.png", "*.jpg", "*.jpeg", "*.webp")
58
  images: List[Path] = []
@@ -64,6 +54,7 @@ def _list_media(out_dir: Path, max_images: int = 24) -> Tuple[List[str], Optiona
64
  video_path = str(videos[-1]) if videos else None
65
  return image_paths, video_path
66
 
 
67
  def ui_multi_turn(
68
  input_image: Optional[str],
69
  turns_text: Optional[str],
@@ -73,21 +64,12 @@ def ui_multi_turn(
73
  resolution_input: int,
74
  ):
75
  """
76
- Multi-turn image editing entrypoint for the UI.
77
- Args:
78
- input_image: Path to a single input image on disk.
79
- turns_text: User-provided editing turns, one instruction per line.
80
- steps_input: Override for generation steps.
81
- cfg_scale_input: Override for guidance scale.
82
- aspect_ratio_input: Override for aspect ratio selection.
83
- resolution_input: Override for shorter-side resolution.
84
- Returns:
85
- (gallery, video, status) for Gradio components.
86
  """
87
  if not input_image or not str(input_image).strip():
88
- return [], None, "Please provide an input image."
89
  if not turns_text or not turns_text.strip():
90
- return [], None, "Please provide edit turns (one per line)."
91
 
92
  turns = [ln.strip() for ln in turns_text.splitlines() if ln.strip()]
93
  try:
@@ -100,12 +82,13 @@ def ui_multi_turn(
100
  steps=int(steps_input) if steps_input is not None else None,
101
  )
102
  except Exception as e:
103
- return [], None, f"Generation error: {e}"
104
 
105
  imgs, vid = _list_media(Path(out_dir))
106
- status = f"Outputs saved to: {out_dir}"
107
  return imgs, vid, status
108
 
 
109
  def ui_multi_concept(
110
  files: Optional[List[str]],
111
  descs_text: Optional[str],
@@ -116,28 +99,18 @@ def ui_multi_concept(
116
  resolution_input: int,
117
  ):
118
  """
119
- Multi-concept composition entrypoint for the UI.
120
- Args:
121
- files: List of paths to concept images on disk.
122
- descs_text: Per-image descriptions (one line per image, in the same order).
123
- final_prompt: A final composition prompt that aggregates the concepts.
124
- steps_input: Override for generation steps.
125
- cfg_scale_input: Override for guidance scale.
126
- aspect_ratio_input: Override for aspect ratio selection.
127
- resolution_input: Override for shorter-side resolution.
128
- Returns:
129
- (gallery, video, status) for Gradio components.
130
  """
131
  if not files:
132
- return [], None, "Please upload concept images."
133
  if not descs_text or not descs_text.strip():
134
- return [], None, "Please provide descriptions (one per line)."
135
  if not final_prompt or not final_prompt.strip():
136
- return [], None, "Please provide a final prompt."
137
 
138
  descs = [ln.strip() for ln in descs_text.splitlines() if ln.strip()]
139
  if len(descs) != len(files):
140
- return [], None, f"Descriptions count ({len(descs)}) must match images count ({len(files)})."
141
 
142
  try:
143
  out_dir = svc.multi_concept_compose(
@@ -150,31 +123,30 @@ def ui_multi_concept(
150
  steps=int(steps_input) if steps_input is not None else None,
151
  )
152
  except Exception as e:
153
- return [], None, f"Generation error: {e}"
154
 
155
  imgs, vid = _list_media(Path(out_dir))
156
- status = f"Outputs saved to: {out_dir}"
157
  return imgs, vid, status
158
 
 
159
  with gr.Blocks(title="VINCIE Service") as demo:
160
- # Header and credits
161
  gr.Markdown(
162
  "\n".join(
163
  [
164
- "# VINCIE Service — Multi-turn Editing and Multi-concept Composition",
165
- "- Automatic setup runs at startup; setup status appears below.",
166
- "- Hardware requirement: NVIDIA L40S (SM 8.9) is recommended for this build.",
167
- "- Functional upstream model: ByteDance-Seed/VINCIE (see project repository).",
168
- "- Space and Docker were developed by Carlex.",
169
- "- Contact: Email: [email protected] | GitHub: carlex22",
170
  ]
171
  )
172
  )
173
 
174
  with gr.Row():
175
- setup_out = gr.Textbox(label="Setup Status", interactive=False)
176
 
177
- # Advanced options shared by both tabs
178
  with gr.Accordion("Opções Avançadas (para Abas 1 e 2)", open=False):
179
  steps_input = gr.Slider(
180
  label="Passos de Inferência",
@@ -203,14 +175,15 @@ with gr.Blocks(title="VINCIE Service") as demo:
203
  value=512,
204
  )
205
 
 
206
  with gr.Tab("Multi-turn Editing"):
207
  with gr.Row():
208
- img = gr.Image(type="filepath", label="Input image")
209
- turns = gr.Textbox(lines=8, label="Turns (one per line)")
210
- run1 = gr.Button("Run")
211
- out_gallery = gr.Gallery(label="Images", columns=4, height="auto")
212
- out_video = gr.Video(label="Video (if available)")
213
- out_status = gr.Textbox(label="Output", interactive=False)
214
 
215
  run1.click(
216
  ui_multi_turn,
@@ -218,14 +191,15 @@ with gr.Blocks(title="VINCIE Service") as demo:
218
  outputs=[out_gallery, out_video, out_status],
219
  )
220
 
 
221
  with gr.Tab("Multi-concept Composition"):
222
- files = gr.File(file_count="multiple", type="filepath", label="Concept images")
223
- descs = gr.Textbox(lines=8, label="Descriptions (one per line, same order as images)")
224
- final_prompt = gr.Textbox(lines=2, label="Final prompt")
225
- run2 = gr.Button("Run")
226
- out_gallery2 = gr.Gallery(label="Images", columns=4, height="auto")
227
- out_video2 = gr.Video(label="Video (if available)")
228
- out_status2 = gr.Textbox(label="Output", interactive=False)
229
 
230
  run2.click(
231
  ui_multi_concept,
@@ -233,13 +207,13 @@ with gr.Blocks(title="VINCIE Service") as demo:
233
  outputs=[out_gallery2, out_video2, out_status2],
234
  )
235
 
236
- # Auto-setup on load (no manual button)
237
  demo.load(fn=setup_auto, outputs=setup_out)
238
 
239
  if __name__ == "__main__":
240
  demo.launch(
241
- server_name="0.0.0.0",
242
- server_port=int(os.getenv("PORT", "7860")),
243
  allowed_paths=["/app/outputs", "/app/ckpt"],
 
244
  )
245
-
 
2
  """
3
  VINCIE Service UI (Gradio)
4
 
5
+ - Auto-setup na carga da interface (sem botão manual).
6
+ - Edição multi-turn e composição multi-concept com overrides avançados (steps, cfg_scale, aspect_ratio, resolution).
7
+ - Repassa parâmetros para o pipeline do VINCIE através do VincieService.
8
+ - Desenvolvido para ambientes NVIDIA L40S (SM 8.9) em CUDA 12.x.
9
+
10
+ Upstream funcional: ByteDance-Seed/VINCIE.
11
  """
12
 
13
  import os
14
+ import json
15
  from pathlib import Path
16
  from typing import List, Tuple, Optional
17
 
18
  import gradio as gr
19
 
20
+ # Serviço que prepara repositório e checkpoint, e invoca geração por CLI
21
+ from services.vincie import VincieService # ajuste o import conforme seu layout
 
 
 
 
 
22
 
23
+ # Instancia o serviço (defaults: /app/VINCIE repo e cache HF/HUB já configurado externamente)
24
  svc = VincieService()
25
 
26
+
27
  def setup_auto() -> str:
28
  """
29
+ Setup idempotente na carga da UI:
30
+ - Clona/Checa o repositório upstream.
31
+ - Baixa/Valida o checkpoint (snapshot completo) no cache HF.
 
32
  """
33
  try:
34
  svc.ensure_repo()
35
  svc.ensure_model()
36
+ if not svc.ready():
37
+ return "Setup finalizado, mas checkpoint incompleto (dit.pth/vae.pth ausentes)." # pragma: no cover
38
+ return "Setup concluído: repositório e checkpoint prontos para inferência." # ok
 
39
  except Exception as e:
40
+ return f"Erro no setup: {e}"
41
+
42
 
43
  def _list_media(out_dir: Path, max_images: int = 24) -> Tuple[List[str], Optional[str]]:
44
  """
45
+ Coleta imagens e o último .mp4 do diretório de saída.
 
 
 
 
 
 
 
46
  """
47
  img_globs = ("*.png", "*.jpg", "*.jpeg", "*.webp")
48
  images: List[Path] = []
 
54
  video_path = str(videos[-1]) if videos else None
55
  return image_paths, video_path
56
 
57
+
58
  def ui_multi_turn(
59
  input_image: Optional[str],
60
  turns_text: Optional[str],
 
64
  resolution_input: int,
65
  ):
66
  """
67
+ Handler de UI para multi-turn editing.
 
 
 
 
 
 
 
 
 
68
  """
69
  if not input_image or not str(input_image).strip():
70
+ return [], None, "Selecione uma imagem de entrada."
71
  if not turns_text or not turns_text.strip():
72
+ return [], None, "Informe instruções (uma por linha)."
73
 
74
  turns = [ln.strip() for ln in turns_text.splitlines() if ln.strip()]
75
  try:
 
82
  steps=int(steps_input) if steps_input is not None else None,
83
  )
84
  except Exception as e:
85
+ return [], None, f"Erro na geração: {e}"
86
 
87
  imgs, vid = _list_media(Path(out_dir))
88
+ status = f"Outputs salvos em: {out_dir}"
89
  return imgs, vid, status
90
 
91
+
92
  def ui_multi_concept(
93
  files: Optional[List[str]],
94
  descs_text: Optional[str],
 
99
  resolution_input: int,
100
  ):
101
  """
102
+ Handler de UI para multi-concept composition.
 
 
 
 
 
 
 
 
 
 
103
  """
104
  if not files:
105
+ return [], None, "Envie imagens de conceito."
106
  if not descs_text or not descs_text.strip():
107
+ return [], None, "Descreva os conceitos (uma linha por imagem)."
108
  if not final_prompt or not final_prompt.strip():
109
+ return [], None, "Informe um prompt final."
110
 
111
  descs = [ln.strip() for ln in descs_text.splitlines() if ln.strip()]
112
  if len(descs) != len(files):
113
+ return [], None, f"Número de descrições ({len(descs)}) deve bater com imagens ({len(files)})."
114
 
115
  try:
116
  out_dir = svc.multi_concept_compose(
 
123
  steps=int(steps_input) if steps_input is not None else None,
124
  )
125
  except Exception as e:
126
+ return [], None, f"Erro na geração: {e}"
127
 
128
  imgs, vid = _list_media(Path(out_dir))
129
+ status = f"Outputs salvos em: {out_dir}"
130
  return imgs, vid, status
131
 
132
+
133
  with gr.Blocks(title="VINCIE Service") as demo:
134
+ # Header
135
  gr.Markdown(
136
  "\n".join(
137
  [
138
+ "# VINCIE — Edição Multi-Turn e Composição Multi-Concept",
139
+ "- Setup automático é executado no carregamento; verifique o status abaixo.",
140
+ "- Requisitos: NVIDIA L40S (SM 8.9) recomendado para este build.",
141
+ "- Upstream: ByteDance-Seed/VINCIE.",
 
 
142
  ]
143
  )
144
  )
145
 
146
  with gr.Row():
147
+ setup_out = gr.Textbox(label="Status do Setup", interactive=False)
148
 
149
+ # Opções avançadas compartilhadas entre abas
150
  with gr.Accordion("Opções Avançadas (para Abas 1 e 2)", open=False):
151
  steps_input = gr.Slider(
152
  label="Passos de Inferência",
 
175
  value=512,
176
  )
177
 
178
+ # Aba 1 — Multi-turn Editing
179
  with gr.Tab("Multi-turn Editing"):
180
  with gr.Row():
181
+ img = gr.Image(type="filepath", label="Imagem de entrada")
182
+ turns = gr.Textbox(lines=8, label="Instruções (uma por linha)")
183
+ run1 = gr.Button("Gerar")
184
+ out_gallery = gr.Gallery(label="Imagens", columns=4, height="auto")
185
+ out_video = gr.Video(label="Vídeo (se houver)")
186
+ out_status = gr.Textbox(label="Saída", interactive=False)
187
 
188
  run1.click(
189
  ui_multi_turn,
 
191
  outputs=[out_gallery, out_video, out_status],
192
  )
193
 
194
+ # Aba 2 — Multi-concept Composition
195
  with gr.Tab("Multi-concept Composition"):
196
+ files = gr.File(file_count="multiple", type="filepath", label="Imagens de conceito")
197
+ descs = gr.Textbox(lines=8, label="Descrições (uma por linha, mesma ordem das imagens)")
198
+ final_prompt = gr.Textbox(lines=2, label="Prompt final")
199
+ run2 = gr.Button("Gerar")
200
+ out_gallery2 = gr.Gallery(label="Imagens", columns=4, height="auto")
201
+ out_video2 = gr.Video(label="Vídeo (se houver)")
202
+ out_status2 = gr.Textbox(label="Saída", interactive=False)
203
 
204
  run2.click(
205
  ui_multi_concept,
 
207
  outputs=[out_gallery2, out_video2, out_status2],
208
  )
209
 
210
+ # Auto-setup on load
211
  demo.load(fn=setup_auto, outputs=setup_out)
212
 
213
  if __name__ == "__main__":
214
  demo.launch(
215
+ server_name=os.getenv("GRADIO_SERVER_NAME", "0.0.0.0"),
216
+ server_port=int(os.getenv("GRADIO_SERVER_PORT", os.getenv("PORT", "7860"))),
217
  allowed_paths=["/app/outputs", "/app/ckpt"],
218
+ enable_queue=os.getenv("GRADIO_ENABLE_QUEUE", "True").lower() == "true",
219
  )