(batch: Any, microbatch_size: Union[int, float], padding_tolerance=1.0)
| 532 | |
| 533 | |
| 534 | def split_packed_batch(batch: Any, microbatch_size: Union[int, float], padding_tolerance=1.0) -> Sequence: |
| 535 | # NOTE: Packed sequences are already packed into a microbatch size worth of tokens. |
| 536 | # So to correctly return a microbatch worth of data, we will simply return each item (i.e. microbatch_size 1) |
| 537 | |
| 538 | num_items = batch["input_ids"].shape[0] |
| 539 | split_inputs = [x.squeeze() for x in batch["input_ids"].split(1)] |
| 540 | split_labels = [x.squeeze() for x in batch["labels"].split(1)] |
| 541 | split_attention_masks = [x.squeeze() for x in batch["attention_mask"].split(1)] |
| 542 | split_cu_seqlens = batch["cu_seqlens"] |
| 543 | |
| 544 | result = [] |
| 545 | for i in range(num_items): |
| 546 | attention_mask = split_attention_masks[i] |
| 547 | padding_amount = 1 - (attention_mask.sum() / len(attention_mask)) |
| 548 | |
| 549 | if padding_amount > padding_tolerance: |
| 550 | last_non_pad = attention_mask.nonzero().max() |
| 551 | input_ids = split_inputs[i][: last_non_pad + 1] |
| 552 | labels = split_labels[i][: last_non_pad + 1] |
| 553 | cu_seqlens = split_cu_seqlens[i][:-1] |
| 554 | attention_mask = attention_mask[: last_non_pad + 1] |
| 555 | else: |
| 556 | input_ids = split_inputs[i] |
| 557 | labels = split_labels[i] |
| 558 | cu_seqlens = split_cu_seqlens[i] |
| 559 | |
| 560 | result.append( |
| 561 | { |
| 562 | "input_ids": input_ids, |
| 563 | "labels": labels, |
| 564 | "cu_seqlens": cu_seqlens, |
| 565 | "max_seqlen": batch["max_seqlen"][i], |
| 566 | "attention_mask": attention_mask, |
| 567 | } |
| 568 | ) |
| 569 | |
| 570 | assert all([x["input_ids"].shape[-1] == y["cu_seqlens"][-1] for x, y in zip(result, result)]) |
| 571 | return result |
| 572 | |
| 573 | |
| 574 | def get_num_samples_in_packed_batch(batch: Batch) -> int: |
no outgoing calls