Xxx / app.py
XCarleX's picture
Upload 6 files
c8a837a verified
#!/usr/bin/env python3
import os
import glob
import gradio as gr
from pathlib import Path
from typing import List, Tuple, Optional
from vincie_service import VincieService
svc = VincieService() # usa /app/VINCIE e /app/ckpt/VINCIE-3B por padrão
def setup() -> str:
"""
Prepara repositório e modelos (idempotente).
"""
try:
svc.ensure_repo()
svc.ensure_model()
except Exception as e:
return f"Setup falhou: {e}"
return "Setup OK"
def _list_media(out_dir: Path, max_images: int = 24) -> Tuple[List[str], Optional[str]]:
"""
Varre o diretório de saída por imagens e vídeo, retornando caminhos ordenados.
"""
exts_img = ("*.png", "*.jpg", "*.jpeg", "*.webp")
imgs: List[Path] = []
for pat in exts_img:
imgs += list(out_dir.rglob(pat))
imgs = sorted(imgs, key=lambda p: p.stat().st_mtime)
imgs_paths = [str(p) for p in imgs[-max_images:]] if imgs else []
vids = sorted(out_dir.rglob("*.mp4"), key=lambda p: p.stat().st_mtime)
vid_path = str(vids[-1]) if vids else None
return imgs_paths, vid_path
def ui_multi_turn(input_image, turns_text):
"""
Executa multi-turn editing e retorna mídia do diretório de saída.
"""
if not input_image or not str(input_image).strip():
return [], None, "Forneça uma imagem."
if not turns_text or not turns_text.strip():
return [], None, "Forneça turns (um por linha)."
turns = [ln.strip() for ln in turns_text.splitlines() if ln.strip()]
try:
out_dir = svc.multi_turn_edit(input_image, turns)
except Exception as e:
return [], None, f"Erro na geração: {e}"
imgs, vid = _list_media(Path(out_dir))
status = f"Gerado em: {str(out_dir)}"
return imgs, vid, status
def ui_multi_concept(files, descs_text, final_prompt):
"""
Executa composição multi-conceito e retorna mídia do diretório de saída.
"""
if not files:
return [], None, "Envie imagens de conceito."
if not descs_text or not descs_text.strip():
return [], None, "Forneça descrições (uma por linha)."
if not final_prompt or not final_prompt.strip():
return [], None, "Forneça o prompt final."
descs = [ln.strip() for ln in descs_text.splitlines() if ln.strip()]
if len(descs) != len(files):
return [], None, f"Número de descrições ({len(descs)}) difere do número de imagens ({len(files)})."
try:
out_dir = svc.multi_concept_compose(files, descs, final_prompt)
except Exception as e:
return [], None, f"Erro na geração: {e}"
imgs, vid = _list_media(Path(out_dir))
status = f"Gerado em: {str(out_dir)}"
return imgs, vid, status
with gr.Blocks(title="VINCIE Service") as demo:
gr.Markdown("# 🎨 VINCIE Service — Multi-turn e Multi-concept")
with gr.Row():
setup_btn = gr.Button("Preparar (repo + modelos)")
setup_out = gr.Textbox(label="Status", interactive=False)
setup_btn.click(fn=setup, outputs=setup_out)
with gr.Tab("🔄 Multi-turn Editing"):
with gr.Row():
img = gr.Image(type="filepath", label="Imagem inicial")
turns = gr.Textbox(lines=8, label="Turns (um por linha)")
run1 = gr.Button("Executar")
out_gallery = gr.Gallery(label="Imagens", columns=4, height="auto")
out_video = gr.Video(label="Vídeo (se houver)")
out_status = gr.Textbox(label="Saída", interactive=False)
run1.click(ui_multi_turn, inputs=[img, turns], outputs=[out_gallery, out_video, out_status])
with gr.Tab("🧩 Multi-concept Compose"):
files = gr.File(file_count="multiple", type="filepath", label="Imagens de conceito")
descs = gr.Textbox(lines=8, label="Descrições (uma por linha, na mesma ordem das imagens)")
final_prompt = gr.Textbox(lines=2, label="Prompt final")
run2 = gr.Button("Executar")
out_gallery2 = gr.Gallery(label="Imagens", columns=4, height="auto")
out_video2 = gr.Video(label="Vídeo (se houver)")
out_status2 = gr.Textbox(label="Saída", interactive=False)
run2.click(ui_multi_concept, inputs=[files, descs, final_prompt], outputs=[out_gallery2, out_video2, out_status2])
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=int(os.getenv("PORT", "7860")),
allowed_paths=["/app/outputs", "/app/ckpt"]
)