Skip to content

Commit 79fa53b

Browse files
No public description
PiperOrigin-RevId: 943982059
1 parent b9aee47 commit 79fa53b

2 files changed

Lines changed: 106 additions & 4 deletions

File tree

src/maxtext/utils/model_creation_utils.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from flax import nnx
4242
from flax.core.meta import Partitioned
4343
import flax.linen as nn
44+
from huggingface_hub import get_token
4445
import jax
4546
import jax.numpy as jnp
4647
from jax.sharding import Mesh
@@ -811,8 +812,12 @@ def from_pretrained(
811812
if config.convert_checkpoint_if_possible and not config.load_parameters_path:
812813
if not (epath.Path(config.base_output_directory) / "0" / "items").exists():
813814
# Try to convert checkpoint on the fly
814-
if not config.hf_access_token:
815-
raise ValueError("hf_access_token must be provided when not providing a pre-existing checkpoint")
815+
hf_access_token = config.hf_access_token or get_token()
816+
if not hf_access_token:
817+
raise ValueError(
818+
"hf_access_token must be provided (or authenticate via"
819+
" huggingface-cli) when not providing a pre-existing checkpoint"
820+
)
816821

817822
# Only process 0 performs the conversion; other processes wait at the barrier below.
818823
# Otherwise every host would race to download from HF and concurrently write the same
@@ -830,8 +835,8 @@ def from_pretrained(
830835
conversion_env = os.environ.copy()
831836
conversion_env["JAX_PLATFORMS"] = "cpu"
832837
# conversion_env["XLA_FLAGS"] = f"--xla_force_host_platform_device_count={simulated_cpu_devices_count}"
833-
if config.hf_access_token:
834-
conversion_env["HF_TOKEN"] = config.hf_access_token
838+
if hf_access_token:
839+
conversion_env["HF_TOKEN"] = hf_access_token
835840

836841
to_maxtext_cmd = [
837842
sys.executable,

tests/unit/model_creation_utils_test.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,3 +834,100 @@ def test_returns_linen_train_state_and_annotations(self):
834834

835835
if __name__ == "__main__":
836836
unittest.main()
837+
838+
839+
class TestFromPretrainedAuth(unittest.TestCase):
840+
"""Tests for Hugging Face authentication in from_pretrained."""
841+
842+
def _make_nnx_metadata_mock(self):
843+
meta = MagicMock()
844+
meta.item_metadata.tree.keys.return_value = ["decoder"]
845+
meta.item_metadata.tree.get.return_value = {}
846+
return meta
847+
848+
@patch("maxtext.utils.model_creation_utils.ocp")
849+
@patch("maxtext.utils.model_creation_utils.subprocess.run")
850+
@patch("maxtext.utils.model_creation_utils.get_token")
851+
@patch("maxtext.utils.model_creation_utils.epath.Path")
852+
def test_auth_success_with_config_token(self, mock_path, mock_get_token, mock_run, mock_ocp):
853+
config = _make_config(
854+
convert_checkpoint_if_possible=True,
855+
base_output_directory="gs://fake_bucket/fake_run",
856+
hf_access_token="config_token",
857+
)
858+
mesh = _make_mesh(config)
859+
860+
mock_ckpt_path = MagicMock()
861+
mock_ckpt_path.exists.return_value = False
862+
mock_path.return_value.__truediv__.return_value.__truediv__.return_value = mock_ckpt_path
863+
864+
mock_ckptr = MagicMock()
865+
mock_ckptr.metadata.return_value = self._make_nnx_metadata_mock()
866+
mock_ckptr.restore.side_effect = lambda path, item=None, **kw: item
867+
mock_ocp.Checkpointer.return_value = mock_ckptr
868+
mock_ocp.checkpoint_utils.construct_restore_args.return_value = {}
869+
mock_ocp.ArrayRestoreArgs = ocp.ArrayRestoreArgs
870+
871+
model = model_creation_utils.from_pretrained(config, mesh)
872+
self.assertIsInstance(model, models.Transformer)
873+
874+
mock_run.assert_called_once()
875+
called_env = mock_run.call_args[1].get("env", {})
876+
self.assertEqual(called_env.get("HF_TOKEN"), "config_token")
877+
mock_get_token.assert_not_called()
878+
879+
@patch("maxtext.utils.model_creation_utils.ocp")
880+
@patch("maxtext.utils.model_creation_utils.subprocess.run")
881+
@patch("maxtext.utils.model_creation_utils.get_token")
882+
@patch("maxtext.utils.model_creation_utils.epath.Path")
883+
def test_auth_success_with_cached_token(self, mock_path, mock_get_token, mock_run, mock_ocp):
884+
config = _make_config(
885+
convert_checkpoint_if_possible=True,
886+
base_output_directory="gs://fake_bucket/fake_run",
887+
hf_access_token="",
888+
)
889+
mesh = _make_mesh(config)
890+
891+
mock_ckpt_path = MagicMock()
892+
mock_ckpt_path.exists.return_value = False
893+
mock_path.return_value.__truediv__.return_value.__truediv__.return_value = mock_ckpt_path
894+
895+
mock_get_token.return_value = "cached_token"
896+
897+
mock_ckptr = MagicMock()
898+
mock_ckptr.metadata.return_value = self._make_nnx_metadata_mock()
899+
mock_ckptr.restore.side_effect = lambda path, item=None, **kw: item
900+
mock_ocp.Checkpointer.return_value = mock_ckptr
901+
mock_ocp.checkpoint_utils.construct_restore_args.return_value = {}
902+
mock_ocp.ArrayRestoreArgs = ocp.ArrayRestoreArgs
903+
904+
model = model_creation_utils.from_pretrained(config, mesh)
905+
self.assertIsInstance(model, models.Transformer)
906+
907+
mock_get_token.assert_called_once()
908+
mock_run.assert_called_once()
909+
called_env = mock_run.call_args[1].get("env", {})
910+
self.assertEqual(called_env.get("HF_TOKEN"), "cached_token")
911+
912+
@patch("maxtext.utils.model_creation_utils.ocp")
913+
@patch("maxtext.utils.model_creation_utils.subprocess.run")
914+
@patch("maxtext.utils.model_creation_utils.get_token")
915+
@patch("maxtext.utils.model_creation_utils.epath.Path")
916+
def test_auth_failure_no_token(self, mock_path, mock_get_token, mock_run, mock_ocp):
917+
config = _make_config(
918+
convert_checkpoint_if_possible=True,
919+
base_output_directory="gs://fake_bucket/fake_run",
920+
hf_access_token="",
921+
)
922+
mesh = _make_mesh(config)
923+
924+
mock_ckpt_path = MagicMock()
925+
mock_ckpt_path.exists.return_value = False
926+
mock_path.return_value.__truediv__.return_value.__truediv__.return_value = mock_ckpt_path
927+
928+
mock_get_token.return_value = None
929+
930+
with self.assertRaisesRegex(ValueError, "hf_access_token must be provided"):
931+
model_creation_utils.from_pretrained(config, mesh)
932+
933+
mock_run.assert_not_called()

0 commit comments

Comments
 (0)