| """ |
| 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(): |
| |
| 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) |
|
|
| |
| with gr.Column(scale=1): |
| output = output_box() |
| info_panel() |
|
|
| |
| 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 |
|
|