Repository: huggingface/transformers
Pull request: Fix GraniteConfig type hints to accept int for multiplier fields

## What does this PR do?

Fixes #44877

Loading `ibm-granite/granite-4.0-1b-speech` fails with
`StrictDataclassFieldValidationError` because its config.json stores
`embedding_multiplier` and `logits_scaling` as integers (e.g. `12`, `8`),
but `GraniteConfig` declares them as `float`.

The fix updates the type hints for all four multiplier fields to `float | int`,
matching the pattern already used for `attention_dropout` in the same class.

- [x] I confirm that this is not a pure code agent PR.
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [x] Did you read the contributor guideline, Pull Request section?
- [x] Was this discussed/approved via a Github issue or the forum?
- [ ] Did you make sure to update the documentation with your changes?
- [x] Did you write any new necessary tests?

Changed files:
filename: src/transformers/models/granite/configuration_granite.py
patch: @@ -80,10 +80,10 @@ class GraniteConfig(PreTrainedConfig):
     attention_bias: bool = False
     attention_dropout: float | int = 0.0
     mlp_bias: bool = False
-    embedding_multiplier: float = 1.0
-    logits_scaling: float = 1.0
-    residual_multiplier: float = 1.0
-    attention_multiplier: float = 1.0
+    embedding_multiplier: float | int = 1.0
+    logits_scaling: float | int = 1.0
+    residual_multiplier: float | int = 1.0
+    attention_multiplier: float | int = 1.0
 
     def __post_init__(self, **kwargs):
         if self.num_key_value_heads is None:

filename: src/transformers/models/granitemoe/configuration_granitemoe.py
patch: @@ -64,10 +64,10 @@ class GraniteMoeConfig(PreTrainedConfig):
     rope_parameters: RopeParameters | dict | None = None
     attention_bias: bool = False
     attention_dropout: float | int | None = 0.0
-    embedding_multiplier: float | None = 1.0
-    logits_scaling: float | None = 1.0
-    residual_multiplier: float | None = 1.0
-    attention_multiplier: float | None = 1.0
+    embedding_multiplier: float | int | None = 1.0
+    logits_scaling: float | int | None = 1.0
+    residual_multiplier: float | int | None = 1.0
+    attention_multiplier: float | int | None = 1.0
     num_local_experts: int | None = 8
     num_experts_per_tok: int | None = 2
     output_router_logits: bool | None = False

filename: src/transformers/models/granitemoeshared/configuration_granitemoeshared.py
patch: @@ -75,10 +75,10 @@ class GraniteMoeSharedConfig(PreTrainedConfig):
     rope_parameters: RopeParameters | dict | None = None
     attention_bias: bool = False
     attention_dropout: float | int | None = 0.0
-    embedding_multiplier: float | None = 1.0
-    logits_scaling: float | None = 1.0
-    residual_multiplier: float | None = 1.0
-    attention_multiplier: float | None = 1.0
+    embedding_multiplier: float | int | None = 1.0
+    logits_scaling: float | int | None = 1.0
+    residual_multiplier: float | int | None = 1.0
+    attention_multiplier: float | int | None = 1.0
     num_local_experts: int | None = 8
     num_experts_per_tok: int | None = 2
     output_router_logits: bool | None = False

filename: tests/models/granite/test_modeling_granite.py
patch: @@ -13,6 +13,7 @@
 # limitations under the License.
 """Testing suite for the PyTorch Granite model."""
 
+import tempfile
 import unittest
 
 from transformers import GraniteConfig, is_torch_available
@@ -185,6 +186,14 @@ def setUp(self):
     def test_config(self):
         self.config_tester.run_common_tests()
 
+    def test_config_int_multiplier_roundtrip(self):
+        config = GraniteConfig(embedding_multiplier=12, logits_scaling=8)
+        with tempfile.TemporaryDirectory() as tmpdir:
+            config.save_pretrained(tmpdir)
+            loaded = GraniteConfig.from_pretrained(tmpdir)
+        self.assertEqual(loaded.embedding_multiplier, 12)
+        self.assertEqual(loaded.logits_scaling, 8)
+
     def test_model(self):
         config_and_inputs = self.model_tester.prepare_config_and_inputs()
         self.model_tester.create_and_check_model(*config_and_inputs)