|
3 | 3 |
|
4 | 4 | """Kimi Task Encoder.""" |
5 | 5 |
|
| 6 | +import logging |
6 | 7 | import torch |
7 | 8 | from loongforge.data.multimodal.vlm_task_encoder import VLMTaskEncoder |
8 | 9 | from typing import Dict, List, Optional, Tuple, Union |
|
26 | 27 |
|
27 | 28 |
|
28 | 29 | from loongforge.utils import constants, get_chat_template |
| 30 | +from megatron.energon.task_encoder.base import stateless |
| 31 | +from loongforge.data.multimodal import MultiMixQASample, MultiVidQASample |
29 | 32 | from .base.task_encoder import ( |
30 | 33 | BaseTaskEncoder, |
31 | 34 | BaseTaskSample, |
@@ -96,6 +99,51 @@ def __init__(self, args): |
96 | 99 | else: |
97 | 100 | self.merge_kernel_size = list(merge_kernel_size) |
98 | 101 |
|
| 102 | + def _sample_sequence_limit(self) -> int: |
| 103 | + sequence_limit = self.args.seq_length |
| 104 | + packed_limit = getattr(self.args, "max_packed_tokens", None) |
| 105 | + if self.is_packing_enabled and packed_limit is not None: |
| 106 | + sequence_limit = min(sequence_limit, packed_limit) |
| 107 | + return sequence_limit |
| 108 | + |
| 109 | + def _should_discard_overlong(self, sample, input_ids) -> bool: |
| 110 | + if not self.args.enable_discard_sample: |
| 111 | + return False |
| 112 | + |
| 113 | + sequence_limit = self._sample_sequence_limit() |
| 114 | + input_length = len(input_ids) |
| 115 | + if input_length <= sequence_limit: |
| 116 | + return False |
| 117 | + |
| 118 | + logging.warning( |
| 119 | + "discard overlong sample %s: input length %s > sequence limit %s", |
| 120 | + sample.__key__, |
| 121 | + input_length, |
| 122 | + sequence_limit, |
| 123 | + ) |
| 124 | + return True |
| 125 | + |
| 126 | + @stateless(restore_seeds=True) |
| 127 | + def encode_sample( |
| 128 | + self, |
| 129 | + sample: Union[CaptioningSample, VQASample, MultiVidQASample, MultiMixQASample], |
| 130 | + ): |
| 131 | + """Return tokenised multimodal sample.""" |
| 132 | + if isinstance(sample, CaptioningSample): |
| 133 | + encoded_sample = self.encode_captioning(sample) |
| 134 | + elif isinstance(sample, VQASample): |
| 135 | + encoded_sample = self.encode_vqa(sample) |
| 136 | + elif isinstance(sample, MultiVidQASample): |
| 137 | + encoded_sample = self.encode_multi_vid_qa(sample) |
| 138 | + elif isinstance(sample, MultiMixQASample): |
| 139 | + encoded_sample = self.encode_multi_mix_qa(sample) |
| 140 | + else: |
| 141 | + yield from super().encode_sample(sample) |
| 142 | + return |
| 143 | + |
| 144 | + if encoded_sample is not None: |
| 145 | + yield encoded_sample |
| 146 | + |
99 | 147 | def _get_vision_token_ids(self): |
100 | 148 | """Get special token IDs for vision processing.""" |
101 | 149 | media_begin_id = self.tokenizer.convert_tokens_to_ids(MEDIA_BEGIN) |
@@ -352,11 +400,9 @@ def encode_captioning(self, sample: CaptioningSample) -> BaseTaskSample: |
352 | 400 | ) |
353 | 401 | num_tiles = [len(image_grid_thw)] if image_grid_thw is not None else [0] |
354 | 402 |
|
355 | | - if self.args.enable_discard_sample: |
356 | | - assert ( |
357 | | - len(input_ids) <= self.args.seq_length |
358 | | - ), f"{sample.__key__} input length {len(input_ids)}" |
359 | | - elif image_grid_thw is not None: |
| 403 | + if self._should_discard_overlong(sample, input_ids): |
| 404 | + return None |
| 405 | + if not self.args.enable_discard_sample and image_grid_thw is not None: |
360 | 406 | assert ( |
361 | 407 | image_grid_thw.prod() / 4 <= self.args.seq_length |
362 | 408 | ), f"{sample.__key__} thw {image_grid_thw}" |
@@ -414,11 +460,9 @@ def encode_vqa(self, sample: VQASample) -> BaseTaskSample: |
414 | 460 |
|
415 | 461 | num_tiles = [len(image_grid_thw)] if image_grid_thw is not None else [0] |
416 | 462 |
|
417 | | - if self.args.enable_discard_sample: |
418 | | - assert ( |
419 | | - len(input_ids) <= self.args.seq_length |
420 | | - ), f"{sample.__key__} input length {len(input_ids)}" |
421 | | - elif image_grid_thw is not None: |
| 463 | + if self._should_discard_overlong(sample, input_ids): |
| 464 | + return None |
| 465 | + if not self.args.enable_discard_sample and image_grid_thw is not None: |
422 | 466 | assert ( |
423 | 467 | image_grid_thw.prod() / 4 <= self.args.seq_length |
424 | 468 | ), f"{sample.__key__} grid_thw: {image_grid_thw}" |
@@ -564,15 +608,21 @@ def encode_multi_mix_qa(self, sample) -> BaseTaskSample: |
564 | 608 | f"Unknown training phase {self.args.training_phase}" |
565 | 609 | ) |
566 | 610 |
|
567 | | - if self.args.enable_discard_sample: |
568 | | - assert ( |
569 | | - len(input_ids) <= self.args.seq_length |
570 | | - ), f"{sample.__key__} input length {len(input_ids)}" |
571 | | - elif sample.video is not None and video_grid_thw is not None: |
| 611 | + if self._should_discard_overlong(sample, input_ids): |
| 612 | + return None |
| 613 | + if ( |
| 614 | + not self.args.enable_discard_sample |
| 615 | + and sample.video is not None |
| 616 | + and video_grid_thw is not None |
| 617 | + ): |
572 | 618 | assert ( |
573 | 619 | video_grid_thw.prod(dim=-1).sum() / 4 <= self.args.seq_length |
574 | 620 | ), f"{sample.__key__} grid_thw: {video_grid_thw}" |
575 | | - elif sample.image is not None and image_grid_thw is not None: |
| 621 | + elif ( |
| 622 | + not self.args.enable_discard_sample |
| 623 | + and sample.image is not None |
| 624 | + and image_grid_thw is not None |
| 625 | + ): |
576 | 626 | assert ( |
577 | 627 | image_grid_thw.prod(dim=-1).sum() / 4 <= self.args.seq_length |
578 | 628 | ), f"{sample.__key__} grid_thw: {image_grid_thw}" |
@@ -626,11 +676,9 @@ def encode_multi_vid_qa(self, sample) -> BaseTaskSample: |
626 | 676 | f"Unknown training phase {self.args.training_phase}" |
627 | 677 | ) |
628 | 678 |
|
629 | | - if self.args.enable_discard_sample: |
630 | | - assert ( |
631 | | - len(input_ids) <= self.args.seq_length |
632 | | - ), f"{sample.__key__} input length {len(input_ids)}" |
633 | | - elif video_grid_thw is not None: |
| 679 | + if self._should_discard_overlong(sample, input_ids): |
| 680 | + return None |
| 681 | + if not self.args.enable_discard_sample and video_grid_thw is not None: |
634 | 682 | assert ( |
635 | 683 | video_grid_thw.prod(dim=-1).sum() / 4 <= self.args.seq_length |
636 | 684 | ), f"{sample.__key__} grid_thw: {video_grid_thw}" |
|
0 commit comments