Spaces:
Running on Zero
Running on Zero
File size: 5,355 Bytes
c9780e6 e83d360 a083e2f e83d360 58b77b1 e83d360 36dff58 56b5c79 1e1ee77 56b5c79 8e9f8c2 edca60d 8d31456 edca60d e83d360 e43fc9e a083e2f e43fc9e edca60d 36ae991 c9780e6 81f91cc 0119d95 81f91cc 0119d95 9c917c1 edca60d 9c917c1 c9780e6 9c917c1 a083e2f 9c917c1 a083e2f 9c917c1 e43fc9e 9c917c1 e83d360 a083e2f 36ae991 9c917c1 a2b5338 e43fc9e edca60d c9780e6 a2b5338 dc42813 e83d360 0119d95 | 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 | import json
import gradio as gr
import spaces, torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from PIL import Image
from typing import Literal
# @spaces.GPU(duration=30)
def load_model():
# moondream2
# return AutoModelForCausalLM.from_pretrained(
# "vikhyatk/moondream2",
# revision="2025-04-14",
# trust_remote_code=True,
# device_map={"": "cuda"},
# )
# moondream3-preview
moondream = AutoModelForCausalLM.from_pretrained(
"moondream/moondream3-preview",
trust_remote_code=True,
dtype=torch.bfloat16,
device_map={"": "cuda"},
)
moondream.compile()
return moondream
_MODEL_ZOO = {
"moondream3-preview": load_model(), # calling spaces.GPU decorated functions outside ZeroGPU scope will cause a PickingError
"moondream2": AutoModelForCausalLM.from_pretrained(
"vikhyatk/moondream2",
revision="2025-06-21",
trust_remote_code=True,
device_map={"": "cuda"},
),
}
@spaces.GPU(duration=30)
def detect(
im: Image.Image,
object_name: str,
mode: Literal["point", "object_detection", "query"],
model_name: Literal["moondream2", "moondream3-preview"] = "moondream3-preview",
reasoning: bool = False,
settings: dict = {"temperature": 0.0, "top_p": 0.95, "max_tokens": 512},
) -> list[dict] | dict:
"""Open-vocabulary object localization and visual question answering with the Moondream vision-language model. The shape of the returned JSON depends on the "mode" argument. In "point" mode it returns a JSON list with one entry per located instance of "object_name"; each entry is an object {"x": float, "y": float} giving that instance's center as coordinates NORMALIZED to 0.0-1.0 of the input image (x is fraction of width from the left edge, y is fraction of height from the top edge). In "object_detection" mode it returns a JSON list with one entry per located instance; each entry is a bounding box {"x_min": float, "y_min": float, "x_max": float, "y_max": float} where all four values are NORMALIZED to 0.0-1.0 of the ORIGINAL input image ("x_min"/"y_min" is the top-left corner, "x_max"/"y_max" is the bottom-right corner) -- this is the albumentations "albumentations" bounding-box format (normalized [x_min, y_min, x_max, y_max]), documented at https://albumentations.ai/docs/3-basic-usage/bounding-boxes-augmentations/#bounding-box-formats -- values are NOT absolute pixels and the box is NOT [x, y, width, height]. In "query" mode it returns a JSON object {"answer": string} answering "object_name" as a natural-language question about the image.
Args:
im: The RGB image to run detection or answer a question about.
object_name: In "point"/"object_detection" mode, the open-vocabulary name of the object to locate (e.g. "person", "red car"); in "query" mode, the natural-language question to ask about the image.
mode: "point" returns normalized center points, "object_detection" returns normalized bounding boxes, "query" returns a text answer.
model_name: Which Moondream checkpoint to run: "moondream3-preview" (default, more capable) or "moondream2".
reasoning: Enable chain-of-thought reasoning; only applies to "query" mode on the moondream3-preview model and is ignored otherwise.
settings: Inference parameters as a JSON object; for "query" mode use "temperature"/"top_p"/"max_tokens", for "point"/"object_detection" use "max_objects"; ignored for the moondream2 model.
"""
model = _MODEL_ZOO[model_name]
is_v2 = model_name == "moondream2"
if isinstance(settings, str):
settings = json.loads(settings)
inf_params = {} if is_v2 else {"settings": settings}
if not is_v2 and mode == "query":
inf_params["reasoning"] = reasoning
if mode == "point":
return model.point(im, object_name, **inf_params)["points"]
elif mode == "object_detection":
return model.detect(im, object_name, **inf_params)["objects"]
elif mode == "query":
return model.query(im, object_name, **inf_params)
demo = gr.Interface(
fn=detect,
title="moondream-pointer",
description="using [moondream3-preview](https://huggingface.co/moondream/moondream3-preview) and [moondream2](https://huggingface.co/vikhyatk/moondream2) for object grounding",
inputs=[
gr.Image(label="Input Image", type="pil"),
gr.Textbox(
label="Object / Question",
info="object to detector (for points / object_detection) or question for a query",
),
gr.Dropdown(label="Mode", choices=["point", "object_detection", "query"]),
gr.Dropdown(label="Model Variant", choices=list(_MODEL_ZOO.keys())),
gr.Checkbox(
label="Reasoning",
value=False,
info="enable [chain-of-thought](https://huggingface.co/moondream/moondream3-preview#query) (query mode only)",
),
gr.Textbox(
label="Settings (JSON)",
value='{"temperature": 0.0, "top_p": 0.95, "max_tokens": 512}',
info="query: temperature / top_p / max_tokens Β· point & object_detection: max_objects",
),
],
outputs=gr.JSON(label="Output JSON"),
)
demo.launch(
mcp_server=True, app_kwargs={"docs_url": "/docs"} # add FastAPI Swagger API Docs
)
|