Coverage for  / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / data / text / build_dataset.py: 59%

68 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-11-15 07:18 +0800

1# Copyright 2026 Huawei Technologies Co., Ltd 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================ 

15"""Public Online and Indexed text Dataset builders.""" 

16 

17from __future__ import annotations 

18 

19from collections.abc import Callable, Mapping, Sequence 

20from typing import Any 

21 

22from hyper_parallel.data.dataset_logging import get_dataset_logger 

23from hyper_parallel.data.indexed.indexed_dataset import ( 

24 build_indexed_dataset as _build_indexed_dataset, 

25) 

26from hyper_parallel.data.online import ( 

27 IterableTransformDataset, 

28 MappingTransformDataset, 

29 OnlineDataPath, 

30 build_online_iterable_source, 

31 build_online_mapping_source, 

32) 

33from hyper_parallel.data.parallel import ( 

34 DataLoaderParallelContext, 

35 create_dataloader_parallel_context, 

36) 

37 

38logger = get_dataset_logger(__name__) 

39 

40 

41def _build_dataloader_context( 

42 mesh_context: Any, 

43 data_config: Mapping[str, Any], 

44) -> DataLoaderParallelContext | None: 

45 """Build DataLoader ownership from the runtime mesh when available.""" 

46 if mesh_context is None: 

47 return None 

48 

49 dataloader_context = create_dataloader_parallel_context( 

50 mesh_context, 

51 data_index_cache=bool(data_config.get("data_index_cache", False)), 

52 shared_storage=not bool(data_config.get("no_shared_storage", False)), 

53 ) 

54 return dataloader_context 

55 

56 

57def _get_train_valid_test_num_samples(training_config: Any) -> tuple[int, int, int]: 

58 """Calculate train, validation, and test sizes from the training plan.""" 

59 if training_config is None: 

60 raise ValueError("Dataset sample planning requires a training configuration") 

61 

62 global_batch_size = training_config.global_batch_size 

63 if training_config.train_iters is not None: 

64 train_iters = training_config.train_iters 

65 elif training_config.train_samples: 

66 train_iters = training_config.train_samples // global_batch_size 

67 else: 

68 raise ValueError("training.train_iters and training.train_samples cannot both be None") 

69 

70 train_samples = training_config.train_samples or train_iters * global_batch_size 

71 eval_iters = training_config.eval_iters 

72 valid_iters = (train_iters // eval_iters + 1) * eval_iters if eval_iters else 0 

73 split_sizes = (train_samples, valid_iters * global_batch_size, eval_iters * global_batch_size) 

74 logger.debug("Dataset target sizes: train=%d, validation=%d, test=%d", *split_sizes) 

75 return split_sizes 

76 

77 

78def build_online_text_mapping_dataset( 

79 *, 

80 data_config: Mapping[str, Any], 

81 data_path: OnlineDataPath | None = None, 

82 transform: Callable[[Any], Any] | None = None, 

83 training_config: Any = None, 

84 sampler_type: str = "single", 

85) -> Any: 

86 """Build an Online Mapping Dataset and apply its text transform. 

87 

88 Args: 

89 data_config: Online Mapping source options. 

90 data_path: Optional local source path, ordered paths, or pre-split 

91 train/valid/test path mapping. Use ``data_config.sources`` for 

92 multiple sources. 

93 transform: Plaintext or conversation sample transform. 

94 training_config: Training plan providing the random seed and split sizes. 

95 sampler_type: Mapping sampler policy controlling source-level shuffle. 

96 

97 Returns: 

98 A transformed Online Dataset on each DataLoader-owning rank. 

99 

100 Raises: 

101 ValueError: If no Online text transform is configured. 

102 """ 

103 if transform is None: 

104 raise ValueError("Online Dataset requires a plaintext or conversation data_transform") 

105 

106 dataset_config = dict(data_config) 

107 training_seed = getattr(training_config, "seed", None) 

108 dataset_config["random_seed"] = 42 if training_seed is None else int(training_seed) 

109 train_valid_test_num_samples = None 

110 if training_config is not None: 

111 train_valid_test_num_samples = _get_train_valid_test_num_samples(training_config) 

112 sample_filter = transform.is_valid_sample 

113 source_dataset = build_online_mapping_source( 

114 data_path=data_path, 

115 data_config=dataset_config, 

116 sample_filter=sample_filter, 

117 sampler_type=sampler_type, 

118 train_valid_test_num_samples=train_valid_test_num_samples, 

119 ) 

120 text_dataset = MappingTransformDataset.apply(source_dataset, transform) 

121 return text_dataset 

122 

123 

124def build_online_iterable_dataset( 

125 *, 

126 data_config: Mapping[str, Any], 

127 data_path: OnlineDataPath | None = None, 

128 transform: Callable[[Any], Any] | None = None, 

129 dataloader_context: DataLoaderParallelContext | None = None, 

130 mesh_context: Any = None, 

131 training_config: Any = None, 

132) -> Any: 

133 """Build an Online Iterable Dataset and apply its text transform. 

134 

135 Args: 

136 data_config: Online Iterable source options. 

137 data_path: Optional local source path, ordered paths, or Hub Dataset 

138 ID. Use ``data_config.sources`` for multiple sources. 

139 transform: Plaintext or conversation sample transform. 

140 dataloader_context: Optional explicit DataLoader ownership context. 

141 mesh_context: Runtime mesh used to derive Iterable source ownership. 

142 training_config: Training plan providing the shuffle seed. 

143 

144 Returns: 

145 A transformed Online Iterable Dataset on each DataLoader-owning rank. 

146 

147 Raises: 

148 ValueError: If no Online text transform is configured. 

149 """ 

150 if transform is None: 

151 raise ValueError("Online Dataset requires a plaintext or conversation data_transform") 

152 

153 dataset_config = dict(data_config) 

154 training_seed = getattr(training_config, "seed", None) 

155 dataset_config["random_seed"] = 42 if training_seed is None else int(training_seed) 

156 sample_filter = transform.is_valid_sample 

157 if dataloader_context is None: 

158 dataloader_context = _build_dataloader_context(mesh_context, dataset_config) 

159 

160 source_dataset = build_online_iterable_source( 

161 data_path=data_path, 

162 data_config=dataset_config, 

163 dataloader_context=dataloader_context, 

164 sample_filter=sample_filter, 

165 ) 

166 text_dataset = IterableTransformDataset.apply(source_dataset, transform) 

167 return text_dataset 

168 

169 

170def build_indexed_text_dataset( 

171 *, 

172 data_config: Mapping[str, Any], 

173 data_path: str | Sequence[str] | None = None, 

174 tokenizer: Any = None, 

175 train_valid_test_num_samples: Sequence[int] | None = None, 

176 dataloader_context: DataLoaderParallelContext | None = None, 

177 mesh_context: Any = None, 

178 training_config: Any = None, 

179) -> Any: 

180 """Build train, validation, and test Datasets from Indexed token files. 

181 

182 Args: 

183 data_config: Indexed Dataset and split options. 

184 data_path: Indexed prefix, directory, or ordered paths. 

185 tokenizer: Tokenizer providing vocabulary and EOD metadata. 

186 train_valid_test_num_samples: Optional explicit split sizes. 

187 dataloader_context: Optional explicit DataLoader ownership context. 

188 mesh_context: Runtime mesh used to derive DataLoader ownership. 

189 training_config: Training plan used to derive split sizes and seed. 

190 

191 Returns: 

192 Train, validation, and test Indexed Datasets. 

193 

194 Raises: 

195 ValueError: If required path or training information is missing. 

196 """ 

197 dataset_config = dict(data_config) 

198 dataset_config.setdefault("distributed_walk", True) 

199 training_seed = getattr(training_config, "seed", None) 

200 dataset_config["random_seed"] = 42 if training_seed is None else int(training_seed) 

201 if tokenizer is not None: 

202 dataset_config["tokenizer"] = tokenizer 

203 

204 if data_path is None and not bool(dataset_config.get("mock_data", False)): 

205 raise ValueError("Indexed Dataset requires data_path") 

206 

207 if train_valid_test_num_samples is None: 

208 train_valid_test_num_samples = _get_train_valid_test_num_samples(training_config) 

209 

210 if dataloader_context is None: 

211 dataloader_context = _build_dataloader_context(mesh_context, dataset_config) 

212 

213 indexed_datasets = _build_indexed_dataset( 

214 data_path=data_path, 

215 data_config=dataset_config, 

216 train_valid_test_num_samples=train_valid_test_num_samples, 

217 dataloader_context=dataloader_context, 

218 ) 

219 return indexed_datasets