andreagemelli commited on
Commit
2c4010c
·
verified ·
1 Parent(s): 485d873

Fix generation from the published artifact; rewrite model card

Browse files
Files changed (2) hide show
  1. README.md +14 -7
  2. modeling_baguettotron_vlm.py +28 -9
README.md CHANGED
@@ -16,8 +16,6 @@ tags:
16
  base_model:
17
  - OpenGVLab/InternViT-300M-448px-V2_5
18
  - PleIAs/Baguettotron
19
- datasets:
20
- - liuhaotian/LLaVA-CC3M-Pretrain-595K
21
  ---
22
 
23
  # baguettotron-internvit-alignment
@@ -38,9 +36,9 @@ Two checkpoints are published:
38
  — instruction-tuned on top of it. It goes past plain description and follows visual
39
  instructions, so prefer it for a richer chat experience.
40
 
41
- Resorces:
42
- - Code: [github.com/andreagemelli/baguettotron-vlm](https://github.com/andreagemelli/baguettotron-vlm)
43
- - Blogpost: [andreagemelli.me/posts/baguettotron-vlm](https://andreagemelli.me/posts/baguettotron-vlm/)
44
 
45
 
46
  > **Alignment checkpoint.** Only the MLP projector was trained (on LLaVA-CC3M-Pretrain-595K) — the ViT and the Baguettotron LLM are unmodified base weights. It writes short captions and nothing more. Published so the alignment stage can be reproduced; for actual use take [baguettotron-vision-vqa](https://huggingface.co/andreagemelli/baguettotron-vision-vqa).
@@ -98,13 +96,22 @@ Greedy, prompt `Describe the image concisely.` — verbatim output. Images from
98
  |---|---|
99
  | <img src="examples/cats.jpg" width="180"> | `a cat is sleeping on the couch` |
100
  | <img src="examples/bear.jpg" width="180"> | `the bear is a good friend.` |
101
- | <img src="examples/stop.jpg" width="180"> | `a sign for a stop sign` |
102
  | <img src="examples/bus.jpg" width="180"> | `the bus is a red double - decoration` |
103
 
104
  ### Chat template
105
 
106
  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").
107
 
 
 
 
 
 
 
 
 
 
108
  > Tested against `transformers` 4.57. Newer major versions may need adjustments.
109
 
110
  **Contributions and suggestions are very welcome** — issues, PRs, and ideas for
@@ -130,4 +137,4 @@ If you use or extend Baguettotron-VLM in your research, please cite it:
130
 
131
  ## License
132
 
133
- Apache 2.0 — see the [GitHub repo](https://github.com/andreagemelli/baguettotron-vlm).
 
16
  base_model:
17
  - OpenGVLab/InternViT-300M-448px-V2_5
18
  - PleIAs/Baguettotron
 
 
19
  ---
20
 
21
  # baguettotron-internvit-alignment
 
36
  — instruction-tuned on top of it. It goes past plain description and follows visual
37
  instructions, so prefer it for a richer chat experience.
38
 
39
+ Apache 2.0. Both live in the [Baguettotron-VLM collection](https://huggingface.co/collections/andreagemelli/baguettotron-vlm-69de37b4cab1960226e9c1f7).
40
+ Source: [github.com/andreagemelli/baguettotron-vlm](https://github.com/andreagemelli/baguettotron-vlm) ·
41
+ Write-up: [andreagemelli.me/posts/baguettotron-vlm](https://andreagemelli.me/posts/baguettotron-vlm/)
42
 
43
 
44
  > **Alignment checkpoint.** Only the MLP projector was trained (on LLaVA-CC3M-Pretrain-595K) — the ViT and the Baguettotron LLM are unmodified base weights. It writes short captions and nothing more. Published so the alignment stage can be reproduced; for actual use take [baguettotron-vision-vqa](https://huggingface.co/andreagemelli/baguettotron-vision-vqa).
 
96
  |---|---|
97
  | <img src="examples/cats.jpg" width="180"> | `a cat is sleeping on the couch` |
98
  | <img src="examples/bear.jpg" width="180"> | `the bear is a good friend.` |
99
+ | <img src="examples/stop.jpg" width="180"> | `a sign for a stop` |
100
  | <img src="examples/bus.jpg" width="180"> | `the bus is a red double - decoration` |
101
 
102
  ### Chat template
103
 
104
  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").
105
 
106
+ ## Limitations
107
+
108
+ - **Resolution ceiling.** One 448×448 crop → 256 visual tokens puts document text at
109
+ roughly 2–4 px/char. OCR, charts and documents are out of reach by architecture, not
110
+ by budget. Neither published checkpoint reads text in an image.
111
+ - **Hallucinations**, especially on fine-grained or text-heavy questions.
112
+ - **Multilingual capability is inherited, not verified.** The backbone covers six
113
+ languages; the VLM was never evaluated on non-English benchmarks.
114
+
115
  > Tested against `transformers` 4.57. Newer major versions may need adjustments.
116
 
117
  **Contributions and suggestions are very welcome** — issues, PRs, and ideas for
 
137
 
138
  ## License
139
 
140
+ Apache 2.0 — see the [GitHub repo](https://github.com/andreagemelli/baguettotron-vlm).
modeling_baguettotron_vlm.py CHANGED
@@ -7,14 +7,36 @@ from transformers import (
7
  AutoModel,
8
  AutoModelForCausalLM,
9
  AutoTokenizer,
 
10
  PreTrainedModel,
11
  StoppingCriteria,
12
  )
 
13
  from transformers.modeling_outputs import CausalLMOutputWithPast
14
 
15
  from .configuration_baguettotron_vlm import BaguettotronVLMConfig
16
 
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  class StopOnTurnEnd(StoppingCriteria):
19
  """Stop when the decoded tail contains a turn marker.
20
 
@@ -237,25 +259,22 @@ class BaguettotronVLMForConditionalGeneration(PreTrainedModel):
237
  )
238
  )
239
 
240
- # transformers' repetition-penalty processor corrupts the very first step
241
- # on MPS: generate(inputs_embeds=...) starts from an empty input_ids, and
242
- # the empty-index gather/scatter zeroes the entire logits row on Metal
243
- # (it is a no-op on CPU and CUDA, as it should be). The result is a
244
- # garbage first token that derails the whole answer.
245
- if inputs_embeds.device.type == "mps" and repetition_penalty != 1.0:
246
- repetition_penalty = 1.0
247
-
248
  # do_sample defaults to greedy but can be overridden by callers
249
  # (e.g. the inference sweep) without colliding on the keyword.
250
  generate_kwargs.setdefault("do_sample", False)
251
  generate_kwargs.setdefault(
252
  "stopping_criteria", [StopOnTurnEnd(self._tokenizer)]
253
  )
 
 
 
 
 
 
254
  output_ids = self.llm.generate(
255
  inputs_embeds=inputs_embeds,
256
  attention_mask=attention_mask,
257
  max_new_tokens=max_new_tokens,
258
- repetition_penalty=repetition_penalty,
259
  eos_token_id=eos_ids,
260
  **generate_kwargs,
261
  )
 
7
  AutoModel,
8
  AutoModelForCausalLM,
9
  AutoTokenizer,
10
+ LogitsProcessor,
11
  PreTrainedModel,
12
  StoppingCriteria,
13
  )
14
+ from transformers.generation.logits_process import RepetitionPenaltyLogitsProcessor
15
  from transformers.modeling_outputs import CausalLMOutputWithPast
16
 
17
  from .configuration_baguettotron_vlm import BaguettotronVLMConfig
18
 
19
 
20
+ class SafeRepetitionPenalty(LogitsProcessor):
21
+ """Repetition penalty that is a no-op on the first decoding step.
22
+
23
+ generate(inputs_embeds=...) begins with an empty input_ids tensor. On MPS
24
+ the empty-index gather inside transformers' RepetitionPenaltyLogitsProcessor
25
+ zeroes the entire logits row rather than leaving it untouched (it is a
26
+ correct no-op on CPU and CUDA), which corrupts the first token and derails
27
+ the answer. There is nothing to penalise on that step anyway, so skipping it
28
+ removes the corruption while keeping the penalty for every later step.
29
+ """
30
+
31
+ def __init__(self, penalty: float):
32
+ self.inner = RepetitionPenaltyLogitsProcessor(penalty)
33
+
34
+ def __call__(self, input_ids: torch.Tensor, scores: torch.Tensor) -> torch.Tensor:
35
+ if input_ids.shape[-1] == 0:
36
+ return scores
37
+ return self.inner(input_ids, scores)
38
+
39
+
40
  class StopOnTurnEnd(StoppingCriteria):
41
  """Stop when the decoded tail contains a turn marker.
42
 
 
259
  )
260
  )
261
 
 
 
 
 
 
 
 
 
262
  # do_sample defaults to greedy but can be overridden by callers
263
  # (e.g. the inference sweep) without colliding on the keyword.
264
  generate_kwargs.setdefault("do_sample", False)
265
  generate_kwargs.setdefault(
266
  "stopping_criteria", [StopOnTurnEnd(self._tokenizer)]
267
  )
268
+ # The penalty goes through SafeRepetitionPenalty rather than generate()'s
269
+ # repetition_penalty kwarg, so the first decoding step is skipped.
270
+ if repetition_penalty != 1.0:
271
+ generate_kwargs.setdefault(
272
+ "logits_processor", [SafeRepetitionPenalty(repetition_penalty)]
273
+ )
274
  output_ids = self.llm.generate(
275
  inputs_embeds=inputs_embeds,
276
  attention_mask=attention_mask,
277
  max_new_tokens=max_new_tokens,
 
278
  eos_token_id=eos_ids,
279
  **generate_kwargs,
280
  )