File size: 2,823 Bytes
dda6bed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
ui/app.py β€” Gradio layout.

This file is pure layout β€” no inference logic lives here.
All intelligence is in core/api_client.py.
"""

import gradio as gr

from core import stream_description
from ui.components import (
    image_upload,
    prompt_box,
    model_selector,
    generation_settings,
    api_key_field,
    prompt_examples,
    output_box,
    info_panel,
)

CSS = """
#title        { text-align: center; }
#submit       { background: #6366f1; color: white; }
#submit:hover { background: #4f46e5; }
#model-hint   { font-size: 0.85em; opacity: 0.75; }
footer        { display: none !important; }
"""


def build_ui() -> gr.Blocks:
    with gr.Blocks(
        title="MiniCPM-V Β· API Image Describer",
        theme=gr.themes.Soft(),
        css=CSS,
    ) as demo:

        gr.Markdown(
            "# πŸ” MiniCPM-V 4.6 Β· Image Description via API\n"
            "**No downloads. No GPU needed.** Calls OpenBMB's hosted API β€” "
            "results stream back in real time.\n\n"
            "> Models: `MiniCPM-V-4.6-Instruct` & `MiniCPM-V-4.6-Thinking` Β· "
            "1.3 B params each Β· well under the 32 B cap Β· Apache-2.0",
            elem_id="title",
        )

        with gr.Row():
            # ── Left column β€” inputs ──────────────────────────────────────────
            with gr.Column(scale=1):
                image   = image_upload()
                prompt  = prompt_box()
                model   = model_selector()

                gr.Markdown(
                    "**Instruct** β€” direct, concise answer.  \n"
                    "**Thinking** β€” reasons step-by-step first (slower, more thorough).",
                    elem_id="model-hint",
                )

                max_tokens, temperature = generation_settings()
                api_key = api_key_field()

                submit = gr.Button(
                    "β–Ά Describe Image", variant="primary", elem_id="submit"
                )
                prompt_examples(prompt)

            # ── Right column β€” output ─────────────────────────────────────────
            with gr.Column(scale=1):
                output = output_box()
                info_panel()

        # ── Event wiring ──────────────────────────────────────────────────────
        inputs  = [image, prompt, model, max_tokens, temperature, api_key]
        outputs = [output]

        submit.click(fn=stream_description, inputs=inputs, outputs=outputs)
        prompt.submit(fn=stream_description, inputs=inputs, outputs=outputs)

    return demo