andreagemelli commited on
Commit
1727faf
·
verified ·
1 Parent(s): 1d5ca14

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

Browse files
README.md ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ - fr
5
+ - de
6
+ - es
7
+ - it
8
+ - pl
9
+ license: apache-2.0
10
+ tags:
11
+ - vision-language-model
12
+ - multimodal
13
+ - visual-question-answering
14
+ - image-captioning
15
+ - vlm
16
+
17
+ base_model:
18
+ - OpenGVLab/InternViT-300M-448px-V2_5
19
+ - PleIAs/Baguettotron
20
+ ---
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
+
39
+ ```
40
+ Image (448×448)
41
+ → InternViT-300M-448px-V2.5 (304M, frozen) → 1024 tokens × 1024d
42
+ → Pixel unshuffle (factor=2) → 256 tokens × 4096d
43
+ → MLP projector (2-layer, ~2.7M) → 256 tokens × 576d
44
+ → Interleave with text tokens
45
+ → Baguettotron (321M, Llama arch, 80L, h=576)
46
+ → Text output with <think> reasoning traces
47
+
48
+ Total: ~628M parameters
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ```python
54
+ import torch
55
+ from transformers import AutoModelForImageTextToText, AutoProcessor
56
+ from PIL import Image
57
+
58
+ model = AutoModelForImageTextToText.from_pretrained(
59
+ "andreagemelli/Baguettotron-VLM-Stage1",
60
+ trust_remote_code=True,
61
+ torch_dtype=torch.bfloat16,
62
+ device_map="auto",
63
+ )
64
+ processor = AutoProcessor.from_pretrained(
65
+ "andreagemelli/Baguettotron-VLM-Stage1",
66
+ trust_remote_code=True,
67
+ )
68
+
69
+ image = Image.open("photo.jpg").convert("RGB")
70
+ inputs = processor(
71
+ messages=[{"role": "user", "content": "<image>\nDescribe the image"}],
72
+ image=image,
73
+ )
74
+ inputs = {k: v.to(model.device) for k, v in inputs.items() if v is not None}
75
+
76
+ print(model.chat(**inputs))
77
+ ```
78
+
79
+ ### Chat template
80
+
81
+ Stage 1 was trained on short image captions with no `<think>` traces. The processor emits a bare assistant prefix (`<|im_start|>assistant\n`) and the model completes the caption directly. Keep prompts simple ("Describe the image").
82
+
83
+ ## Training details
84
+
85
+ | | Stage 1 |
86
+ |---|---|
87
+ | Data | LLaVA-CC3M-Pretrain-595K (595K image-caption pairs) |
88
+ | Trainable params | ~2.7M (projector only) |
89
+ | Frozen | ViT + LLM |
90
+ | Effective batch size | 256 |
91
+ | Learning rate | 1e-3, cosine, 250-step warmup |
92
+ | Precision | bf16 |
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).
config.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "baguettotron_vlm",
3
+ "vit_model_id": "OpenGVLab/InternViT-300M-448px-V2_5",
4
+ "llm_model_id": "PleIAs/Baguettotron",
5
+ "vit_hidden": 1024,
6
+ "vit_tokens": 1024,
7
+ "llm_hidden": 576,
8
+ "num_visual_tokens": 256,
9
+ "unshuffle_factor": 2,
10
+ "image_token": "<image>",
11
+ "chat_style": "base",
12
+ "stage": 1,
13
+ "torch_dtype": "bfloat16",
14
+ "auto_map": {
15
+ "AutoConfig": "configuration_baguettotron_vlm.BaguettotronVLMConfig",
16
+ "AutoModelForImageTextToText": "modeling_baguettotron_vlm.BaguettotronVLMForConditionalGeneration",
17
+ "AutoProcessor": "processing_baguettotron_vlm.BaguettotronVLMProcessor"
18
+ }
19
+ }
configuration_baguettotron_vlm.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BaguettotronVLM configuration."""
2
+ from __future__ import annotations
3
+ from transformers import PretrainedConfig
4
+
5
+
6
+ class BaguettotronVLMConfig(PretrainedConfig):
7
+ model_type = "baguettotron_vlm"
8
+
9
+ def __init__(
10
+ self,
11
+ vit_model_id: str = "OpenGVLab/InternViT-300M-448px-V2_5",
12
+ llm_model_id: str = "PleIAs/Baguettotron",
13
+ vit_hidden: int = 1024,
14
+ vit_tokens: int = 1024,
15
+ llm_hidden: int = 576,
16
+ num_visual_tokens: int = 256,
17
+ unshuffle_factor: int = 2,
18
+ image_token: str = "<image>",
19
+ chat_style: str = "answer",
20
+ stage: int = 2,
21
+ **kwargs,
22
+ ):
23
+ super().__init__(**kwargs)
24
+ self.vit_model_id = vit_model_id
25
+ self.llm_model_id = llm_model_id
26
+ self.vit_hidden = vit_hidden
27
+ self.vit_tokens = vit_tokens
28
+ self.llm_hidden = llm_hidden
29
+ self.num_visual_tokens = num_visual_tokens
30
+ self.unshuffle_factor = unshuffle_factor
31
+ self.image_token = image_token
32
+ # chat_style controls the assistant-turn prefix emitted by the
33
+ # processor when add_generation_prompt=True:
34
+ # "base" → <|im_start|>assistant\n (stage 1, no think tokens)
35
+ # "answer" → <|im_start|>assistant\n</think>\n (stage 2, answer-only)
36
+ # "think" → <|im_start|>assistant\n<think>\n (stage 3, reasoning)
37
+ self.chat_style = chat_style
38
+ self.stage = stage
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:86537f6ef5d0e5e3d7e28cccea94ff515278b9defa5000971bb476f63934ebfa
3
+ size 1336330920
modeling_baguettotron_vlm.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BaguettotronVLM model — self-contained for HuggingFace Hub."""
2
+ from __future__ import annotations
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ from transformers import (
7
+ AutoModel,
8
+ AutoModelForCausalLM,
9
+ AutoTokenizer,
10
+ PreTrainedModel,
11
+ )
12
+ from transformers.modeling_outputs import CausalLMOutputWithPast
13
+
14
+ from .configuration_baguettotron_vlm import BaguettotronVLMConfig
15
+
16
+
17
+ class PixelUnshuffleProjector(nn.Module):
18
+ """Reduces ViT tokens 4× via PixelUnshuffle then projects to LLM dim."""
19
+
20
+ def __init__(self, in_dim: int, out_dim: int, factor: int):
21
+ super().__init__()
22
+ self.factor = factor
23
+ self.unshuffle = nn.PixelUnshuffle(factor)
24
+ self.mlp = nn.Sequential(
25
+ nn.Linear(in_dim * factor * factor, out_dim),
26
+ nn.GELU(),
27
+ nn.Linear(out_dim, out_dim),
28
+ )
29
+
30
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
31
+ B, N, D = x.shape
32
+ spatial = int(N ** 0.5)
33
+ x = x.reshape(B, spatial, spatial, D).permute(0, 3, 1, 2)
34
+ x = self.unshuffle(x)
35
+ x = x.flatten(2).transpose(1, 2)
36
+ return self.mlp(x)
37
+
38
+
39
+ class BaguettotronVLMForConditionalGeneration(PreTrainedModel):
40
+ """
41
+ BaguettotronVLM: InternViT-300M + PixelUnshuffle projector + Baguettotron-321M.
42
+
43
+ ~628M total parameters. The same architecture is shipped for all three
44
+ training stages; only the checkpoint weights and `config.chat_style`
45
+ differ between them.
46
+
47
+ Load with:
48
+ from transformers import AutoModelForImageTextToText
49
+ model = AutoModelForImageTextToText.from_pretrained(
50
+ "andreagemelli/Baguettotron-VLM",
51
+ trust_remote_code=True,
52
+ torch_dtype=torch.bfloat16,
53
+ )
54
+ """
55
+
56
+ config_class = BaguettotronVLMConfig
57
+ _no_split_modules = ["InternVisionEncoderLayer", "LlamaDecoderLayer"]
58
+ # Tell HF Trainer not to pass num_items_in_batch (loss handled internally)
59
+ model_accepts_loss_kwargs: bool = False
60
+
61
+ def __init__(self, config: BaguettotronVLMConfig):
62
+ super().__init__(config)
63
+
64
+ self.vit = AutoModel.from_pretrained(
65
+ config.vit_model_id,
66
+ dtype=torch.bfloat16,
67
+ low_cpu_mem_usage=True,
68
+ trust_remote_code=True,
69
+ )
70
+ self.projector = PixelUnshuffleProjector(
71
+ in_dim=config.vit_hidden,
72
+ out_dim=config.llm_hidden,
73
+ factor=config.unshuffle_factor,
74
+ )
75
+
76
+ tokenizer = AutoTokenizer.from_pretrained(config.llm_model_id)
77
+ tokenizer.add_special_tokens(
78
+ {"additional_special_tokens": [config.image_token, "</image>"]}
79
+ )
80
+ raw_id = tokenizer.convert_tokens_to_ids(config.image_token)
81
+ self.image_token_id: int = raw_id if isinstance(raw_id, int) else int(raw_id[0])
82
+
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
+
90
+ self._tokenizer = tokenizer
91
+
92
+ def _init_weights(self, module: nn.Module) -> None:
93
+ # Pretrained components are initialised from their respective hubs;
94
+ # the projector weights come from the saved checkpoint — skip random init.
95
+ pass
96
+
97
+ # ------------------------------------------------------------------
98
+ # Training interface
99
+ # ------------------------------------------------------------------
100
+
101
+ def forward(
102
+ self,
103
+ input_ids: torch.Tensor,
104
+ attention_mask: torch.Tensor,
105
+ labels: torch.Tensor | None = None,
106
+ pixel_values: torch.Tensor | None = None,
107
+ **kwargs,
108
+ ) -> CausalLMOutputWithPast:
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
121
+ ).to(inputs_embeds.dtype)
122
+
123
+ return self.llm(
124
+ inputs_embeds=inputs_embeds,
125
+ attention_mask=attention_mask,
126
+ labels=labels,
127
+ return_dict=True,
128
+ use_cache=False,
129
+ )
130
+
131
+ # ------------------------------------------------------------------
132
+ # Inference interface
133
+ # ------------------------------------------------------------------
134
+
135
+ @torch.no_grad()
136
+ def chat(
137
+ self,
138
+ input_ids: torch.Tensor,
139
+ attention_mask: torch.Tensor,
140
+ pixel_values: torch.Tensor | None = None,
141
+ max_new_tokens: int = 256,
142
+ repetition_penalty: float = 1.3,
143
+ **generate_kwargs,
144
+ ) -> str:
145
+ """Inject visual tokens, generate autoregressively, return decoded string."""
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
157
+ ).to(inputs_embeds.dtype)
158
+
159
+ im_end_id = int(self._tokenizer.convert_tokens_to_ids("<|im_end|>"))
160
+ output_ids = self.llm.generate(
161
+ inputs_embeds=inputs_embeds,
162
+ attention_mask=attention_mask,
163
+ max_new_tokens=max_new_tokens,
164
+ do_sample=False,
165
+ repetition_penalty=repetition_penalty,
166
+ eos_token_id=[self._tokenizer.eos_token_id, im_end_id],
167
+ **generate_kwargs,
168
+ )
169
+ decoded = self._tokenizer.decode(output_ids[0], skip_special_tokens=False)
170
+ if "<|im_end|>" in decoded:
171
+ decoded = decoded[: decoded.index("<|im_end|>")]
172
+ return decoded.strip()
preprocessor_config.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "crop_size": {
3
+ "height": 448,
4
+ "width": 448
5
+ },
6
+ "do_center_crop": true,
7
+ "do_convert_rgb": true,
8
+ "do_normalize": true,
9
+ "do_rescale": true,
10
+ "do_resize": true,
11
+ "image_mean": [
12
+ 0.485,
13
+ 0.456,
14
+ 0.406
15
+ ],
16
+ "image_processor_type": "CLIPImageProcessor",
17
+ "image_std": [
18
+ 0.229,
19
+ 0.224,
20
+ 0.225
21
+ ],
22
+ "resample": 3,
23
+ "rescale_factor": 0.00392156862745098,
24
+ "size": {
25
+ "shortest_edge": 448
26
+ }
27
+ }
processing_baguettotron_vlm.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BaguettotronVLM processor — self-contained for HuggingFace Hub."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import os
6
+ from pathlib import Path
7
+
8
+ from PIL import Image
9
+ from transformers import CLIPImageProcessor, ProcessorMixin
10
+ from transformers import PreTrainedTokenizerFast
11
+
12
+ NUM_VISUAL_TOKENS = 256
13
+ IMAGE_TOKEN = "<image>"
14
+ IMAGE_END_TOKEN = "</image>"
15
+
16
+
17
+ def _assistant_prefix(chat_style: str, enable_thinking: bool | None) -> str:
18
+ """Return the assistant-turn content prefix for a generation prompt.
19
+
20
+ chat_style is the default baked into the repo at publish time:
21
+ - "base": stage 1 — no think tokens
22
+ - "answer": stage 2 — pre-fill </think> so the model skips reasoning
23
+ - "think": stage 3 — pre-fill <think> to trigger reasoning traces
24
+
25
+ enable_thinking overrides chat_style at call-time (stage 3 models can
26
+ toggle thinking on/off dynamically):
27
+ - None → keep chat_style default
28
+ - True → "<think>\n"
29
+ - False → "</think>\n"
30
+ """
31
+ if enable_thinking is True:
32
+ return "<think>\n"
33
+ if enable_thinking is False:
34
+ return "</think>\n"
35
+ if chat_style == "think":
36
+ return "<think>\n"
37
+ if chat_style == "answer":
38
+ return "</think>\n"
39
+ return ""
40
+
41
+
42
+ class BaguettotronVLMProcessor(ProcessorMixin):
43
+ """
44
+ Wraps CLIPImageProcessor + Baguettotron tokenizer.
45
+
46
+ Expands a single <image> placeholder into NUM_VISUAL_TOKENS consecutive
47
+ <image> token IDs so the model's forward() can replace them with ViT
48
+ features. Builds Qwen-style chat prompts with stage-appropriate
49
+ assistant prefixes.
50
+
51
+ Load with::
52
+
53
+ from transformers import AutoProcessor
54
+ processor = AutoProcessor.from_pretrained(
55
+ "andreagemelli/Baguettotron-VLM",
56
+ trust_remote_code=True,
57
+ )
58
+ """
59
+
60
+ attributes = ["image_processor", "tokenizer"]
61
+ image_processor_class = "CLIPImageProcessor"
62
+ tokenizer_class = "AutoTokenizer"
63
+
64
+ def __init__(
65
+ self,
66
+ image_processor: CLIPImageProcessor,
67
+ tokenizer: PreTrainedTokenizerFast,
68
+ num_visual_tokens: int = NUM_VISUAL_TOKENS,
69
+ chat_style: str = "answer",
70
+ ):
71
+ super().__init__(image_processor, tokenizer)
72
+ self.num_visual_tokens = num_visual_tokens
73
+ self.chat_style = chat_style
74
+ raw_id = tokenizer.convert_tokens_to_ids(IMAGE_TOKEN)
75
+ self.image_token_id: int = raw_id if isinstance(raw_id, int) else int(raw_id[0])
76
+
77
+ @classmethod
78
+ def from_pretrained(cls, pretrained_model_name_or_path, **kwargs): # type: ignore[override]
79
+ processor = super().from_pretrained(pretrained_model_name_or_path, **kwargs)
80
+ # Re-register special tokens (some tokenizers drop them on save/load)
81
+ processor.tokenizer.add_special_tokens(
82
+ {"additional_special_tokens": [IMAGE_TOKEN, IMAGE_END_TOKEN]}
83
+ )
84
+ raw_id = processor.tokenizer.convert_tokens_to_ids(IMAGE_TOKEN)
85
+ processor.image_token_id = raw_id if isinstance(raw_id, int) else int(raw_id[0])
86
+
87
+ # Load chat_style from config.json (written by push_to_hub per stage)
88
+ chat_style = "answer"
89
+ try:
90
+ if os.path.isdir(pretrained_model_name_or_path):
91
+ cfg_path = Path(pretrained_model_name_or_path) / "config.json"
92
+ if cfg_path.exists():
93
+ chat_style = json.loads(cfg_path.read_text()).get(
94
+ "chat_style", chat_style
95
+ )
96
+ else:
97
+ from huggingface_hub import hf_hub_download
98
+ cfg_path = hf_hub_download(
99
+ repo_id=pretrained_model_name_or_path, filename="config.json"
100
+ )
101
+ chat_style = json.loads(Path(cfg_path).read_text()).get(
102
+ "chat_style", chat_style
103
+ )
104
+ except Exception:
105
+ pass
106
+ processor.chat_style = chat_style
107
+ return processor
108
+
109
+ def _format_messages(
110
+ self,
111
+ messages: list[dict],
112
+ add_generation_prompt: bool,
113
+ enable_thinking: bool | None,
114
+ ) -> str:
115
+ parts = [
116
+ f"<|im_start|>{m['role']}\n{m['content']}<|im_end|>" for m in messages
117
+ ]
118
+ text = "\n".join(parts)
119
+ if add_generation_prompt:
120
+ prefix = _assistant_prefix(self.chat_style, enable_thinking)
121
+ text = f"{text}\n<|im_start|>assistant\n{prefix}"
122
+ return text
123
+
124
+ def __call__(
125
+ self,
126
+ text: str | None = None,
127
+ messages: list[dict] | None = None,
128
+ image: Image.Image | None = None,
129
+ return_tensors: str = "pt",
130
+ add_generation_prompt: bool = True,
131
+ enable_thinking: bool | None = None,
132
+ ) -> dict:
133
+ """Tokenise text (or a messages list) and optionally preprocess an image.
134
+
135
+ Args:
136
+ text: raw prompt string (with a single <image> placeholder).
137
+ messages: alternative to text — list of chat dicts with "role"/"content".
138
+ image: PIL image to preprocess (optional).
139
+ add_generation_prompt: append an <|im_start|>assistant\n prefix.
140
+ enable_thinking: override chat_style for this call.
141
+ - None: keep the stage default (chat_style)
142
+ - True: pre-fill <think>\n (stage 3 reasoning mode)
143
+ - False: pre-fill </think>\n (stage 2 / stage 3 no-think mode)
144
+ """
145
+ if messages is not None:
146
+ text = self._format_messages(
147
+ messages, add_generation_prompt, enable_thinking
148
+ )
149
+ if text is None:
150
+ raise ValueError("Provide either text or messages.")
151
+
152
+ expanded = text.replace(IMAGE_TOKEN, IMAGE_TOKEN * self.num_visual_tokens, 1)
153
+ enc = self.tokenizer(
154
+ expanded, return_tensors=return_tensors, add_special_tokens=False
155
+ )
156
+ result = {
157
+ "input_ids": enc["input_ids"],
158
+ "attention_mask": enc["attention_mask"],
159
+ }
160
+ if image is not None:
161
+ pv = self.image_processor(images=image, return_tensors=return_tensors)
162
+ result["pixel_values"] = pv.pixel_values
163
+ else:
164
+ result["pixel_values"] = None
165
+ return result
processor_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "processor_class": "BaguettotronVLMProcessor",
3
+ "chat_style": "base",
4
+ "num_visual_tokens": 256,
5
+ "auto_map": {
6
+ "AutoProcessor": "processing_baguettotron_vlm.BaguettotronVLMProcessor"
7
+ }
8
+ }
special_tokens_map.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ {
4
+ "content": "<image>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false
9
+ },
10
+ {
11
+ "content": "</image>",
12
+ "lstrip": false,
13
+ "normalized": false,
14
+ "rstrip": false,
15
+ "single_word": false
16
+ }
17
+ ],
18
+ "bos_token": {
19
+ "content": "<|begin_of_text|>",
20
+ "lstrip": false,
21
+ "normalized": false,
22
+ "rstrip": false,
23
+ "single_word": false
24
+ },
25
+ "eos_token": {
26
+ "content": "<|end_of_text|>",
27
+ "lstrip": false,
28
+ "normalized": false,
29
+ "rstrip": false,
30
+ "single_word": false
31
+ },
32
+ "pad_token": {
33
+ "content": "[PAD]",
34
+ "lstrip": false,
35
+ "normalized": false,
36
+ "rstrip": false,
37
+ "single_word": false
38
+ },
39
+ "unk_token": {
40
+ "content": "[UNK]",
41
+ "lstrip": false,
42
+ "normalized": false,
43
+ "rstrip": false,
44
+ "single_word": false
45
+ }
46
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[UNK]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "<|begin_of_text|>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "<|end_of_text|>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "[PAD]",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "65491": {
36
+ "content": "<|im_start|>",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ },
43
+ "65492": {
44
+ "content": "<|im_end>",
45
+ "lstrip": false,
46
+ "normalized": false,
47
+ "rstrip": false,
48
+ "single_word": false,
49
+ "special": true
50
+ },
51
+ "65493": {
52
+ "content": "<think>",
53
+ "lstrip": false,
54
+ "normalized": false,
55
+ "rstrip": false,
56
+ "single_word": false,
57
+ "special": true
58
+ },
59
+ "65494": {
60
+ "content": "</think>",
61
+ "lstrip": false,
62
+ "normalized": false,
63
+ "rstrip": false,
64
+ "single_word": false,
65
+ "special": true
66
+ },
67
+ "65495": {
68
+ "content": "source_1",
69
+ "lstrip": false,
70
+ "normalized": false,
71
+ "rstrip": false,
72
+ "single_word": false,
73
+ "special": true
74
+ },
75
+ "65496": {
76
+ "content": "source_2",
77
+ "lstrip": false,
78
+ "normalized": false,
79
+ "rstrip": false,
80
+ "single_word": false,
81
+ "special": true
82
+ },
83
+ "65497": {
84
+ "content": "source_3",
85
+ "lstrip": false,
86
+ "normalized": false,
87
+ "rstrip": false,
88
+ "single_word": false,
89
+ "special": true
90
+ },
91
+ "65498": {
92
+ "content": "source_4",
93
+ "lstrip": false,
94
+ "normalized": false,
95
+ "rstrip": false,
96
+ "single_word": false,
97
+ "special": true
98
+ },
99
+ "65499": {
100
+ "content": "source_5",
101
+ "lstrip": false,
102
+ "normalized": false,
103
+ "rstrip": false,
104
+ "single_word": false,
105
+ "special": true
106
+ },
107
+ "65500": {
108
+ "content": "source_6",
109
+ "lstrip": false,
110
+ "normalized": false,
111
+ "rstrip": false,
112
+ "single_word": false,
113
+ "special": true
114
+ },
115
+ "65501": {
116
+ "content": "source_7",
117
+ "lstrip": false,
118
+ "normalized": false,
119
+ "rstrip": false,
120
+ "single_word": false,
121
+ "special": true
122
+ },
123
+ "65502": {
124
+ "content": "source_8",
125
+ "lstrip": false,
126
+ "normalized": false,
127
+ "rstrip": false,
128
+ "single_word": false,
129
+ "special": true
130
+ },
131
+ "65503": {
132
+ "content": "source_9",
133
+ "lstrip": false,
134
+ "normalized": false,
135
+ "rstrip": false,
136
+ "single_word": false,
137
+ "special": true
138
+ },
139
+ "65504": {
140
+ "content": "source_10",
141
+ "lstrip": false,
142
+ "normalized": false,
143
+ "rstrip": false,
144
+ "single_word": false,
145
+ "special": true
146
+ },
147
+ "65505": {
148
+ "content": "<ref",
149
+ "lstrip": false,
150
+ "normalized": false,
151
+ "rstrip": false,
152
+ "single_word": false,
153
+ "special": true
154
+ },
155
+ "65506": {
156
+ "content": "</ref>",
157
+ "lstrip": false,
158
+ "normalized": false,
159
+ "rstrip": false,
160
+ "single_word": false,
161
+ "special": true
162
+ },
163
+ "65507": {
164
+ "content": "→",
165
+ "lstrip": false,
166
+ "normalized": false,
167
+ "rstrip": false,
168
+ "single_word": false,
169
+ "special": true
170
+ },
171
+ "65508": {
172
+ "content": "↺",
173
+ "lstrip": false,
174
+ "normalized": false,
175
+ "rstrip": false,
176
+ "single_word": false,
177
+ "special": true
178
+ },
179
+ "65509": {
180
+ "content": "※",
181
+ "lstrip": false,
182
+ "normalized": false,
183
+ "rstrip": false,
184
+ "single_word": false,
185
+ "special": true
186
+ },
187
+ "65510": {
188
+ "content": "?maybe?",
189
+ "lstrip": false,
190
+ "normalized": false,
191
+ "rstrip": false,
192
+ "single_word": false,
193
+ "special": true
194
+ },
195
+ "65511": {
196
+ "content": "●",
197
+ "lstrip": false,
198
+ "normalized": false,
199
+ "rstrip": false,
200
+ "single_word": false,
201
+ "special": true
202
+ },
203
+ "65512": {
204
+ "content": "◐",
205
+ "lstrip": false,
206
+ "normalized": false,
207
+ "rstrip": false,
208
+ "single_word": false,
209
+ "special": true
210
+ },
211
+ "65513": {
212
+ "content": "○",
213
+ "lstrip": false,
214
+ "normalized": false,
215
+ "rstrip": false,
216
+ "single_word": false,
217
+ "special": true
218
+ },
219
+ "65514": {
220
+ "content": "⚠",
221
+ "lstrip": false,
222
+ "normalized": false,
223
+ "rstrip": false,
224
+ "single_word": false,
225
+ "special": true
226
+ },
227
+ "65515": {
228
+ "content": "☐",
229
+ "lstrip": false,
230
+ "normalized": false,
231
+ "rstrip": false,
232
+ "single_word": false,
233
+ "special": true
234
+ },
235
+ "65516": {
236
+ "content": "☑",
237
+ "lstrip": false,
238
+ "normalized": false,
239
+ "rstrip": false,
240
+ "single_word": false,
241
+ "special": true
242
+ },
243
+ "65517": {
244
+ "content": "✓",
245
+ "lstrip": false,
246
+ "normalized": false,
247
+ "rstrip": false,
248
+ "single_word": false,
249
+ "special": true
250
+ },
251
+ "65518": {
252
+ "content": "⟨H≈0.1⟩",
253
+ "lstrip": false,
254
+ "normalized": false,
255
+ "rstrip": false,
256
+ "single_word": false,
257
+ "special": true
258
+ },
259
+ "65519": {
260
+ "content": "⟨H≈0.2⟩",
261
+ "lstrip": false,
262
+ "normalized": false,
263
+ "rstrip": false,
264
+ "single_word": false,
265
+ "special": true
266
+ },
267
+ "65520": {
268
+ "content": "⟨H≈0.3⟩",
269
+ "lstrip": false,
270
+ "normalized": false,
271
+ "rstrip": false,
272
+ "single_word": false,
273
+ "special": true
274
+ },
275
+ "65521": {
276
+ "content": "⟨H≈0.4⟩",
277
+ "lstrip": false,
278
+ "normalized": false,
279
+ "rstrip": false,
280
+ "single_word": false,
281
+ "special": true
282
+ },
283
+ "65522": {
284
+ "content": "⟨H≈0.5⟩",
285
+ "lstrip": false,
286
+ "normalized": false,
287
+ "rstrip": false,
288
+ "single_word": false,
289
+ "special": true
290
+ },
291
+ "65523": {
292
+ "content": "⟨H≈0.6⟩",
293
+ "lstrip": false,
294
+ "normalized": false,
295
+ "rstrip": false,
296
+ "single_word": false,
297
+ "special": true
298
+ },
299
+ "65524": {
300
+ "content": "⟨H≈0.7⟩",
301
+ "lstrip": false,
302
+ "normalized": false,
303
+ "rstrip": false,
304
+ "single_word": false,
305
+ "special": true
306
+ },
307
+ "65525": {
308
+ "content": "⟨H≈0.8⟩",
309
+ "lstrip": false,
310
+ "normalized": false,
311
+ "rstrip": false,
312
+ "single_word": false,
313
+ "special": true
314
+ },
315
+ "65526": {
316
+ "content": "⟨H≈0.9⟩",
317
+ "lstrip": false,
318
+ "normalized": false,
319
+ "rstrip": false,
320
+ "single_word": false,
321
+ "special": true
322
+ },
323
+ "65527": {
324
+ "content": "⟨H≈1.0⟩",
325
+ "lstrip": false,
326
+ "normalized": false,
327
+ "rstrip": false,
328
+ "single_word": false,
329
+ "special": true
330
+ },
331
+ "65528": {
332
+ "content": "⟨H≈1.1⟩",
333
+ "lstrip": false,
334
+ "normalized": false,
335
+ "rstrip": false,
336
+ "single_word": false,
337
+ "special": true
338
+ },
339
+ "65529": {
340
+ "content": "⟨H≈1.2⟩",
341
+ "lstrip": false,
342
+ "normalized": false,
343
+ "rstrip": false,
344
+ "single_word": false,
345
+ "special": true
346
+ },
347
+ "65530": {
348
+ "content": "⟨H≈1.3⟩",
349
+ "lstrip": false,
350
+ "normalized": false,
351
+ "rstrip": false,
352
+ "single_word": false,
353
+ "special": true
354
+ },
355
+ "65531": {
356
+ "content": "⟨H≈1.4⟩",
357
+ "lstrip": false,
358
+ "normalized": false,
359
+ "rstrip": false,
360
+ "single_word": false,
361
+ "special": true
362
+ },
363
+ "65532": {
364
+ "content": "⟨H≈1.5⟩",
365
+ "lstrip": false,
366
+ "normalized": false,
367
+ "rstrip": false,
368
+ "single_word": false,
369
+ "special": true
370
+ },
371
+ "65533": {
372
+ "content": "⟨H≈1.6⟩",
373
+ "lstrip": false,
374
+ "normalized": false,
375
+ "rstrip": false,
376
+ "single_word": false,
377
+ "special": true
378
+ },
379
+ "65534": {
380
+ "content": "⟨H≈1.7⟩",
381
+ "lstrip": false,
382
+ "normalized": false,
383
+ "rstrip": false,
384
+ "single_word": false,
385
+ "special": true
386
+ },
387
+ "65535": {
388
+ "content": "⟨H≈1.8⟩",
389
+ "lstrip": false,
390
+ "normalized": false,
391
+ "rstrip": false,
392
+ "single_word": false,
393
+ "special": true
394
+ },
395
+ "65536": {
396
+ "content": "<image>",
397
+ "lstrip": false,
398
+ "normalized": false,
399
+ "rstrip": false,
400
+ "single_word": false,
401
+ "special": true
402
+ },
403
+ "65537": {
404
+ "content": "</image>",
405
+ "lstrip": false,
406
+ "normalized": false,
407
+ "rstrip": false,
408
+ "single_word": false,
409
+ "special": true
410
+ }
411
+ },
412
+ "additional_special_tokens": [
413
+ "<image>",
414
+ "</image>"
415
+ ],
416
+ "bos_token": "<|begin_of_text|>",
417
+ "clean_up_tokenization_spaces": true,
418
+ "eos_token": "<|end_of_text|>",
419
+ "extra_special_tokens": {},
420
+ "model_max_length": 1000000000000000019884624838656,
421
+ "pad_token": "[PAD]",
422
+ "tokenizer_class": "PreTrainedTokenizerFast",
423
+ "unk_token": "[UNK]"
424
+ }