yuhangzang commited on
Commit
f42ad7c
·
1 Parent(s): 1a6fc68

Add CapRL-Qwen3VL-4B space with LFS for images

Browse files
Files changed (7) hide show
  1. .gitattributes +4 -0
  2. README.md +38 -4
  3. app.py +246 -0
  4. examples/1909.png +3 -0
  5. examples/44687.jpeg +3 -0
  6. examples/natural.png +3 -0
  7. requirements.txt +8 -0
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ examples/natural.png filter=lfs diff=lfs merge=lfs -text
37
+ examples/*.png filter=lfs diff=lfs merge=lfs -text
38
+ examples/*.jpeg filter=lfs diff=lfs merge=lfs -text
39
+ examples/*.jpg filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,12 +1,46 @@
1
  ---
2
- title: CapRL Qwen3VL 4B
3
- emoji: 👀
4
- colorFrom: gray
5
  colorTo: purple
6
  sdk: gradio
7
- sdk_version: 6.2.0
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: CapRL-Qwen3VL-4B
3
+ emoji: 🎨
4
+ colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 5.49.1
8
  app_file: app.py
9
  pinned: false
10
+ license: apache-2.0
11
  ---
12
 
13
+ # CapRL-Qwen3VL-4B Image Captioning
14
+
15
+ This Space demonstrates **CapRL-Qwen3VL-4B**, a 4B parameter multimodal vision-language model fine-tuned using reinforcement learning for dense image captioning.
16
+
17
+ ## Model
18
+
19
+ - **Model**: [internlm/CapRL-Qwen3VL-4B](https://huggingface.co/internlm/CapRL-Qwen3VL-4B)
20
+ - **Architecture**: Based on Qwen3-VL
21
+ - **Task**: Dense Image Captioning
22
+
23
+ ## Usage
24
+
25
+ Upload an image or select from the examples to generate a detailed caption.
26
+
27
+ ## Links
28
+
29
+ - [Paper](https://arxiv.org/abs/2509.22647)
30
+ - [GitHub](https://github.com/InternLM/CapRL)
31
+ - [CapRL-3B Model](https://huggingface.co/internlm/CapRL-3B)
32
+ - [CapRL-2M Dataset](https://huggingface.co/datasets/internlm/CapRL-2M)
33
+ - [CapRL Collection](https://huggingface.co/collections/long-xing1/caprl-68d64ac32ded31596c36e189)
34
+
35
+ ## Citation
36
+
37
+ ```bibtex
38
+ @article{xing2025caprl,
39
+ title={{CapRL}: Stimulating Dense Image Caption Capabilities via Reinforcement Learning},
40
+ author={Xing, Long and Dong, Xiaoyi and Zang, Yuhang and Cao, Yuhang and Liang, Jianze and Huang, Qidong and Wang, Jiaqi and Wu, Feng and Lin, Dahua},
41
+ journal={arXiv preprint arXiv:2509.22647},
42
+ year={2025}
43
+ }
44
+ ```
45
+
46
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import spaces
3
+ import torch
4
+ from PIL import Image
5
+ from transformers import Qwen3VLForConditionalGeneration, AutoProcessor
6
+
7
+ MODEL_ID = "internlm/CapRL-Qwen3VL-4B"
8
+ DEFAULT_PROMPT = "Describe the image in detail."
9
+ MAX_NEW_TOKENS = 4096
10
+
11
+ # Default demo content
12
+ DEFAULT_IMAGE = "./examples/1909.png"
13
+ DEFAULT_CAPTION = (
14
+ "The image is a bar chart from the Pew Research Center that illustrates how older Republicans and Republican leaners view Donald Trump, specifically focusing on how many describe the phrase \"fights for what I believe in\" to describe Trump. The data is based on a survey conducted from February 4-15, 2020, among U.S. adults who identify as Republicans or Republican-leaning independents.\n\n"
15
+ "### Title:\n"
16
+ "Older Republicans especially likely to see Trump as fighting for their beliefs\n\n"
17
+ "### Main Question:\n"
18
+ "Among Republicans and Republican leaners, % who say the phrase 'fights for what I believe in' describes Trump ...\n\n"
19
+ "### Data Breakdown:\n\n"
20
+ "1. **All Rep/Lean Rep (Overall):**\n"
21
+ " - Very well: 51%\n"
22
+ " - Fairly well: 36%\n"
23
+ " - NET: 87%\n\n"
24
+ "2. **Ages 18-29:**\n"
25
+ " - Very well: 31%\n"
26
+ " - Fairly well: 45%\n"
27
+ " - NET: 76%\n\n"
28
+ "3. **30-49:**\n"
29
+ " - Very well: 41%\n"
30
+ " - Fairly well: 42%\n"
31
+ " - NET: 82%\n\n"
32
+ "4. **50-64:**\n"
33
+ " - Very well: 58%\n"
34
+ " - Fairly well: 33%\n"
35
+ " - NET: 92%\n\n"
36
+ "5. **65+:**\n"
37
+ " - Very well: 68%\n"
38
+ " - Fairly well: 26%\n"
39
+ " - NET: 94%\n\n"
40
+ "6. **Postgrad:**\n"
41
+ " - Very well: 42%\n"
42
+ " - Fairly well: 38%\n"
43
+ " - NET: 80%\n\n"
44
+ "7. **College grad:**\n"
45
+ " - Very well: 45%\n"
46
+ " - Fairly well: 40%\n"
47
+ " - NET: 85%\n\n"
48
+ "8. **Some college:**\n"
49
+ " - Very well: 51%\n"
50
+ " - Fairly well: 36%\n"
51
+ " - NET: 87%\n\n"
52
+ "9. **HS or less:**\n"
53
+ " - Very well: 56%\n"
54
+ " - Fairly well: 33%\n"
55
+ " - NET: 89\n\n"
56
+ "10. **Conserv (Conservative):**\n"
57
+ " - Very well: 63%\n"
58
+ " - Fairly well: 31%\n"
59
+ " - NET: 94%\n\n"
60
+ "11. **Mod/Lib (Moderate/Liberal):**\n"
61
+ " - Very well: 32%\n"
62
+ " - Fairly well: 44%\n"
63
+ " - NET: 75\n\n"
64
+ "12. **Republican:**\n"
65
+ " - Very well: 61%\n"
66
+ " - Fairly well: 32%\n"
67
+ " - NET: 93\n\n"
68
+ "13. **Lean Republican:**\n"
69
+ " - Very well: 36%\n"
70
+ " - Fairly well: 41%\n"
71
+ " - NET: 77\n\n"
72
+ "### Notes:\n"
73
+ "- The note at the bottom states that the data is based on Republicans and Republican-leaning independents.\n"
74
+ "- The source is a survey of U.S. adults conducted from February 4-15, 2020.\n\n"
75
+ "### Key Observations:\n"
76
+ "1. Older Republicans (65+) are the most likely to see Trump as someone who \"fights for what I believe in,\" with a net positive percentage of 94.\n"
77
+ "2. Younger age groups (18-29) have the lowest net positive percentage at 76.\n"
78
+ "3. Those with higher educational backgrounds (postgrad and college grad) have slightly lower net positive percentages compared to those with some college education (80 vs. 85).\n"
79
+ "4. Conservatives (63% very well) are the most likely to see Trump this way, followed by Republicans (61%).\n"
80
+ "5. Lean Republicans (36% very well) have the lowest percentage among the leaner categories.\n\n"
81
+ "This detailed description should provide a pure text model with sufficient information to answer any related questions about the image."
82
+ )
83
+ DEFAULT_CAPTION_TOKENS = 826
84
+
85
+
86
+ def get_device() -> str:
87
+ return "cuda" if torch.cuda.is_available() else "cpu"
88
+
89
+
90
+ def select_dtype(device: str):
91
+ if device == "cuda":
92
+ if torch.cuda.is_bf16_supported():
93
+ return torch.bfloat16
94
+ return torch.float16
95
+ return torch.float32
96
+
97
+
98
+ def load_model():
99
+ device = get_device()
100
+ dtype = select_dtype(device)
101
+
102
+ # Use device_map="auto" for proper GPU allocation with spaces.GPU decorator
103
+ model = Qwen3VLForConditionalGeneration.from_pretrained(
104
+ MODEL_ID,
105
+ torch_dtype=dtype,
106
+ device_map="auto",
107
+ trust_remote_code=True,
108
+ )
109
+
110
+ processor = AutoProcessor.from_pretrained(MODEL_ID, trust_remote_code=True)
111
+ return model, processor
112
+
113
+
114
+ MODEL, PROCESSOR = load_model()
115
+
116
+
117
+ @spaces.GPU
118
+ @torch.inference_mode()
119
+ def generate_caption(image: Image.Image):
120
+ if image is None:
121
+ return "", 0
122
+
123
+ try:
124
+ # Validate image
125
+ if not isinstance(image, Image.Image):
126
+ return "Error: Invalid image format", 0
127
+
128
+ # Check image size (warn if too large)
129
+ max_size = 4096
130
+ if image.width > max_size or image.height > max_size:
131
+ # Resize if too large to prevent OOM
132
+ image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
133
+
134
+ device = MODEL.device
135
+ messages = [
136
+ {
137
+ "role": "user",
138
+ "content": [
139
+ {"type": "image", "image": image},
140
+ {"type": "text", "text": DEFAULT_PROMPT},
141
+ ],
142
+ }
143
+ ]
144
+
145
+ # Preparation for inference using Qwen3-VL style
146
+ inputs = PROCESSOR.apply_chat_template(
147
+ messages,
148
+ tokenize=True,
149
+ add_generation_prompt=True,
150
+ return_dict=True,
151
+ return_tensors="pt",
152
+ )
153
+ inputs = inputs.to(device)
154
+
155
+ generated_ids = MODEL.generate(
156
+ **inputs,
157
+ max_new_tokens=MAX_NEW_TOKENS,
158
+ do_sample=False,
159
+ )
160
+
161
+ generated_ids_trimmed = [
162
+ out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
163
+ ]
164
+ output_text = PROCESSOR.batch_decode(
165
+ generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
166
+ )
167
+ caption = output_text[0].strip()
168
+
169
+ input_ids = inputs.get("input_ids")
170
+ input_length = input_ids.shape[-1] if input_ids is not None else 0
171
+ total_length = generated_ids.shape[-1]
172
+ num_generated_tokens = max(total_length - input_length, 0)
173
+
174
+ return caption, int(num_generated_tokens)
175
+
176
+ except torch.cuda.OutOfMemoryError:
177
+ torch.cuda.empty_cache()
178
+ return "Error: Out of GPU memory. Please try with a smaller image.", 0
179
+ except Exception as e:
180
+ return f"Error generating caption: {str(e)}", 0
181
+
182
+
183
+ with gr.Blocks(title="CapRL-Qwen3VL-4B Image Captioning") as demo:
184
+ gr.Markdown("# CapRL-Qwen3VL-4B for Image Captioning")
185
+ gr.Markdown("### CapRL: Stimulating Dense Image Caption Capabilities via Reinforcement Learning")
186
+ gr.Markdown("Upload an image to generate a detailed caption with CapRL-Qwen3VL-4B!")
187
+ gr.Markdown(
188
+ """
189
+ <a href="https://arxiv.org/abs/2509.22647">Paper</a> | <a href="https://github.com/InternLM/CapRL">Github</a> | <a href="https://huggingface.co/internlm/CapRL-Qwen3VL-4B">CapRL-Qwen3VL-4B Model</a> | <a href="https://huggingface.co/internlm/CapRL-3B">CapRL-3B Model</a> |
190
+ <a href="https://huggingface.co/datasets/internlm/CapRL-2M">CapRL-2M Dataset</a>
191
+
192
+ <a href="https://huggingface.co/collections/long-xing1/caprl-68d64ac32ded31596c36e189">CapRL Collection</a> | <a href="https://huggingface.co/papers/2509.22647">Daily Paper</a>
193
+ """
194
+ )
195
+
196
+ with gr.Row():
197
+ with gr.Column():
198
+ # Preload a default image to match the provided caption
199
+ image_input = gr.Image(type="pil", label="Input Image", value=Image.open(DEFAULT_IMAGE))
200
+ generate_button = gr.Button("Generate Caption")
201
+ with gr.Column():
202
+ # Show a default caption and its token count on load
203
+ caption_output = gr.Textbox(label="Caption", lines=6, value=DEFAULT_CAPTION)
204
+ token_output = gr.Number(label="Generated Tokens", precision=0, value=DEFAULT_CAPTION_TOKENS)
205
+
206
+ generate_button.click(
207
+ fn=generate_caption,
208
+ inputs=image_input,
209
+ outputs=[caption_output, token_output],
210
+ show_progress=True,
211
+ )
212
+
213
+ image_input.upload(
214
+ fn=generate_caption,
215
+ inputs=image_input,
216
+ outputs=[caption_output, token_output],
217
+ show_progress=True,
218
+ )
219
+
220
+ gr.Examples(
221
+ examples=[
222
+ ["./examples/1909.png"],
223
+ ["./examples/44687.jpeg"],
224
+ ["./examples/natural.png"],
225
+ ],
226
+ inputs=image_input,
227
+ outputs=[caption_output, token_output],
228
+ fn=generate_caption,
229
+ cache_examples=True,
230
+ label="Example Images"
231
+ )
232
+
233
+ gr.Markdown("### Citation")
234
+ gr.Markdown("If you find this project useful, please kindly cite:")
235
+
236
+ citation_text = """@article{xing2025caprl,
237
+ title={{CapRL}: Stimulating Dense Image Caption Capabilities via Reinforcement Learning},
238
+ author={Xing, Long and Dong, Xiaoyi and Zang, Yuhang and Cao, Yuhang and Liang, Jianze and Huang, Qidong and Wang, Jiaqi and Wu, Feng and Lin, Dahua},
239
+ journal={arXiv preprint arXiv:2509.22647},
240
+ year={2025}
241
+ }"""
242
+
243
+ gr.Code(value=citation_text, language="markdown", label="BibTeX Citation")
244
+
245
+
246
+ demo.launch()
examples/1909.png ADDED

Git LFS Details

  • SHA256: 54ddd8eb81ae84c52add25beca7c5ea9b74d895fe440b64b776b87867765d27a
  • Pointer size: 131 Bytes
  • Size of remote file: 207 kB
examples/44687.jpeg ADDED

Git LFS Details

  • SHA256: 138d38df0fa796ec6e8788792d513e02618a8b853acfb61456f49b9397a44128
  • Pointer size: 131 Bytes
  • Size of remote file: 291 kB
examples/natural.png ADDED

Git LFS Details

  • SHA256: ac53f860f38dc2cbaf178c9679a60b2cd443393ed97a4dd8ea49dcfd131ff53e
  • Pointer size: 133 Bytes
  • Size of remote file: 15.5 MB
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ gradio==5.49.1
2
+ spaces
3
+ transformers
4
+ torch
5
+ accelerate
6
+ torchvision
7
+ Pillow
8
+ sentencepiece