Skip to content

Commit 47eb5cd

Browse files
committed
update format
1 parent ce35993 commit 47eb5cd

9 files changed

Lines changed: 228 additions & 231 deletions

File tree

flagscale/train/datasets/energon/cooker.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
21
import json
32

43
from megatron.energon import stateless
54
from megatron.energon.task_encoder.cooking import Cooker
65

7-
8-
IMAGE_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.webp')
9-
VIDEO_EXTENSIONS = ('.mp4', '.avi', '.mov', '.webm', '.mkv', '.flv')
6+
IMAGE_EXTENSIONS = (".jpg", ".jpeg", ".png", ".webp")
7+
VIDEO_EXTENSIONS = (".mp4", ".avi", ".mov", ".webm", ".mkv", ".flv")
108

119

1210
@stateless
@@ -17,22 +15,22 @@ def cook_bagel_images_sample(sample: dict) -> dict:
1715
000000000.000.jpg -> sample['000.jpg'] (PIL Image or bytes)
1816
000000000.json -> sample['json'] (decoded dict)
1917
"""
20-
json_data = sample.get('json', {})
18+
json_data = sample.get("json", {})
2119
if isinstance(json_data, (bytes, str)):
2220
json_data = json.loads(json_data)
2321

2422
# Collect all image keys (e.g., '000.jpg', '000.png', etc.)
2523
images = []
2624
for key, value in sample.items():
27-
if key.startswith('__'):
25+
if key.startswith("__"):
2826
continue
2927
if any(key.endswith(ext) for ext in IMAGE_EXTENSIONS):
3028
images.append(value)
3129

3230
result = {
33-
**{k: v for k, v in sample.items() if k.startswith('__')}, # preserve meta keys
34-
'json_data': json_data,
35-
'images': images,
31+
**{k: v for k, v in sample.items() if k.startswith("__")}, # preserve meta keys
32+
"json_data": json_data,
33+
"images": images,
3634
}
3735
return result
3836

@@ -54,7 +52,7 @@ def cook_bagel_video_sample(sample: dict) -> dict:
5452
'video_bytes': bytes, # raw video bytes for FrameSampler
5553
}
5654
"""
57-
json_data = sample.get('json', {})
55+
json_data = sample.get("json", {})
5856
if isinstance(json_data, (bytes, str)):
5957
json_data = json.loads(json_data)
6058

@@ -63,11 +61,11 @@ def cook_bagel_video_sample(sample: dict) -> dict:
6361
video_bytes = None
6462
images = []
6563
for key, value in sample.items():
66-
if key.startswith('__'):
64+
if key.startswith("__"):
6765
continue
6866
if any(key.endswith(ext) for ext in VIDEO_EXTENSIONS):
6967
# AVDecoder object → extract raw bytes for decord
70-
if hasattr(value, 'stream'):
68+
if hasattr(value, "stream"):
7169
value.stream.seek(0)
7270
video_bytes = value.stream.read()
7371
value.stream.seek(0)
@@ -80,10 +78,10 @@ def cook_bagel_video_sample(sample: dict) -> dict:
8078
images.append(value)
8179

8280
result = {
83-
**{k: v for k, v in sample.items() if k.startswith('__')}, # preserve meta keys
84-
'json_data': json_data,
85-
'images': images,
86-
'video_bytes': video_bytes,
81+
**{k: v for k, v in sample.items() if k.startswith("__")}, # preserve meta keys
82+
"json_data": json_data,
83+
"images": images,
84+
"video_bytes": video_bytes,
8785
}
8886
return result
8987

flagscale/train/datasets/energon/data_utils.py

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
# Copyright (c) 2025, BAAI. All rights reserved.
22
# Utility functions for Bagel data processing, ported from Bagel's data_utils.py.
33

4-
import math
5-
import random
6-
from PIL import Image, ImageFile, PngImagePlugin
7-
84
import torch
9-
5+
from PIL import Image, ImageFile, PngImagePlugin
106

117
Image.MAX_IMAGE_PIXELS = 200000000
128
ImageFile.LOAD_TRUNCATED_IMAGES = True
139
MaximumDecompressedSize = 1024
14-
MegaByte = 2 ** 20
10+
MegaByte = 2**20
1511
PngImagePlugin.MAX_TEXT_CHUNK = MaximumDecompressedSize * MegaByte
1612

1713

@@ -52,20 +48,22 @@ def prepare_attention_mask_per_sample(split_lens, attn_modes, device="cpu"):
5248

5349
csum = 0
5450
for s, attn_mode in zip(split_lens, attn_modes):
55-
assert attn_mode in ['causal', 'full', 'noise']
51+
assert attn_mode in ["causal", "full", "noise"]
5652
if attn_mode == "causal":
57-
attention_mask[csum:csum + s, csum:csum + s] = torch.ones((s, s), device=device).tril()
58-
attention_mask[csum:csum + s, :csum] = 1
53+
attention_mask[csum : csum + s, csum : csum + s] = torch.ones(
54+
(s, s), device=device
55+
).tril()
56+
attention_mask[csum : csum + s, :csum] = 1
5957
else:
60-
attention_mask[csum:csum + s, csum:csum + s] = torch.ones((s, s))
61-
attention_mask[csum:csum + s, :csum] = 1
58+
attention_mask[csum : csum + s, csum : csum + s] = torch.ones((s, s))
59+
attention_mask[csum : csum + s, :csum] = 1
6260
csum += s
6361

6462
csum = 0
6563
for s, attn_mode in zip(split_lens, attn_modes):
6664
if attn_mode == "noise":
67-
attention_mask[:, csum:csum + s] = torch.zeros((sample_len, s))
68-
attention_mask[csum:csum + s, csum:csum + s] = torch.ones((s, s))
65+
attention_mask[:, csum : csum + s] = torch.zeros((sample_len, s))
66+
attention_mask[csum : csum + s, csum : csum + s] = torch.ones((s, s))
6967
csum += s
7068

7169
attention_mask = torch.zeros_like(attention_mask, dtype=torch.float).masked_fill_(
@@ -74,15 +72,15 @@ def prepare_attention_mask_per_sample(split_lens, attn_modes, device="cpu"):
7472
return attention_mask
7573

7674

77-
def len2weight(x, loss_reduction='square'):
75+
def len2weight(x, loss_reduction="square"):
7876
if x == 0:
7977
return x
80-
if loss_reduction == 'token':
78+
if loss_reduction == "token":
8179
return 1
82-
if loss_reduction == 'sample':
80+
if loss_reduction == "sample":
8381
return 1 / x
84-
if loss_reduction == 'square':
85-
return 1 / (x ** 0.5)
82+
if loss_reduction == "square":
83+
return 1 / (x**0.5)
8684
raise NotImplementedError(loss_reduction)
8785

8886

@@ -107,15 +105,15 @@ def add_special_tokens(tokenizer):
107105
all_special_tokens += v
108106

109107
new_tokens = []
110-
for token in ['<|im_start|>', '<|im_end|>', '<|vision_start|>', '<|vision_end|>']:
108+
for token in ["<|im_start|>", "<|im_end|>", "<|vision_start|>", "<|vision_end|>"]:
111109
if token not in all_special_tokens:
112110
new_tokens.append(token)
113111

114112
num_new_tokens = tokenizer.add_tokens(new_tokens)
115-
bos_token_id = tokenizer.convert_tokens_to_ids('<|im_start|>')
116-
eos_token_id = tokenizer.convert_tokens_to_ids('<|im_end|>')
117-
start_of_image = tokenizer.convert_tokens_to_ids('<|vision_start|>')
118-
end_of_image = tokenizer.convert_tokens_to_ids('<|vision_end|>')
113+
bos_token_id = tokenizer.convert_tokens_to_ids("<|im_start|>")
114+
eos_token_id = tokenizer.convert_tokens_to_ids("<|im_end|>")
115+
start_of_image = tokenizer.convert_tokens_to_ids("<|vision_start|>")
116+
end_of_image = tokenizer.convert_tokens_to_ids("<|vision_end|>")
119117

120118
new_token_ids = dict(
121119
bos_token_id=bos_token_id,

flagscale/train/datasets/energon/sample_types.py

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Sample type definitions for Bagel-Energon integration.
33

44
from dataclasses import dataclass, field
5-
from typing import Any, Dict, List, Optional, Tuple
5+
from typing import Any
66

77
import torch
88

@@ -13,12 +13,13 @@ class BagelSample:
1313
1414
This is what goes into the PackingDataset buffer.
1515
"""
16-
image_tensor_list: List[torch.Tensor] # ViT/VAE preprocessed images
17-
text_ids_list: List[List[int]] # Tokenized text segments
18-
sequence_plan: List[Dict[str, Any]] # Packing instructions per segment
19-
num_tokens: int # Total token count for this sample
20-
is_mandatory: bool = False # Whether this sample must appear in every pack
21-
subflavor: str = "" # Task type: "t2i" / "vlm"
16+
17+
image_tensor_list: list[torch.Tensor] # ViT/VAE preprocessed images
18+
text_ids_list: list[list[int]] # Tokenized text segments
19+
sequence_plan: list[dict[str, Any]] # Packing instructions per segment
20+
num_tokens: int # Total token count for this sample
21+
is_mandatory: bool = False # Whether this sample must appear in every pack
22+
subflavor: str = "" # Task type: "t2i" / "vlm"
2223
# Energon metadata
2324
__key__: str = ""
2425
__restore_key__: tuple = ()
@@ -27,58 +28,59 @@ class BagelSample:
2728
@dataclass
2829
class BagelPackedBatch:
2930
"""Output of pack_selected_samples — a fully packed sequence ready for the model."""
31+
3032
sequence_length: int
31-
sample_lens: List[int]
33+
sample_lens: list[int]
3234
packed_text_ids: torch.Tensor
3335
packed_text_indexes: torch.Tensor
3436
packed_position_ids: torch.Tensor
3537
# FlexAttention fields
36-
split_lens: List[int] = field(default_factory=list)
37-
attn_modes: List[str] = field(default_factory=list)
38+
split_lens: list[int] = field(default_factory=list)
39+
attn_modes: list[str] = field(default_factory=list)
3840
# VAE image generation (optional)
39-
padded_images: Optional[torch.Tensor] = None
40-
patchified_vae_latent_shapes: Optional[List] = None
41-
packed_latent_position_ids: Optional[torch.Tensor] = None
42-
packed_vae_token_indexes: Optional[torch.Tensor] = None
41+
padded_images: torch.Tensor | None = None
42+
patchified_vae_latent_shapes: list | None = None
43+
packed_latent_position_ids: torch.Tensor | None = None
44+
packed_vae_token_indexes: torch.Tensor | None = None
4345
# ViT image understanding (optional)
44-
packed_vit_tokens: Optional[torch.Tensor] = None
45-
packed_vit_position_ids: Optional[torch.Tensor] = None
46-
packed_vit_token_indexes: Optional[torch.Tensor] = None
47-
vit_token_seqlens: Optional[torch.Tensor] = None
46+
packed_vit_tokens: torch.Tensor | None = None
47+
packed_vit_position_ids: torch.Tensor | None = None
48+
packed_vit_token_indexes: torch.Tensor | None = None
49+
vit_token_seqlens: torch.Tensor | None = None
4850
# Diffusion timesteps (optional)
49-
packed_timesteps: Optional[torch.Tensor] = None
50-
mse_loss_indexes: Optional[torch.Tensor] = None
51+
packed_timesteps: torch.Tensor | None = None
52+
mse_loss_indexes: torch.Tensor | None = None
5153
# CE loss (optional)
52-
packed_label_ids: Optional[torch.Tensor] = None
53-
ce_loss_indexes: Optional[torch.Tensor] = None
54-
ce_loss_weights: Optional[torch.Tensor] = None
54+
packed_label_ids: torch.Tensor | None = None
55+
ce_loss_indexes: torch.Tensor | None = None
56+
ce_loss_weights: torch.Tensor | None = None
5557

5658
def to_dict(self):
5759
"""Convert to dict for get_batch compatibility."""
5860
data = {
59-
'sequence_length': self.sequence_length,
60-
'sample_lens': self.sample_lens,
61-
'packed_text_ids': self.packed_text_ids,
62-
'packed_text_indexes': self.packed_text_indexes,
63-
'packed_position_ids': self.packed_position_ids,
64-
'split_lens': self.split_lens,
65-
'attn_modes': self.attn_modes,
61+
"sequence_length": self.sequence_length,
62+
"sample_lens": self.sample_lens,
63+
"packed_text_ids": self.packed_text_ids,
64+
"packed_text_indexes": self.packed_text_indexes,
65+
"packed_position_ids": self.packed_position_ids,
66+
"split_lens": self.split_lens,
67+
"attn_modes": self.attn_modes,
6668
}
6769
if self.padded_images is not None:
68-
data['padded_images'] = self.padded_images
69-
data['patchified_vae_latent_shapes'] = self.patchified_vae_latent_shapes
70-
data['packed_latent_position_ids'] = self.packed_latent_position_ids
71-
data['packed_vae_token_indexes'] = self.packed_vae_token_indexes
70+
data["padded_images"] = self.padded_images
71+
data["patchified_vae_latent_shapes"] = self.patchified_vae_latent_shapes
72+
data["packed_latent_position_ids"] = self.packed_latent_position_ids
73+
data["packed_vae_token_indexes"] = self.packed_vae_token_indexes
7274
if self.packed_vit_tokens is not None:
73-
data['packed_vit_tokens'] = self.packed_vit_tokens
74-
data['packed_vit_position_ids'] = self.packed_vit_position_ids
75-
data['packed_vit_token_indexes'] = self.packed_vit_token_indexes
76-
data['vit_token_seqlens'] = self.vit_token_seqlens
75+
data["packed_vit_tokens"] = self.packed_vit_tokens
76+
data["packed_vit_position_ids"] = self.packed_vit_position_ids
77+
data["packed_vit_token_indexes"] = self.packed_vit_token_indexes
78+
data["vit_token_seqlens"] = self.vit_token_seqlens
7779
if self.packed_timesteps is not None:
78-
data['packed_timesteps'] = self.packed_timesteps
79-
data['mse_loss_indexes'] = self.mse_loss_indexes
80+
data["packed_timesteps"] = self.packed_timesteps
81+
data["mse_loss_indexes"] = self.mse_loss_indexes
8082
if self.packed_label_ids is not None:
81-
data['packed_label_ids'] = self.packed_label_ids
82-
data['ce_loss_indexes'] = self.ce_loss_indexes
83-
data['ce_loss_weights'] = self.ce_loss_weights
83+
data["packed_label_ids"] = self.packed_label_ids
84+
data["ce_loss_indexes"] = self.ce_loss_indexes
85+
data["ce_loss_weights"] = self.ce_loss_weights
8486
return data

flagscale/train/datasets/energon/task_handlers/base.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
2-
31
class BaseTaskHandler:
4-
52
def __init__(self, tokenizer, special_tokens, data_config):
63
self.tokenizer = tokenizer
74
self.special_tokens = special_tokens
Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
1-
import io
21
import json
32
import random
4-
from PIL import Image
53

64
from flagscale.train.datasets.energon.data_utils import pil_img2rgb
75
from flagscale.train.datasets.energon.sample_types import BagelSample
86
from flagscale.train.datasets.energon.task_handlers.base import BaseTaskHandler
97

108

119
class T2IHandler(BaseTaskHandler):
12-
1310
def encode(self, sample, **kwargs):
1411
"""Encode text-to-image sample: caption + VAE image."""
1512
transform = kwargs.get("transform")
1613

17-
data_item = sample.get('json_data')
18-
images = sample.get('images', [])
19-
caption_dict = data_item.get('caption_dict', '')
14+
data_item = sample.get("json_data")
15+
images = sample.get("images", [])
16+
caption_dict = data_item.get("caption_dict", "")
2017
# print(f"{images=}, {caption_dict=}")
2118

2219
assert images is not None and len(images) == 1
@@ -34,7 +31,7 @@ def encode(self, sample, **kwargs):
3431
image_tensor = transform(raw_image)
3532
image_tensor_list.append(image_tensor)
3633
height, width = image_tensor.shape[1:]
37-
num_tokens += width * height // transform_stride ** 2
34+
num_tokens += width * height // transform_stride**2
3835

3936
# Tokenize caption
4037
caption_dict = json.loads(caption_dict)
@@ -46,31 +43,35 @@ def encode(self, sample, **kwargs):
4643
if len(caption_token) > 0:
4744
text_ids_list.append(caption_token)
4845
num_tokens += len(caption_token)
49-
sequence_plan.append({
50-
'type': 'text',
51-
'enable_cfg': 1,
52-
'loss': 0,
53-
'special_token_loss': 0,
54-
'special_token_label': None,
55-
})
46+
sequence_plan.append(
47+
{
48+
"type": "text",
49+
"enable_cfg": 1,
50+
"loss": 0,
51+
"special_token_loss": 0,
52+
"special_token_label": None,
53+
}
54+
)
5655

5756
# VAE image plan
5857
if image_tensor_list:
59-
sequence_plan.append({
60-
'type': 'vae_image',
61-
'enable_cfg': 0,
62-
'loss': 1,
63-
'special_token_loss': 0,
64-
'special_token_label': None,
65-
})
58+
sequence_plan.append(
59+
{
60+
"type": "vae_image",
61+
"enable_cfg": 0,
62+
"loss": 1,
63+
"special_token_loss": 0,
64+
"special_token_label": None,
65+
}
66+
)
6667

6768
return BagelSample(
6869
image_tensor_list=image_tensor_list,
6970
text_ids_list=text_ids_list,
7071
sequence_plan=sequence_plan,
7172
num_tokens=num_tokens,
72-
is_mandatory=sample.get('__subflavors__', {}).get('is_mandatory', False),
73-
subflavor=sample.get('__subflavors__', {}).get("task", "vlm"),
74-
__key__=sample.get('__key__', ''),
75-
__restore_key__=sample.get('__restore_key__', ()),
73+
is_mandatory=sample.get("__subflavors__", {}).get("is_mandatory", False),
74+
subflavor=sample.get("__subflavors__", {}).get("task", "vlm"),
75+
__key__=sample.get("__key__", ""),
76+
__restore_key__=sample.get("__restore_key__", ()),
7677
)

0 commit comments

Comments
 (0)