Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / distributed_data / data_constructor.py: 88%
34 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-15 07:18 +0800
« 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"""Target-rank Data Constructor for plan-ordered packing and collation."""
17from __future__ import annotations
19from collections.abc import Callable, Mapping, Sequence
20from typing import Any
22from hyper_parallel.distributed_data.schema import PackingBinPlan, SampleKey
25def default_pack_fn(samples: Sequence[Any], seq_len: int) -> tuple[Any, ...]:
26 """Preserve one planned packing bin without assuming a sample schema.
28 Args:
29 samples: Raw samples assigned to one Planner-validated bin, including
30 an explicitly permitted singleton overflow when configured.
31 seq_len: Configured normal sequence capacity.
33 Returns:
34 Immutable raw samples in their deterministic planned order.
35 """
36 if not isinstance(seq_len, int) or isinstance(seq_len, bool) or seq_len < 1:
37 raise ValueError(f"seq_len must be a positive integer, but got {seq_len!r}.")
38 return tuple(samples)
41def default_collate_fn(packed_sequences: Sequence[Any]) -> tuple[Any, ...]:
42 """Preserve the planned bins as one immutable rank-local batch.
44 Args:
45 packed_sequences: Outputs produced for this rank's packing bins.
47 Returns:
48 Immutable bins in contiguous ``pack_index`` order.
49 """
50 return tuple(packed_sequences)
53class PackingDataConstructor:
54 """Apply configured packing per planned bin and collate one local batch.
56 ``pack_fn`` never runs in a Dataset Reader. It receives raw samples only
57 after sample-level planning and CPU redistribution have completed.
58 """
60 def __init__(
61 self,
62 pack_fn: Callable[[Sequence[Any], int], Any],
63 collate_fn: Callable[[Sequence[Any]], Any],
64 *,
65 seq_len: int,
66 ) -> None:
67 """Initialize user callbacks.
69 Args:
70 pack_fn: Called once per planned sequence bin as
71 ``pack_fn(raw_samples, seq_len)``.
72 collate_fn: Called once per local batch with packed sequences.
73 seq_len: Maximum non-oversized sequence length.
74 """
75 if not callable(pack_fn) or not callable(collate_fn):
76 raise ValueError("pack_fn and collate_fn must be callable.")
77 if not isinstance(seq_len, int) or isinstance(seq_len, bool) or seq_len < 1:
78 raise ValueError(f"seq_len must be a positive integer, but got {seq_len!r}.")
79 self._pack_fn = pack_fn
80 self._collate_fn = collate_fn
81 self._seq_len = seq_len
83 def construct(
84 self,
85 plan: Sequence[PackingBinPlan],
86 payloads: Mapping[SampleKey, Any],
87 ) -> Any:
88 """Construct one target-rank local batch.
90 Args:
91 plan: Ordered packing bins assigned to this Data Constructor.
92 payloads: Received raw samples keyed by stable Dataset Reader and
93 Dataset-index identity.
95 Returns:
96 User-collated rank-local batch.
97 """
98 expected_keys = tuple(
99 key
100 for packing_bin in plan
101 for key in packing_bin.sample_keys
102 )
103 expected_set = set(expected_keys)
104 if len(payloads) != len(expected_keys) or payloads.keys() != expected_set:
105 missing = expected_set - payloads.keys()
106 unexpected = payloads.keys() - expected_set
107 raise ValueError(
108 f"Data Constructor payload keys do not match the plan; "
109 f"missing={sorted(missing)}, unexpected={sorted(unexpected)}."
110 )
112 packed_sequences = []
113 for pack_index, packing_bin in enumerate(plan):
114 if packing_bin.pack_tokens > self._seq_len and not packing_bin.oversized:
115 raise ValueError(
116 f"Packing bin {pack_index} has {packing_bin.pack_tokens} tokens, "
117 f"exceeding seq_len={self._seq_len}."
118 )
119 raw_samples = [payloads[key] for key in packing_bin.sample_keys]
120 packed_sequences.append(self._pack_fn(raw_samples, self._seq_len))
121 return self._collate_fn(packed_sequences)
124__all__ = ["PackingDataConstructor", "default_collate_fn", "default_pack_fn"]