File size: 4,437 Bytes
26102fe
c8a837a
 
8ca7229
26102fe
c8a837a
 
26102fe
8ca7229
c8a837a
8ca7229
c8a837a
 
 
 
8ca7229
26102fe
 
8ca7229
26102fe
 
 
c8a837a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26102fe
c8a837a
 
 
 
 
 
 
 
26102fe
c8a837a
 
 
 
 
 
 
 
26102fe
 
c8a837a
 
 
 
 
 
 
 
 
 
26102fe
 
c8a837a
 
 
 
 
 
 
 
 
 
26102fe
 
c8a837a
 
 
 
 
26102fe
 
 
c8a837a
 
 
26102fe
c8a837a
 
 
 
26102fe
c8a837a
 
 
 
26102fe
c8a837a
 
 
 
8ca7229
 
c8a837a
 
 
 
59c5b81
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
#!/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"]
    )