Skip to content

Commit 305adb8

Browse files
committed
Merge branch 'fix/mlm-seq2seq-suffix-window'
1 parent 093b1c5 commit 305adb8

6 files changed

Lines changed: 46 additions & 60 deletions

File tree

docs/models/mlm.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,10 @@ Task dataset and preprocessing: [TinyGSM](../tasks/tinygsm.md). GSM8K and code-e
138138
| Setting | Value |
139139
|---------|--------|
140140
| Tokenizer | Qwen2-0.5B (`Qwen/Qwen2-0.5B`) with added `<|mask|>` |
141-
| `block_size` | 512 |
142-
| `input_block_size` | 0 |
143-
| `model.max_length` | 2048 (prompt + `block_size` suffix; overrides default 516) |
141+
| `block_size` | 256 |
142+
| `input_block_size` | 256 |
144143
| Batching | Per-device 32; global 512 |
145-
| Collators | STAR seq2seq (`seq2seq_*` / `seq2seq_pred_*`); no BOS; train/val `truncate: null` |
144+
| Collators | STAR seq2seq (`seq2seq_*` / `seq2seq_pred_*`); no BOS |
146145
| Val / test prediction | Post-hoc `code_exec_accuracy` (`Gsm8kCodeEval`); token EM disabled |
147146
| Monitored metric | `val/lm/accumulated_loss` |
148147
| Training schedule | Up to 1M steps; validation every 50k steps; checkpoint every 2.5k steps (keep every 100k) |

tests/models/mlm/test_collator_mlm.py

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -189,38 +189,3 @@ def test_star_hidden_tail_and_suffix_slot(self, simple_tokenizer):
189189
# MLM masks only in suffix slot
190190
suffix_region = batch["input_ids"][0, 4:visible_len]
191191
assert (suffix_region == mask).any()
192-
193-
def test_tinygsm_variable_prefix_no_shared_block(self, simple_tokenizer):
194-
torch.manual_seed(0)
195-
pad = simple_tokenizer.pad_token_id
196-
eos = simple_tokenizer.eos_token_id
197-
mask = simple_tokenizer.mask_token_id
198-
block_size = 8
199-
200-
batch = prepare_prefix_suffix_ids(
201-
prefix_ids=[[10, 11, 12, 13, 14], [20, 21]],
202-
suffix_ids=[[30, 31], [40, 41, 42]],
203-
pad_token_id=pad,
204-
mask_token_id=mask,
205-
eos_token_id=eos,
206-
bos_token_id=None,
207-
max_seq_len=None,
208-
truncate=None,
209-
suffix_block_size=block_size,
210-
)
211-
212-
# Batch padded to max visible: 5 + 8 = 13 vs 2 + 8 = 10
213-
assert batch["input_ids"].shape == (2, 13)
214-
visible_len_0 = 5 + block_size
215-
visible_len_1 = 2 + block_size
216-
assert batch["attention_mask"][0, :visible_len_0].all()
217-
assert not batch["attention_mask"][0, visible_len_0:].any()
218-
assert batch["attention_mask"][1, :visible_len_1].all()
219-
assert not batch["attention_mask"][1, visible_len_1:].any()
220-
assert (batch["target_ids"][1, visible_len_1:] == -100).all()
221-
# Suffix slot starts right after prompt (no BOS); check targets for layout
222-
assert batch["target_ids"][0, 5] == 30
223-
assert batch["target_ids"][0, 6] == 31
224-
assert batch["target_ids"][0, 7] == eos
225-
assert (batch["input_ids"][0, 5:visible_len_0] == mask).any()
226-
assert (batch["input_ids"][0, :5] != mask).all()

tests/models/mlm/test_predictor_mlm.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,36 @@ def test_both_top_k_and_top_p_raises(
100100
top_k=5,
101101
top_p=0.9,
102102
)
103+
104+
105+
class TestMLMPredictorSeq2SeqMaskInjection:
106+
"""Seq2seq inference appends exactly ``max_new_tokens`` [MASK] slots."""
107+
108+
def test_appends_block_size_masks_after_prefix(
109+
self, tiny_mlm_model, simple_tokenizer, dummy_noise_schedule
110+
):
111+
block_size = 8
112+
input_block_size = 16
113+
predictor = MLMPredictor(
114+
max_steps=block_size,
115+
max_new_tokens=block_size,
116+
tokenizer=simple_tokenizer,
117+
model=tiny_mlm_model,
118+
noise_schedule=dummy_noise_schedule,
119+
top_k=1,
120+
)
121+
batch = {
122+
"input_ids": torch.tensor(
123+
[[0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0]],
124+
dtype=torch.long,
125+
),
126+
"attention_mask": torch.tensor(
127+
[[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]],
128+
dtype=torch.bool,
129+
),
130+
}
131+
with torch.no_grad():
132+
preds = predictor.predict(batch)
133+
assert preds["output_start_idx"] == input_block_size
134+
assert preds["ids"].shape == (1, input_block_size + block_size)
135+
assert preds["ids"].shape[-1] - preds["output_start_idx"] == block_size

xlm-models/mlm/configs/datamodule/tinygsm_mlm.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ datamodule:
1717
lm:
1818
collator:
1919
add_bos: false
20-
truncate: null
2120
val:
2221
lm:
2322
collator:
2423
add_bos: false
25-
truncate: null
2624
prediction:
2725
collator:
2826
add_bos: false

xlm-models/mlm/configs/experiment/tinygsm_mlm.yaml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,10 @@ add_eos: true
1010
per_device_batch_size: 32
1111
global_batch_size: 512
1212
num_dataloader_workers: 5
13-
block_size: 512
14-
input_block_size: 0
13+
block_size: 256
14+
input_block_size: 256
1515
monitored_metric: val/lm/accumulated_loss
1616

17-
# prompt + block_size suffix can exceed default rotary max_length (516)
18-
model:
19-
max_length: 2048
20-
2117
global_components:
2218
tokenizer:
2319
_target_: xlm.datamodule.load_auto_tokenizer

xlm-models/mlm/datamodule_mlm.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -504,21 +504,15 @@ def __call__(
504504
suffix_lists = [
505505
seq2seq_suffix_ids(e, self.target_field) for e in examples
506506
]
507-
if self.input_block_size == 0:
508-
max_seq_len = None
509-
truncate = None
510-
else:
511-
max_seq_len = self.input_block_size + self.block_size
512-
truncate = self.truncate
513507
prefix_suffix = prepare_prefix_suffix_ids(
514508
[e["prompt_ids"] for e in examples],
515509
suffix_lists,
516510
self.tokenizer.pad_token_id,
517511
self.tokenizer.mask_token_id,
518512
eos_token_id=self.tokenizer.eos_token_id if self.add_eos else None,
519513
bos_token_id=self.tokenizer.bos_token_id if self.add_bos else None,
520-
max_seq_len=max_seq_len,
521-
truncate=truncate,
514+
max_seq_len=(self.input_block_size + self.block_size),
515+
truncate=self.truncate,
522516
loss_on_padding=self.loss_on_padding,
523517
suffix_block_size=self.block_size,
524518
)
@@ -677,12 +671,13 @@ def __call__(
677671
examples: List[Seq2SeqCollatorInput],
678672
) -> MLMBatch:
679673
pf = self.prompt_field
674+
prefix_ids_list = [e[pf] for e in examples] # type: ignore[misc]
675+
if self.add_bos:
676+
prefix_ids_list = [
677+
p + [self.tokenizer.bos_token_id] for p in prefix_ids_list
678+
]
680679
prefix = prepare_prefix_ids(
681-
[
682-
e[pf] # type: ignore[misc]
683-
+ [self.tokenizer.bos_token_id] * int(self.add_bos)
684-
for e in examples
685-
],
680+
prefix_ids_list,
686681
self.tokenizer.pad_token_id,
687682
max_seq_len=self.input_block_size,
688683
)

0 commit comments

Comments
 (0)