Video-Text-to-Text
MLX
Safetensors
English
qwen2_vl
apple-silicon
video-captioning
qwen2-vl
tarsier
4-bit precision
Instructions to use viavicdev/Tarsier2-Recap-7b-MLX-4bit with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use viavicdev/Tarsier2-Recap-7b-MLX-4bit with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir Tarsier2-Recap-7b-MLX-4bit viavicdev/Tarsier2-Recap-7b-MLX-4bit
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
Model card: redact conversion recipe, correct sizes/usage, add measured example
Browse files- Conversion section generalised; exact key remaps, failing handler, config reconstruction and convert command removed
- Sizes corrected: weights 5.64 GB / repo 5.65 GB (was a single '~5.3 GB')
- Usage fixed: generate() returns GenerationResult -> print(result.text)
- Versions: verified on mlx-vlm 0.6.8 (was an unverified '0.6.3 or later')
- Added measured example on CC0 test footage + note on packed 4-bit param count
- base_model_relation: quantized set explicitly
README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
base_model: omni-research/Tarsier2-Recap-7b
|
|
|
|
| 4 |
pipeline_tag: video-text-to-text
|
| 5 |
library_name: mlx
|
| 6 |
language:
|
|
@@ -11,37 +12,42 @@ tags:
|
|
| 11 |
- video-captioning
|
| 12 |
- qwen2-vl
|
| 13 |
- tarsier
|
|
|
|
| 14 |
---
|
| 15 |
|
| 16 |
# Tarsier2-Recap-7b-MLX-4bit
|
| 17 |
|
| 18 |
A 4-bit [MLX](https://github.com/ml-explore/mlx) conversion of
|
| 19 |
[omni-research/Tarsier2-Recap-7b](https://huggingface.co/omni-research/Tarsier2-Recap-7b),
|
| 20 |
-
prepared for
|
| 21 |
|
| 22 |
-
Tarsier2
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
- **Base model:** omni-research/Tarsier2-Recap-7b (Apache-2.0)
|
| 27 |
- **Format:** MLX, 4-bit affine quantization (group size 64)
|
| 28 |
-
- **
|
| 29 |
-
- **
|
| 30 |
-
- **
|
|
|
|
| 31 |
|
| 32 |
-
##
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
architectural features — rather than generic scene summaries. On Apple Silicon,
|
| 37 |
-
the practical way to run a 7B vision-language model at usable speed is MLX
|
| 38 |
-
4-bit; the full bf16 weights under `transformers` on MPS are prohibitively slow
|
| 39 |
-
(hundreds of seconds per clip). This conversion reduces inference to
|
| 40 |
-
approximately **7 seconds per short clip** on an M4 Pro.
|
| 41 |
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
-
|
| 45 |
|
| 46 |
```python
|
| 47 |
from mlx_vlm import load, generate
|
|
@@ -50,83 +56,115 @@ from mlx_vlm.prompt_utils import apply_chat_template
|
|
| 50 |
model, processor = load("viavicdev/Tarsier2-Recap-7b-MLX-4bit")
|
| 51 |
|
| 52 |
# Provide the video as a list of extracted frame images (see note 1)
|
| 53 |
-
frames = ["
|
|
|
|
| 54 |
prompt = apply_chat_template(
|
| 55 |
processor, model.config,
|
| 56 |
"Describe this video in detail.",
|
| 57 |
-
num_images=len(frames),
|
| 58 |
)
|
| 59 |
-
|
|
|
|
| 60 |
model, processor, prompt,
|
| 61 |
-
image=frames,
|
| 62 |
max_tokens=300,
|
| 63 |
temperature=0.3,
|
| 64 |
-
repetition_penalty=1.3,
|
| 65 |
repetition_context_size=40,
|
| 66 |
)
|
| 67 |
-
print(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
```
|
| 69 |
|
| 70 |
### Practical notes
|
| 71 |
|
| 72 |
-
1. **
|
| 73 |
-
|
| 74 |
-
frames with ffmpeg and
|
| 75 |
-
`num_images
|
| 76 |
2. **The chat template is included** in this repository (`chat_template.json`
|
| 77 |
-
and `chat_template.jinja`). Some MLX repackings omit it, which
|
| 78 |
-
`apply_chat_template`
|
| 79 |
3. **Apply a repetition penalty.** At 4-bit precision the model can occasionally
|
| 80 |
-
loop.
|
| 81 |
-
|
| 82 |
-
clips degenerated without a penalty and none did with it.
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
##
|
| 85 |
|
| 86 |
-
|
| 87 |
-
`model_type: llava`, but its text and vision towers are Qwen2-VL weights under
|
| 88 |
-
different key names. The `mlx-vlm` llava handler does not support Qwen2-VL's
|
| 89 |
-
mRoPE (it raises `rope_scaling type only supports linear`), whereas the
|
| 90 |
-
`qwen2_vl` handler does. The conversion therefore consists of a key-remap into
|
| 91 |
-
the native Qwen2-VL layout, followed by a standard MLX quantization.
|
| 92 |
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
-
|
| 96 |
-
language_model.model.* -> model.*
|
| 97 |
-
language_model.lm_head.* -> lm_head.*
|
| 98 |
-
vision_tower.* -> visual.*
|
| 99 |
-
```
|
| 100 |
|
| 101 |
-
A
|
| 102 |
-
|
| 103 |
-
|
|
|
|
|
|
|
| 104 |
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
|
|
|
| 108 |
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
|
| 114 |
## Limitations
|
| 115 |
|
| 116 |
-
- 4-bit quantization trades some fidelity for reduced size and higher speed.
|
| 117 |
For maximum quality, use the original bf16 weights on a CUDA device.
|
| 118 |
-
-
|
| 119 |
-
|
| 120 |
-
- Vision only (no audio). It captions what is seen, not what is heard.
|
| 121 |
-
-
|
| 122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
|
| 124 |
## License and attribution
|
| 125 |
|
| 126 |
-
This conversion inherits the **Apache-2.0** license of the base model.
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
| 131 |
|
| 132 |
-
When citing Tarsier2,
|
|
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
base_model: omni-research/Tarsier2-Recap-7b
|
| 4 |
+
base_model_relation: quantized
|
| 5 |
pipeline_tag: video-text-to-text
|
| 6 |
library_name: mlx
|
| 7 |
language:
|
|
|
|
| 12 |
- video-captioning
|
| 13 |
- qwen2-vl
|
| 14 |
- tarsier
|
| 15 |
+
- 4-bit
|
| 16 |
---
|
| 17 |
|
| 18 |
# Tarsier2-Recap-7b-MLX-4bit
|
| 19 |
|
| 20 |
A 4-bit [MLX](https://github.com/ml-explore/mlx) conversion of
|
| 21 |
[omni-research/Tarsier2-Recap-7b](https://huggingface.co/omni-research/Tarsier2-Recap-7b),
|
| 22 |
+
prepared for native inference on Apple Silicon.
|
| 23 |
|
| 24 |
+
Tarsier2-Recap-7b produces unusually specific, grounded video descriptions — it
|
| 25 |
+
tends to name concrete details rather than summarise a scene generically. No
|
| 26 |
+
official MLX build exists. This repository provides one: the same weights,
|
| 27 |
+
quantized to 4-bit and run on the Mac GPU through MLX.
|
| 28 |
+
|
| 29 |
+
> The underlying model is in the Qwen2-VL 7B class. Hugging Face may display a
|
| 30 |
+
> lower automatic parameter count (~1.9 B) because MLX 4-bit weights are packed
|
| 31 |
+
> into 32-bit integers.
|
| 32 |
|
| 33 |
- **Base model:** omni-research/Tarsier2-Recap-7b (Apache-2.0)
|
| 34 |
- **Format:** MLX, 4-bit affine quantization (group size 64)
|
| 35 |
+
- **Model weights:** approximately 5.64 GB / 5.25 GiB (two safetensors shards)
|
| 36 |
+
- **Complete repository:** approximately 5.65 GB / 5.26 GiB
|
| 37 |
+
- **Underlying architecture:** Qwen2-VL 7B (see conversion notes)
|
| 38 |
+
- **Not retrained or fine-tuned** — format conversion and quantization only
|
| 39 |
|
| 40 |
+
## Requirements
|
| 41 |
|
| 42 |
+
Verified with [`mlx-vlm`](https://github.com/Blaizzy/mlx-vlm) 0.6.8 on macOS
|
| 43 |
+
15.7.2, Python 3.12, `mlx` 0.32.0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
+
```bash
|
| 46 |
+
pip install mlx-vlm==0.6.8
|
| 47 |
+
brew install ffmpeg # for extracting frames
|
| 48 |
+
```
|
| 49 |
|
| 50 |
+
## Usage
|
| 51 |
|
| 52 |
```python
|
| 53 |
from mlx_vlm import load, generate
|
|
|
|
| 56 |
model, processor = load("viavicdev/Tarsier2-Recap-7b-MLX-4bit")
|
| 57 |
|
| 58 |
# Provide the video as a list of extracted frame images (see note 1)
|
| 59 |
+
frames = ["frame_01.jpg", "frame_02.jpg", "frame_03.jpg", "frame_04.jpg"]
|
| 60 |
+
|
| 61 |
prompt = apply_chat_template(
|
| 62 |
processor, model.config,
|
| 63 |
"Describe this video in detail.",
|
| 64 |
+
num_images=len(frames), # must match len(frames)
|
| 65 |
)
|
| 66 |
+
|
| 67 |
+
result = generate(
|
| 68 |
model, processor, prompt,
|
| 69 |
+
image=frames, # parameter is image= (not images=)
|
| 70 |
max_tokens=300,
|
| 71 |
temperature=0.3,
|
| 72 |
+
repetition_penalty=1.3, # see note 3
|
| 73 |
repetition_context_size=40,
|
| 74 |
)
|
| 75 |
+
print(result.text) # .text — generate() returns a GenerationResult
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
Extract frames with ffmpeg, for example eight evenly spaced frames from a clip
|
| 79 |
+
of known duration `D`:
|
| 80 |
+
|
| 81 |
+
```bash
|
| 82 |
+
ffmpeg -i clip.mp4 -vf "fps=8/D,scale=-2:448" -frames:v 8 -q:v 2 frame_%02d.jpg
|
| 83 |
```
|
| 84 |
|
| 85 |
### Practical notes
|
| 86 |
|
| 87 |
+
1. **Pass frames as images, not a video file.** The `mlx-vlm` video decoder path
|
| 88 |
+
is unreliable for this model and can produce output unrelated to the clip.
|
| 89 |
+
Extracting frames with ffmpeg and passing them as a list (`image=[...]` with
|
| 90 |
+
a matching `num_images`) delivers the actual frames to the model.
|
| 91 |
2. **The chat template is included** in this repository (`chat_template.json`
|
| 92 |
+
and `chat_template.jinja`). Some MLX repackings omit it, which makes
|
| 93 |
+
`apply_chat_template` fail.
|
| 94 |
3. **Apply a repetition penalty.** At 4-bit precision the model can occasionally
|
| 95 |
+
loop. `repetition_penalty=1.3`, `repetition_context_size=40` and
|
| 96 |
+
`temperature=0.3` kept output stable in our testing; in a small internal set
|
| 97 |
+
of 22 short clips, one degenerated without a penalty and none did with it.
|
| 98 |
+
4. **Runtime scales with frame resolution and frame count**, not with the
|
| 99 |
+
duration of the source clip. See the measurements below.
|
| 100 |
|
| 101 |
+
## Example
|
| 102 |
|
| 103 |
+
A single measured run, not a benchmark.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
+
- **Input:** 8 frames (796×448) from a 10.7-second clip —
|
| 106 |
+
[*Trains – Mini World Lyon*](https://commons.wikimedia.org/wiki/File:Trains_-_Mini_World_Lyon.webm)
|
| 107 |
+
by Benoît Prieur, Wikimedia Commons, CC0
|
| 108 |
+
- **Hardware:** Apple M4 Pro, 24 GB unified memory, macOS 15.7.2
|
| 109 |
+
- **Versions:** Python 3.12.12, `mlx` 0.32.0, `mlx-vlm` 0.6.8
|
| 110 |
+
- **Model load (cold, excluded from generation timing):** ≈14 s
|
| 111 |
+
- **Generation:** median **15.8 s** over 3 warm runs (15.3 / 15.8 / 16.1)
|
| 112 |
+
- **Peak memory:** ≈6.8 GB
|
| 113 |
+
- **Settings:** `max_tokens=300`, as in the usage example above
|
| 114 |
|
| 115 |
+
Output (run 2 of 3, verbatim):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
+
> A model train, consisting of a green engine and several red freight cars,
|
| 118 |
+
> moves along the tracks from left to right. The background features a large
|
| 119 |
+
> crowd of people gathered in an open area with numerous colorful cars parked
|
| 120 |
+
> and displayed. The train passes by the car display area multiple times, moving
|
| 121 |
+
> smoothly along the tracks.
|
| 122 |
|
| 123 |
+
For comparison, 8 frames at 252×448 (a vertical clip) on the same machine ran in
|
| 124 |
+
a median of **5.5 s**. Frame resolution dominates runtime — budget accordingly.
|
| 125 |
+
|
| 126 |
+
## Conversion notes
|
| 127 |
|
| 128 |
+
The original checkpoint could not be converted directly with the standard
|
| 129 |
+
`mlx-vlm` workflow, because its published architecture metadata does not fully
|
| 130 |
+
match the underlying multimodal model structure.
|
| 131 |
+
|
| 132 |
+
For this release, the checkpoint was adapted to a compatible native MLX layout
|
| 133 |
+
before 4-bit quantization. This required resolving differences in the
|
| 134 |
+
vision-language architecture and in the positional encoding configuration.
|
| 135 |
+
|
| 136 |
+
The resulting checkpoint runs through the standard native inference path in
|
| 137 |
+
`mlx-vlm`. The conversion changes the storage and runtime format only; the model
|
| 138 |
+
was not retrained or fine-tuned.
|
| 139 |
+
|
| 140 |
+
The complete conversion procedure is not included in this repository.
|
| 141 |
|
| 142 |
## Limitations
|
| 143 |
|
| 144 |
+
- **4-bit quantization trades some fidelity** for reduced size and higher speed.
|
| 145 |
For maximum quality, use the original bf16 weights on a CUDA device.
|
| 146 |
+
- **English only.** It describes in English regardless of any spoken language in
|
| 147 |
+
the clip.
|
| 148 |
+
- **Vision only (no audio).** It captions what is seen, not what is heard.
|
| 149 |
+
- **Free-form description over rigid schemas.** It follows open-ended captioning
|
| 150 |
+
prompts more reliably than strict output formats, and is better used as a
|
| 151 |
+
captioner than as a classifier.
|
| 152 |
+
- **Detail depends on the source.** On low-resolution or distant subjects it
|
| 153 |
+
describes what is visible at that scale and may not identify the subject
|
| 154 |
+
specifically.
|
| 155 |
+
- **Not systematically evaluated here.** For accuracy figures, see the base
|
| 156 |
+
model's card and paper. The timings above are single measurements on one
|
| 157 |
+
machine.
|
| 158 |
|
| 159 |
## License and attribution
|
| 160 |
|
| 161 |
+
This conversion inherits the **Apache-2.0** license of the base model.
|
| 162 |
+
|
| 163 |
+
All credit for the original model, training and weights belongs to the Tarsier2
|
| 164 |
+
authors ([omni-research/Tarsier2-Recap-7b](https://huggingface.co/omni-research/Tarsier2-Recap-7b)).
|
| 165 |
+
|
| 166 |
+
This repository provides the MLX format conversion, 4-bit quantization,
|
| 167 |
+
packaging, Apple Silicon compatibility testing and usage documentation. The
|
| 168 |
+
model was not retrained or fine-tuned.
|
| 169 |
|
| 170 |
+
When citing Tarsier2, cite the original authors.
|