@@ -47,11 +47,25 @@ def prevalidated_batch_values() -> Iterator[None]:
4747 "syntax" : ("ast_depth_ids" , "sibling_index_ids" , "node_type_ids" ),
4848 "structure" : ("structure_ids" , "dep_levels" ),
4949}
50+ _DOMAIN_ROUTE_FIELD_ALIASES : Mapping [str , tuple [str , ...]] = {
51+ "domain_ids" : ("token_domain_ids" ,),
52+ "role_ids" : ("token_role_ids" ,),
53+ "entity_ids" : ("token_entity_ids" ,),
54+ "scope_ids" : ("token_scope_ids" ,),
55+ "source_doc_ids" : ("token_source_doc_ids" ,),
56+ "source_identity_ids" : ("token_source_identity_ids" ,),
57+ "confidence_ids" : ("token_confidence_ids" ,),
58+ }
5059
5160
5261@dataclass (frozen = True )
5362class LMTokenBatch :
54- """A dense next-token LM batch plus optional cppmega structure side-channels."""
63+ """A dense next-token LM batch plus optional cppmega structure side-channels.
64+
65+ Persisted ``token_*`` domain aliases are accepted in the domain side-channel
66+ family, but only canonical ``domain_ids``/``role_ids``/``confidence_ids``
67+ names are exposed to model kwargs.
68+ """
5569
5670 tokens : mx .array
5771 target_tokens : mx .array | None = None
@@ -156,25 +170,14 @@ def __post_init__(self) -> None:
156170 mx .eval (has_negative )
157171 if bool (has_negative .item ()):
158172 raise ValueError ("platform_ids must be non-negative" )
159- for name , value in self .domain_route_fields ().items ():
173+ if self .side_channels is not None :
174+ _validate_side_channel_map (self .side_channels )
175+ resolved_domain_routes = self .resolved_domain_route_fields ()
176+ for name , value in resolved_domain_routes .items ():
160177 if value is not None and value .shape != self .tokens .shape :
161178 raise ValueError (
162179 f"{ name } must match tokens shape { self .tokens .shape } , got { value .shape } "
163180 )
164- nested_domain_routes = (
165- None if self .side_channels is None else self .side_channels .get ("domain_routes" )
166- )
167- if nested_domain_routes is not None :
168- duplicated = sorted (
169- name
170- for name , value in self .domain_route_fields ().items ()
171- if value is not None and nested_domain_routes .get (name ) is not None
172- )
173- if duplicated :
174- raise ValueError (
175- "domain routes cannot be provided both directly and through "
176- f"side_channels.domain_routes: { duplicated } "
177- )
178181 if self .graph_batch is not None :
179182 if not isinstance (self .graph_batch , GraphBatch ):
180183 raise TypeError (
@@ -205,8 +208,6 @@ def __post_init__(self) -> None:
205208 f"{ name } must be shaped for model inputs as { expected } , "
206209 f"got { tuple (value .shape )} "
207210 )
208- if self .side_channels is not None :
209- _validate_side_channel_map (self .side_channels )
210211 if self .metadata is not None and not isinstance (self .metadata , Mapping ):
211212 raise ValueError ("metadata must be a mapping when provided" )
212213
@@ -260,6 +261,25 @@ def domain_route_fields(self) -> dict[str, mx.array | None]:
260261 "confidence_ids" : self .confidence_ids ,
261262 }
262263
264+ def resolved_domain_route_fields (self ) -> dict [str , mx .array | None ]:
265+ """Return canonical model-facing domain routes without alias ambiguity."""
266+
267+ nested = _canonical_domain_route_channels (
268+ None
269+ if self .side_channels is None
270+ else self .side_channels .get ("domain_routes" )
271+ )
272+ resolved : dict [str , mx .array | None ] = {}
273+ for field_name , direct in self .domain_route_fields ().items ():
274+ nested_value = nested .get (field_name )
275+ if direct is not None and nested_value is not None :
276+ raise ValueError (
277+ "domain routes cannot be provided both directly and through "
278+ f"side_channels.domain_routes: { field_name } "
279+ )
280+ resolved [field_name ] = direct if direct is not None else nested_value
281+ return resolved
282+
263283 def model_kwargs (self ) -> dict [str , Any ]:
264284 kwargs = {
265285 name : self ._input_aligned (value )
@@ -281,15 +301,7 @@ def model_kwargs(self) -> dict[str, Any]:
281301 kwargs ["block_bias" ] = self .graph_attention_bias
282302 if self .graph_edge_kind_bias is not None :
283303 kwargs ["edge_kind_bias" ] = self .graph_edge_kind_bias
284- direct_domain_routes = self .domain_route_fields ()
285- if self .side_channels is not None :
286- domain_routes = self .side_channels .get ("domain_routes" )
287- if domain_routes is not None :
288- for field_name in ("domain_ids" , "role_ids" , "confidence_ids" ):
289- value = domain_routes .get (field_name )
290- if value is not None :
291- kwargs [field_name ] = self ._input_aligned (value )
292- for field_name , value in direct_domain_routes .items ():
304+ for field_name , value in self .resolved_domain_route_fields ().items ():
293305 if value is not None :
294306 kwargs [field_name ] = self ._input_aligned (value )
295307 return kwargs
@@ -308,7 +320,24 @@ def side_channel_map(self) -> dict[str, dict[str, mx.array]]:
308320 out [family ][field_name ] = value
309321 if self .side_channels is not None :
310322 for family , columns in self .side_channels .items ():
311- out .setdefault (family , {}).update (dict (columns ))
323+ if family == "domain_routes" :
324+ canonical = _canonical_domain_route_channels (columns )
325+ out .setdefault (family , {}).update (canonical )
326+ alias_names = {
327+ alias
328+ for aliases in _DOMAIN_ROUTE_FIELD_ALIASES .values ()
329+ for alias in aliases
330+ }
331+ out [family ].update (
332+ {
333+ name : value
334+ for name , value in columns .items ()
335+ if name not in alias_names
336+ and name not in _DOMAIN_ROUTE_FIELD_ALIASES
337+ }
338+ )
339+ else :
340+ out .setdefault (family , {}).update (dict (columns ))
312341 return {family : columns for family , columns in out .items () if columns }
313342
314343 def with_side_channel_dropout (
@@ -430,6 +459,33 @@ def as_dict(
430459_DOCUMENT_ID_ALIASES = ("document_ids" , "doc_ids" , "packing_document_ids" )
431460
432461
462+ def _canonical_domain_route_channels (
463+ channels : Mapping [str , mx .array ] | None ,
464+ ) -> dict [str , mx .array ]:
465+ if channels is None :
466+ return {}
467+ canonical : dict [str , mx .array ] = {}
468+ for field_name , aliases in _DOMAIN_ROUTE_FIELD_ALIASES .items ():
469+ present = [
470+ name
471+ for name in (field_name , * aliases )
472+ if name in channels and channels [name ] is not None
473+ ]
474+ if len (present ) > 1 :
475+ raise ValueError (
476+ "domain route declared more than once via canonical/alias keys: "
477+ f"{ present } "
478+ )
479+ if present :
480+ value = channels [present [0 ]]
481+ if not isinstance (value , mx .array ):
482+ raise ValueError (
483+ f"domain route { present [0 ]!r} must be an mlx array"
484+ )
485+ canonical [field_name ] = value
486+ return canonical
487+
488+
433489def _validate_side_channel_map (
434490 side_channels : Mapping [str , Mapping [str , mx .array ]],
435491) -> None :
0 commit comments