@@ -1604,3 +1604,95 @@ def test_returns_none_when_enum_empty_list(self, mock_spec):
16041604 def test_returns_none_on_exception (self , mock_spec ):
16051605 mock_spec .side_effect = RuntimeError ("hub content unavailable" )
16061606 assert self ._call () is None
1607+
1608+
1609+ class TestListHyperparameters :
1610+ """Tests for the list_hyperparameters public API."""
1611+
1612+ @patch ('sagemaker.train.common_utils.finetune_utils._get_hub_content_metadata' )
1613+ @patch ('boto3.client' )
1614+ def test_list_hyperparameters_returns_finetuning_options (self , mock_boto_client , mock_get_hub_content ):
1615+ """list_hyperparameters returns a FineTuningOptions object with correct params."""
1616+ from sagemaker .train .common_utils .finetune_utils import list_hyperparameters
1617+ from sagemaker .train .common import FineTuningOptions
1618+
1619+ mock_get_hub_content .return_value = {
1620+ 'hub_content_arn' : "arn:aws:sagemaker:us-west-2:123456789012:model/test-model" ,
1621+ 'hub_content_document' : {
1622+ "GatedBucket" : False ,
1623+ "RecipeCollection" : [
1624+ {
1625+ "CustomizationTechnique" : "SFT" ,
1626+ "SmtjRecipeTemplateS3Uri" : "s3://bucket/template.json" ,
1627+ "SmtjOverrideParamsS3Uri" : "s3://bucket/params.json" ,
1628+ "Peft" : "LORA"
1629+ }
1630+ ]
1631+ }
1632+ }
1633+
1634+ mock_s3_client = Mock ()
1635+ mock_boto_client .return_value = mock_s3_client
1636+ mock_s3_client .get_object .return_value = {
1637+ "Body" : Mock (read = Mock (return_value = json .dumps ({
1638+ "learning_rate" : {"type" : "float" , "default" : 0.0001 , "min" : 5e-7 , "max" : 0.001 , "required" : True },
1639+ "global_batch_size" : {"type" : "integer" , "default" : 8 , "required" : True },
1640+ "max_epochs" : {"type" : "integer" , "default" : 5 , "min" : 1 , "max" : 100 , "required" : True },
1641+ }).encode ()))
1642+ }
1643+
1644+ mock_session = Mock ()
1645+ mock_session .boto_session .region_name = "us-west-2"
1646+ mock_session .boto_session .client .return_value = mock_s3_client
1647+
1648+ with patch ('sagemaker.train.common_utils.finetune_utils.TrainDefaults.get_sagemaker_session' , return_value = mock_session ):
1649+ result = list_hyperparameters ("test-model" , "SFT" , "LORA" , sagemaker_session = mock_session )
1650+
1651+ assert isinstance (result , FineTuningOptions )
1652+ assert result .learning_rate == 0.0001
1653+ assert result .global_batch_size == 8
1654+ assert result .max_epochs == 5
1655+
1656+ @patch ('sagemaker.train.common_utils.finetune_utils._get_hub_content_metadata' )
1657+ @patch ('boto3.client' )
1658+ def test_list_hyperparameters_accepts_enum_values (self , mock_boto_client , mock_get_hub_content ):
1659+ """list_hyperparameters accepts both string and enum values for technique/training_type."""
1660+ from sagemaker .train .common_utils .finetune_utils import list_hyperparameters
1661+ from sagemaker .train .common import CustomizationTechnique , TrainingType
1662+
1663+ mock_get_hub_content .return_value = {
1664+ 'hub_content_arn' : "arn:aws:sagemaker:us-west-2:123456789012:model/test-model" ,
1665+ 'hub_content_document' : {
1666+ "GatedBucket" : False ,
1667+ "RecipeCollection" : [
1668+ {
1669+ "CustomizationTechnique" : "DPO" ,
1670+ "SmtjRecipeTemplateS3Uri" : "s3://bucket/template.json" ,
1671+ "SmtjOverrideParamsS3Uri" : "s3://bucket/params.json" ,
1672+ "Peft" : "LORA"
1673+ }
1674+ ]
1675+ }
1676+ }
1677+
1678+ mock_s3_client = Mock ()
1679+ mock_boto_client .return_value = mock_s3_client
1680+ mock_s3_client .get_object .return_value = {
1681+ "Body" : Mock (read = Mock (return_value = json .dumps ({
1682+ "learning_rate" : {"type" : "float" , "default" : 0.0001 , "required" : True },
1683+ }).encode ()))
1684+ }
1685+
1686+ mock_session = Mock ()
1687+ mock_session .boto_session .region_name = "us-west-2"
1688+ mock_session .boto_session .client .return_value = mock_s3_client
1689+
1690+ with patch ('sagemaker.train.common_utils.finetune_utils.TrainDefaults.get_sagemaker_session' , return_value = mock_session ):
1691+ result = list_hyperparameters (
1692+ "test-model" ,
1693+ CustomizationTechnique .DPO ,
1694+ TrainingType .LORA ,
1695+ sagemaker_session = mock_session ,
1696+ )
1697+
1698+ assert result .learning_rate == 0.0001
0 commit comments