Read rope_theta from rope_parameters across Inference V2 - #8345
Read rope_theta from rope_parameters across Inference V2#8345alanhuangyoo wants to merge 4 commits into
Conversation
transformers 5.0 folded the rotary settings into config.rope_parameters
and dropped the rope_theta attribute. Eight V2 models still read the
attribute:
llama_v2, mistral, mixtral, phi, phi3, qwen_v2, qwen_v2_moe
self._config.rope_theta -> AttributeError on 5.x
exaone4
getattr(self._config, "rope_theta", 1000000.0)
-> no error, but 1e6 instead of the 1e4 the config carries
exaone4 is the worse of the two: a 100x rotary base is a silent
numerical error, not a startup failure.
exaone4_5 already reads both spellings, added with the model in deepspeedai#8121.
Hoist the same lookup onto DSTransformerModelBase so every model that
reaches it through the base gets it, and raise instead of guessing a
base when neither spelling carries one.
Same drift as deepspeedai#8341, which covers the v1 kernel-injection policy.
Signed-off-by: alanhuangyoo <alanhuangyoo@gmail.com>
A config that sets RoPE per layer type nests the settings one level deeper,
keyed by the layer type, and standardize_rope_params leaves the class default
at the top level of the same dict:
rope_parameters: {'sliding_attention': {'rope_theta': 1000000.0, ...},
'full_attention': {'rope_theta': 16000000.0, ...},
'rope_theta': 10000.0, 'rope_type': 'default'}
Reading the top level returns 10000.0, which is the class default rather than
anything the checkpoint asked for, so the property resolved to a wrong base
quietly instead of raising. The nested entries now win.
When the layer types disagree the config is refused rather than resolved to
one of them. Every caller of this property feeds a single
RotateHalfConfig.theta_base for the whole model, so there is no shape in which
picking either base is right for the layers using the other one.
Released EXAONE-4 configs carry a flat rope_parameters and are unaffected.
Signed-off-by: alanhuangyoo <alanhuangyoo@gmail.com>
ef14c37 to
92ab1af
Compare
|
@tohtana — this is the #8341 is the injection-policy path for Llama; this one is the same |
…-from-rope-parameters
|
New information rather than a ping: #8341 merged this morning, and it is the same bug one layer up.
Merged current master in just now and re-ran on 1×H20; nothing has gone stale.
|
tohtana
left a comment
There was a problem hiding this comment.
Hi @alanhuangyoo, thanks for following up, and sorry I missed your earlier ping before merging #8341.
Yes, this fix is still needed, can we apply the same approach regarding RoPE scaling as in #8341?
In #8341, we ended up rejecting unsupported scaled RoPE configurations to avoid silently producing incorrect results. Could you apply the same protection here? The new rope_theta property currently accepts configurations such as rope_type="llama3" and returns only the scalar theta, while these V2 callers do not propagate the additional scaling parameters. Please also add regression coverage for this rejection through both rope_parameters and the legacy rope_scaling layout, while preserving support for unscaled configurations.
Requested by @tohtana: apply the protection deepspeedai#8341 added for kernel injection here too. Every caller of this property builds `RotateHalfConfig(theta_base=self.rope_theta)`, and that config carries `use_trained_freqs`, `theta_base` and `rotate_dim` and nothing else. A config asking for `rope_type="llama3"` has nowhere to put its scaling parameters, so returning the base alone ran the model with unscaled positions and no error -- the same silent wrong answer deepspeedai#8341 refused. `_rope_types` reads both layouts, since transformers 5.x keeps these in `rope_parameters` and 4.x in `rope_scaling`, both spellings of the key (`rope_type` and `type`), and the per-layer-type entries nested inside either. The check runs before the attribute read, or a 4.x config carrying both `rope_theta` and a scaled `rope_scaling` would return early and never reach it. Coverage, as asked: rejection through `rope_parameters`, through legacy `rope_scaling` under both key spellings, nested per layer type, and with the attribute present; plus the unscaled spellings (absent and `"default"`) still resolving in both layouts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: alanhuangyoo <alanhuangyoo@gmail.com>
|
@tohtana Done in I checked the premise before writing it rather than taking it on faith: every caller of this property does return RotateHalfConfig(theta_base=self.rope_theta)and What the check reads.
It runs before the Coverage, as requested:
Verified they fail for the right reason on the pre-review commit rather than only that they pass now: Whole directory: One thing worth your call: this refuses a model that runs today, silently and wrongly. |
Follow-up to #8341, which covers the same drift in the v1 kernel-injection policy. Separate engine, separate change; #8341 noted this exposure but did not touch it.
What breaks
transformers 5.0 folded the rotary settings into
config.rope_parametersand dropped therope_thetaattribute. Eight V2 models still read the attribute.Seven of them read it directly and raise;
exaone4reads it through agetattrdefault and quietly uses that default instead:llama_v2AttributeError: 'LlamaConfig' object has no attribute 'rope_theta'mistralAttributeError: 'MistralConfig' …mixtralAttributeError: 'MixtralConfig' …phiAttributeError: 'PhiConfig' …phi3AttributeError: 'Phi3Config' …qwen_v2AttributeError: 'Qwen2Config' …qwen_v2_moeAttributeError: 'Qwen2MoeConfig' …exaone4exaone4is the worse of the two.Exaone4Configcarriesrope_parameters['rope_theta'] == 10000.0, so thegetattrdefault puts a 100x rotary base intoRotateHalfConfigwith nothing raised — wrong frequencies rather than a startup failure.requirements-inf.txtasks fortransformers>=4.32.1with no upper bound, so 5.x is in range.The fix
exaone4_5already reads both spellings — added with the model in #8121:Hoist the same lookup onto
DSTransformerModelBaseas arope_thetaproperty.DSMoETransformerModelBaseextends it, so all eight models are covered by one place and each call site becomestheta_base=self.rope_theta.The attribute is tried first, so pre-5.0 installs take exactly the path they take today. When neither spelling carries a base it raises instead of guessing one — that is the only behaviour change beyond the fix, and it replaces
exaone4's silent 1e6.exaone4_5is left alone; its own helper also handles the nested per-layersliding_attentiondict, which is specific to that model.Test
tests/unit/inference/v2/model_implementations/test_rope_theta.py— the three layouts, the precedence between them, the raise, plus a parametrization over the eight real configs from the installed transformers:I exercised the property and the configs, not a full V2 engine run against downloaded checkpoints.