Spaces:
Running on Zero
Running on Zero
File size: 5,127 Bytes
4ee0b66 d232d09 4ee0b66 d232d09 | 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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | import spaces # MUST come before any torch/CUDA-touching import
import torch
import gradio as gr
from transformers import Qwen3VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info
MODEL_ID = "AvaXiao/ReToken-Qwen3VL-8B"
PROCESSOR_ID = "Qwen/Qwen3-VL-8B-Instruct"
model = Qwen3VLForConditionalGeneration.from_pretrained(
MODEL_ID,
torch_dtype=torch.bfloat16,
attn_implementation="sdpa",
)
model.to("cuda")
model.eval()
processor = AutoProcessor.from_pretrained(PROCESSOR_ID, use_fast=False)
@spaces.GPU(duration=60)
def answer_question(image, question, max_new_tokens=512, temperature=0.1, top_p=0.9,
progress=gr.Progress(track_tqdm=True)):
"""Answer a visual question about an image using ReToken-Qwen3VL-8B.
Args:
image: Input image to ask a question about.
question: The question to ask about the image.
max_new_tokens: Maximum number of new tokens to generate.
temperature: Sampling temperature (lower = more deterministic).
top_p: Nucleus sampling probability.
"""
if image is None:
return "Please upload an image first."
if not question.strip():
return "Please enter a question."
messages = [
{
"role": "user",
"content": [
{"type": "image", "image": image},
{"type": "text", "text": question},
],
}
]
text = processor.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(
text=[text],
images=image_inputs,
videos=video_inputs,
padding=True,
return_tensors="pt",
)
inputs = inputs.to("cuda")
with torch.inference_mode():
output_ids = model.generate(
**inputs,
max_new_tokens=max_new_tokens,
do_sample=temperature > 0,
temperature=temperature if temperature > 0 else 1.0,
top_p=top_p,
)
# Decode only the new tokens
generated_ids = output_ids[:, inputs["input_ids"].shape[1]:]
response = processor.batch_decode(
generated_ids,
skip_special_tokens=True,
clean_up_tokenization_spaces=True,
)[0]
return response
CSS = """
#col-container { max-width: 1100px; margin: 0 auto; }
.dark .gradio-container { color: var(--body-text-color); }
"""
with gr.Blocks() as demo:
gr.Markdown(
"""
# ReToken: Visual Retrieval with Qwen3-VL-8B
This demo showcases **ReToken-Qwen3VL-8B**, a vision-language model augmented with a learned retrieval token for improved visual retrieval. Ask questions about images — the model leverages a fine-tuned Qwen3-VL-8B backbone trained with a retrieval token that improves long-context visual understanding.
[Paper](https://huggingface.co/papers/2607.28627) · [GitHub](https://github.com/avaxiao/ReToken) · [Model](https://huggingface.co/AvaXiao/ReToken-Qwen3VL-8B)
"""
)
with gr.Row(elem_id="col-container"):
with gr.Column(scale=1):
image_input = gr.Image(type="filepath", label="Input Image")
question_input = gr.Textbox(
label="Question",
placeholder="Ask a question about the image…",
lines=2,
)
run_btn = gr.Button("Answer", variant="primary")
with gr.Accordion("Advanced settings", open=False):
max_new_tokens = gr.Slider(
minimum=16, maximum=1024, value=512, step=16,
label="Max new tokens",
)
temperature = gr.Slider(
minimum=0.0, maximum=2.0, value=0.1, step=0.1,
label="Temperature (0 = greedy)",
)
top_p = gr.Slider(
minimum=0.1, maximum=1.0, value=0.9, step=0.05,
label="Top-p",
)
with gr.Column(scale=1):
output_text = gr.Textbox(
label="Answer",
lines=12,
interactive=False,
)
run_btn.click(
fn=answer_question,
inputs=[image_input, question_input, max_new_tokens, temperature, top_p],
outputs=output_text,
api_name="answer",
)
question_input.submit(
fn=answer_question,
inputs=[image_input, question_input, max_new_tokens, temperature, top_p],
outputs=output_text,
api_name="answer_submit",
)
gr.Examples(
examples=[
["example1.jpg", "What breed is this dog and what is it doing?"],
["example2.jpg", "Describe this bird's colors and habitat."],
["example3.jpg", "What is this cat looking at?"],
],
inputs=[image_input, question_input],
outputs=output_text,
fn=answer_question,
cache_examples=True,
cache_mode="lazy",
)
demo.launch(mcp_server=True, theme=gr.themes.Citrus(), css=CSS) |