andreagemelli commited on
Commit
9b486d0
Β·
verified Β·
1 Parent(s): 1727faf

Stage 1 checkpoint (projector warmup on LLaVA-CC3M-Pretrain-595K)

Browse files
Files changed (2) hide show
  1. README.md +68 -10
  2. modeling_baguettotron_vlm.py +5 -3
README.md CHANGED
@@ -21,18 +21,33 @@ base_model:
21
 
22
  # Baguettotron-VLM β€” Stage 1 (Projector Warmup)
23
 
24
- **Stage 1 checkpoint.** Only the MLP projector has been trained (on LLaVA-CC3M-Pretrain-595K); the ViT and the Baguettotron LLM are the unmodified base weights. Published for reproducibility β€” for actual use prefer the Stage 2 or Stage 3 checkpoints.
 
 
 
 
 
25
 
26
- Part of the [Baguettotron-VLM](https://github.com/andreagemelli/baguettotron-vlm)
27
- project: an open, reproducible, multilingual Vision-Language Model built by
28
- extending [PleIAs/Baguettotron](https://huggingface.co/PleIAs/Baguettotron)
29
- (321M reasoning SLM) with visual capabilities via
30
- [InternViT-300M-448px-V2.5](https://huggingface.co/OpenGVLab/InternViT-300M-448px-V2_5).
 
31
 
32
- Related checkpoints:
33
- - Stage 1 (projector warmup): [andreagemelli/Baguettotron-VLM-Stage1](https://huggingface.co/andreagemelli/Baguettotron-VLM-Stage1)
34
- - Stage 2 (instruction tuning): [andreagemelli/Baguettotron-VLM-Stage2](https://huggingface.co/andreagemelli/Baguettotron-VLM-Stage2)
35
- - Stage 3 (reasoning SFT, flagship): [andreagemelli/Baguettotron-VLM](https://huggingface.co/andreagemelli/Baguettotron-VLM)
 
 
 
 
 
 
 
 
 
36
 
37
  ## Architecture
38
 
@@ -93,6 +108,49 @@ Stage 1 was trained on short image captions with no `<think>` traces. The proces
93
  | Hardware | 1Γ— H100 SXM (RunPod) |
94
  | Duration | ~5h |
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  ## License
97
 
98
  Apache 2.0 β€” see the [GitHub repo](https://github.com/andreagemelli/baguettotron-vlm).
 
21
 
22
  # Baguettotron-VLM β€” Stage 1 (Projector Warmup)
23
 
24
+ **Baguettotron-VLM** is an open, fully-reproducible, multilingual Vision-Language
25
+ Model in the **sub-1B parameter** class. It extends
26
+ [PleIAs/Baguettotron](https://huggingface.co/PleIAs/Baguettotron) β€” a 321M
27
+ text-only reasoning SLM β€” with visual capabilities via the
28
+ [InternViT-300M-448px-V2.5](https://huggingface.co/OpenGVLab/InternViT-300M-448px-V2_5)
29
+ vision encoder and a lightweight MLP projector, for a total of ~628M parameters.
30
 
31
+ It supports **six European languages** (EN, FR, DE, ES, IT, PL, inherited from
32
+ the Baguettotron backbone), natively emits `<think>` reasoning traces, and was
33
+ trained end-to-end on a single H100 SXM β€” code, data pipeline, weights, and
34
+ training logs are all public. Everything is released under **Apache 2.0** with
35
+ a proof-of-concept goal: exploring what an open sub-1B multilingual VLM can do,
36
+ not chasing SOTA.
37
 
38
+ The project ships three checkpoints from a staged training curriculum:
39
+
40
+ - **Stage 1 β€” projector warmup**: [andreagemelli/Baguettotron-VLM-Stage1](https://huggingface.co/andreagemelli/Baguettotron-VLM-Stage1)
41
+ (MLP projector only, LLaVA-CC3M-Pretrain-595K β€” published for reproducibility).
42
+ - **Stage 2 β€” instruction tuning**: [andreagemelli/Baguettotron-VLM-Stage2](https://huggingface.co/andreagemelli/Baguettotron-VLM-Stage2)
43
+ (full fine-tune on The Cauldron + SYNTH, direct-answer mode).
44
+ - **Stage 3 β€” reasoning SFT (flagship)**: [andreagemelli/Baguettotron-VLM](https://huggingface.co/andreagemelli/Baguettotron-VLM)
45
+ (reasoning traces via R1-Vision-Reasoning-Instructions, dynamic `<think>` toggle).
46
+
47
+ Source & training pipeline: [github.com/andreagemelli/baguettotron-vlm](https://github.com/andreagemelli/baguettotron-vlm).
48
+
49
+
50
+ > **Stage 1 checkpoint.** Only the MLP projector has been trained (on LLaVA-CC3M-Pretrain-595K); the ViT and the Baguettotron LLM are the unmodified base weights. Published for reproducibility β€” for actual use prefer the Stage 2 or Stage 3 checkpoints.
51
 
52
  ## Architecture
53
 
 
108
  | Hardware | 1Γ— H100 SXM (RunPod) |
109
  | Duration | ~5h |
110
 
111
+ ## Project scope & limitations
112
+
113
+ Baguettotron-VLM is a **self-educational, open-source proof of concept** trained
114
+ on a limited compute budget. The goal has always been to explore what an open,
115
+ fully-reproducible, multilingual sub-1B VLM can do when every design choice has
116
+ to justify itself against a hard budget cap.
117
+
118
+ Concretely, this means the model may have limitations:
119
+
120
+ - **Likely undertrained for VQA alignment.** The Stage 2 instruction-tuning
121
+ budget (~60h on a single H100) is small relative to the data mixture; the
122
+ model has seen far fewer tokens than typical VLMs of comparable size.
123
+ - **Hallucinations.** The Baguettotron backbone is pretrained on synthetic
124
+ corpora and reasoning traces, which gives it strong `<think>` behaviour but
125
+ also a tendency to confabulate details that aren't grounded in the image,
126
+ especially on fine-grained or text-heavy questions.
127
+ - **Best on simple, scene-level prompts.** In informal testing the model is
128
+ most reliable at open-ended description and scene understanding
129
+ ("what is happening in this image?") and less reliable at OCR, counting,
130
+ chart reading, or multi-hop visual reasoning. Quantitative benchmark
131
+ numbers will be published once the evaluation harness lands.
132
+
133
+ **Contributions and suggestions are very welcome** β€” issues, PRs, and ideas for
134
+ better data mixes, training recipes, or evaluation setups are all appreciated.
135
+ Open an issue or PR on the
136
+ [GitHub repo](https://github.com/andreagemelli/baguettotron-vlm).
137
+
138
+
139
+ ## Citation
140
+
141
+ If you use or extend Baguettotron-VLM in your research, please cite it:
142
+
143
+ ```bibtex
144
+ @misc{gemelli2026baguettotronvlm,
145
+ title = {Baguettotron-VLM: An Open, Reproducible, Multilingual Sub-1B Vision-Language Model},
146
+ author = {Gemelli, Andrea},
147
+ year = {2026},
148
+ howpublished = {\url{https://huggingface.co/andreagemelli/Baguettotron-VLM}},
149
+ note = {Code: \url{https://github.com/andreagemelli/baguettotron-vlm}}
150
+ }
151
+ ```
152
+
153
+
154
  ## License
155
 
156
  Apache 2.0 β€” see the [GitHub repo](https://github.com/andreagemelli/baguettotron-vlm).
modeling_baguettotron_vlm.py CHANGED
@@ -83,7 +83,7 @@ class BaguettotronVLMForConditionalGeneration(PreTrainedModel):
83
  self.llm = AutoModelForCausalLM.from_pretrained(
84
  config.llm_model_id, dtype=torch.bfloat16
85
  )
86
- self.llm.resize_token_embeddings(len(tokenizer))
87
  # Break weight tying β€” safetensors rejects shared-storage tensors
88
  self.llm.lm_head.weight = nn.Parameter(self.llm.lm_head.weight.data.clone())
89
 
@@ -109,12 +109,13 @@ class BaguettotronVLMForConditionalGeneration(PreTrainedModel):
109
  inputs_embeds = self.llm.get_input_embeddings()(input_ids)
110
 
111
  if pixel_values is not None:
 
112
  with torch.no_grad():
113
  vit_out = self.vit(pixel_values)
114
  image_features = vit_out.last_hidden_state
115
  if image_features.shape[1] == self.config.vit_tokens + 1:
116
  image_features = image_features[:, 1:, :]
117
- visual_tokens = self.projector(image_features.float())
118
  image_mask = input_ids == self.image_token_id
119
  inputs_embeds[image_mask] = visual_tokens.reshape(
120
  -1, self.config.llm_hidden
@@ -146,11 +147,12 @@ class BaguettotronVLMForConditionalGeneration(PreTrainedModel):
146
  inputs_embeds = self.llm.get_input_embeddings()(input_ids)
147
 
148
  if pixel_values is not None:
 
149
  vit_out = self.vit(pixel_values)
150
  image_features = vit_out.last_hidden_state
151
  if image_features.shape[1] == self.config.vit_tokens + 1:
152
  image_features = image_features[:, 1:, :]
153
- visual_tokens = self.projector(image_features.float())
154
  image_mask = input_ids == self.image_token_id
155
  inputs_embeds[image_mask] = visual_tokens.reshape(
156
  -1, self.config.llm_hidden
 
83
  self.llm = AutoModelForCausalLM.from_pretrained(
84
  config.llm_model_id, dtype=torch.bfloat16
85
  )
86
+ self.llm.resize_token_embeddings(len(tokenizer), mean_resizing=False)
87
  # Break weight tying β€” safetensors rejects shared-storage tensors
88
  self.llm.lm_head.weight = nn.Parameter(self.llm.lm_head.weight.data.clone())
89
 
 
109
  inputs_embeds = self.llm.get_input_embeddings()(input_ids)
110
 
111
  if pixel_values is not None:
112
+ pixel_values = pixel_values.to(dtype=self.vit.dtype, device=self.vit.device)
113
  with torch.no_grad():
114
  vit_out = self.vit(pixel_values)
115
  image_features = vit_out.last_hidden_state
116
  if image_features.shape[1] == self.config.vit_tokens + 1:
117
  image_features = image_features[:, 1:, :]
118
+ visual_tokens = self.projector(image_features.to(inputs_embeds.dtype))
119
  image_mask = input_ids == self.image_token_id
120
  inputs_embeds[image_mask] = visual_tokens.reshape(
121
  -1, self.config.llm_hidden
 
147
  inputs_embeds = self.llm.get_input_embeddings()(input_ids)
148
 
149
  if pixel_values is not None:
150
+ pixel_values = pixel_values.to(dtype=self.vit.dtype, device=self.vit.device)
151
  vit_out = self.vit(pixel_values)
152
  image_features = vit_out.last_hidden_state
153
  if image_features.shape[1] == self.config.vit_tokens + 1:
154
  image_features = image_features[:, 1:, :]
155
+ visual_tokens = self.projector(image_features.to(inputs_embeds.dtype))
156
  image_mask = input_ids == self.image_token_id
157
  inputs_embeds[image_mask] = visual_tokens.reshape(
158
  -1, self.config.llm_hidden