Skip to content

Commit f9ac7c5

Browse files
authored
Merge branch 'master' into pt-2.3-fix
2 parents 7169a2d + 58bdbd0 commit f9ac7c5

File tree

9 files changed

+180
-37
lines changed

9 files changed

+180
-37
lines changed

src/sagemaker/estimator.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
from sagemaker.interactive_apps import SupportedInteractiveAppTypes
6969
from sagemaker.interactive_apps.tensorboard import TensorBoardApp
7070
from sagemaker.instance_group import InstanceGroup
71+
from sagemaker.model_card.model_card import ModelCard, TrainingDetails
7172
from sagemaker.utils import instance_supports_kms
7273
from sagemaker.job import _Job
7374
from sagemaker.jumpstart.utils import (
@@ -1797,8 +1798,17 @@ def register(
17971798
else:
17981799
if "model_kms_key" not in kwargs:
17991800
kwargs["model_kms_key"] = self.output_kms_key
1800-
model = self.create_model(image_uri=image_uri, **kwargs)
1801+
model = self.create_model(image_uri=image_uri, name=model_name, **kwargs)
18011802
model.name = model_name
1803+
if self.model_data is not None and model_card is None:
1804+
training_details = TrainingDetails.from_model_s3_artifacts(
1805+
model_artifacts=[self.model_data], sagemaker_session=self.sagemaker_session
1806+
)
1807+
model_card = ModelCard(
1808+
name="estimator_card",
1809+
training_details=training_details,
1810+
sagemaker_session=self.sagemaker_session,
1811+
)
18021812
return model.register(
18031813
content_types,
18041814
response_types,

src/sagemaker/image_uri_config/huggingface-llm.json

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"1.2": "1.2.0",
1313
"1.3": "1.3.3",
1414
"1.4": "1.4.5",
15-
"2.0": "2.0.2"
15+
"2.0": "2.2.0"
1616
},
1717
"versions": {
1818
"0.6.0": {
@@ -672,6 +672,53 @@
672672
"container_version": {
673673
"gpu": "cu121-ubuntu22.04"
674674
}
675+
},
676+
"2.2.0": {
677+
"py_versions": [
678+
"py310"
679+
],
680+
"registries": {
681+
"af-south-1": "626614931356",
682+
"il-central-1": "780543022126",
683+
"ap-east-1": "871362719292",
684+
"ap-northeast-1": "763104351884",
685+
"ap-northeast-2": "763104351884",
686+
"ap-northeast-3": "364406365360",
687+
"ap-south-1": "763104351884",
688+
"ap-south-2": "772153158452",
689+
"ap-southeast-1": "763104351884",
690+
"ap-southeast-2": "763104351884",
691+
"ap-southeast-3": "907027046896",
692+
"ap-southeast-4": "457447274322",
693+
"ca-central-1": "763104351884",
694+
"cn-north-1": "727897471807",
695+
"cn-northwest-1": "727897471807",
696+
"eu-central-1": "763104351884",
697+
"eu-central-2": "380420809688",
698+
"eu-north-1": "763104351884",
699+
"eu-west-1": "763104351884",
700+
"eu-west-2": "763104351884",
701+
"eu-west-3": "763104351884",
702+
"eu-south-1": "692866216735",
703+
"eu-south-2": "503227376785",
704+
"me-south-1": "217643126080",
705+
"me-central-1": "914824155844",
706+
"sa-east-1": "763104351884",
707+
"us-east-1": "763104351884",
708+
"us-east-2": "763104351884",
709+
"us-gov-east-1": "446045086412",
710+
"us-gov-west-1": "442386744353",
711+
"us-iso-east-1": "886529160074",
712+
"us-isob-east-1": "094389454867",
713+
"us-west-1": "763104351884",
714+
"us-west-2": "763104351884",
715+
"ca-west-1": "204538143572"
716+
},
717+
"tag_prefix": "2.3.0-tgi2.2.0",
718+
"repository": "huggingface-pytorch-tgi-inference",
719+
"container_version": {
720+
"gpu": "cu121-ubuntu22.04-v2.0"
721+
}
675722
}
676723
}
677724
}

src/sagemaker/jumpstart/hub/hub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def list_sagemaker_public_hub_models(
233233
f"arn:{info.partition}:"
234234
f"sagemaker:{info.region}:"
235235
f"aws:hub-content/{info.hub_name}/"
236-
f"{HubContentType.MODEL}/{model[0]}"
236+
f"{HubContentType.MODEL.value}/{model[0]}"
237237
)
238238
hub_content_summary = {
239239
"hub_content_name": model[0],

src/sagemaker/model.py

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,10 @@ def register(
549549
model_package_group_name = utils.base_name_from_image(
550550
self.image_uri, default_base_name=ModelPackage.__name__
551551
)
552-
if model_package_group_name is not None:
552+
if (
553+
model_package_group_name is not None
554+
and model_type is not JumpStartModelType.PROPRIETARY
555+
):
553556
container_def = self.prepare_container_def(accept_eula=accept_eula)
554557
container_def = update_container_with_inference_params(
555558
framework=framework,
@@ -2466,32 +2469,55 @@ def update_model_card(self, model_card: Union[ModelCard, ModelPackageModelCard])
24662469
desc_model_package = sagemaker_session.sagemaker_client.describe_model_package(
24672470
ModelPackageName=self.model_package_arn
24682471
)
2472+
if hasattr(model_card, "model_package_details"):
2473+
model_card.model_package_details = None
24692474
update_model_card_req = model_card._create_request_args()
2470-
if update_model_card_req["ModelCardStatus"] is not None:
2471-
if (
2472-
desc_model_package["ModelCard"]["ModelCardStatus"]
2473-
== update_model_card_req["ModelCardStatus"]
2474-
):
2475-
del update_model_card_req["ModelCardStatus"]
2476-
24772475
if update_model_card_req.get("ModelCardName") is not None:
24782476
del update_model_card_req["ModelCardName"]
2479-
if update_model_card_req.get("Content") is not None:
2480-
previous_content_hash = _hash_content_str(
2481-
desc_model_package["ModelCard"]["ModelCardContent"]
2482-
)
2483-
current_content_hash = _hash_content_str(update_model_card_req["Content"])
2484-
if (
2485-
previous_content_hash == current_content_hash
2486-
or update_model_card_req.get("Content") == "{}"
2487-
or update_model_card_req.get("Content") == "null"
2488-
):
2489-
del update_model_card_req["Content"]
2490-
else:
2491-
update_model_card_req["ModelCardContent"] = update_model_card_req["Content"]
2492-
del update_model_card_req["Content"]
2493-
update_model_package_args = {
2494-
"ModelPackageArn": self.model_package_arn,
2495-
"ModelCard": update_model_card_req,
2496-
}
2497-
sagemaker_session.sagemaker_client.update_model_package(**update_model_package_args)
2477+
if update_model_card_req["Content"] is not None:
2478+
if "model_package_details" in update_model_card_req["Content"]:
2479+
update_model_card_req["Content"].pop("model_package_details", None)
2480+
update_model_card_req["ModelCardContent"] = update_model_card_req["Content"]
2481+
del update_model_card_req["Content"]
2482+
2483+
if "ModelCard" in desc_model_package:
2484+
if update_model_card_req["ModelCardStatus"] is not None:
2485+
if (
2486+
desc_model_package["ModelCard"]["ModelCardStatus"]
2487+
!= update_model_card_req["ModelCardStatus"]
2488+
):
2489+
new_mc_mp_req = update_model_card_req
2490+
del new_mc_mp_req["ModelCardContent"]
2491+
update_model_package_args = {
2492+
"ModelPackageArn": self.model_package_arn,
2493+
"ModelCard": new_mc_mp_req,
2494+
}
2495+
sagemaker_session.sagemaker_client.update_model_package(
2496+
**update_model_package_args
2497+
)
2498+
2499+
if update_model_card_req.get("ModelCardContent") is not None:
2500+
previous_content_hash = _hash_content_str(
2501+
desc_model_package["ModelCard"]["ModelCardContent"]
2502+
)
2503+
current_content_hash = _hash_content_str(update_model_card_req["ModelCardContent"])
2504+
if not (
2505+
previous_content_hash == current_content_hash
2506+
or update_model_card_req.get("ModelCardContent") == "{}"
2507+
or update_model_card_req.get("ModelCardContent") == "null"
2508+
):
2509+
new_mc_mp_req = update_model_card_req
2510+
del new_mc_mp_req["ModelCardStatus"]
2511+
update_model_package_args = {
2512+
"ModelPackageArn": self.model_package_arn,
2513+
"ModelCard": new_mc_mp_req,
2514+
}
2515+
sagemaker_session.sagemaker_client.update_model_package(
2516+
**update_model_package_args
2517+
)
2518+
else:
2519+
update_model_package_args = {
2520+
"ModelPackageArn": self.model_package_arn,
2521+
"ModelCard": update_model_card_req,
2522+
}
2523+
sagemaker_session.sagemaker_client.update_model_package(**update_model_package_args)

tests/integ/test_byo_estimator.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,20 @@
1212
# language governing permissions and limitations under the License.
1313
from __future__ import absolute_import
1414

15+
import io
1516
import json
1617
import os
1718

19+
import numpy as np
20+
1821
import pytest
22+
import sagemaker.amazon.common as smac
23+
1924

2025
import sagemaker
2126
from sagemaker import image_uris
2227
from sagemaker.estimator import Estimator
28+
from sagemaker.s3 import S3Uploader
2329
from sagemaker.serializers import SimpleBaseSerializer
2430
from sagemaker.utils import unique_name_from_base
2531
from tests.integ import DATA_DIR, TRAINING_DEFAULT_TIMEOUT_MINUTES, datasets
@@ -102,6 +108,60 @@ def test_byo_estimator(sagemaker_session, region, cpu_instance_type, training_se
102108
assert prediction["score"] is not None
103109

104110

111+
@pytest.mark.release
112+
def test_estimator_register_publish_training_details(sagemaker_session, region):
113+
114+
bucket = sagemaker_session.default_bucket()
115+
prefix = "model-card-sample-notebook"
116+
117+
raw_data = (
118+
(0.5, 0),
119+
(0.75, 0),
120+
(1.0, 0),
121+
(1.25, 0),
122+
(1.50, 0),
123+
(1.75, 0),
124+
(2.0, 0),
125+
(2.25, 1),
126+
(2.5, 0),
127+
(2.75, 1),
128+
(3.0, 0),
129+
(3.25, 1),
130+
(3.5, 0),
131+
(4.0, 1),
132+
(4.25, 1),
133+
(4.5, 1),
134+
(4.75, 1),
135+
(5.0, 1),
136+
(5.5, 1),
137+
)
138+
training_data = np.array(raw_data).astype("float32")
139+
labels = training_data[:, 1]
140+
141+
# upload data to S3 bucket
142+
buf = io.BytesIO()
143+
smac.write_numpy_to_dense_tensor(buf, training_data, labels)
144+
buf.seek(0)
145+
s3_train_data = f"s3://{bucket}/{prefix}/train"
146+
S3Uploader.upload_bytes(b=buf, s3_uri=s3_train_data, sagemaker_session=sagemaker_session)
147+
output_location = f"s3://{bucket}/{prefix}/output"
148+
container = image_uris.retrieve("linear-learner", region)
149+
estimator = Estimator(
150+
container,
151+
role="SageMakerRole",
152+
instance_count=1,
153+
instance_type="ml.m4.xlarge",
154+
output_path=output_location,
155+
sagemaker_session=sagemaker_session,
156+
)
157+
estimator.set_hyperparameters(
158+
feature_dim=2, mini_batch_size=10, predictor_type="binary_classifier"
159+
)
160+
estimator.fit({"train": s3_train_data})
161+
print(f"Training job name: {estimator.latest_training_job.name}")
162+
estimator.register()
163+
164+
105165
def test_async_byo_estimator(sagemaker_session, region, cpu_instance_type, training_set):
106166
image_uri = image_uris.retrieve("factorization-machines", region)
107167
endpoint_name = unique_name_from_base("byo")

tests/integ/test_sklearn.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,6 @@ def test_deploy_model(
159159
def test_deploy_model_with_serverless_inference_config(
160160
sklearn_training_job,
161161
sagemaker_session,
162-
sklearn_latest_version,
163-
sklearn_latest_py_version,
164162
):
165163
endpoint_name = unique_name_from_base("test-sklearn-deploy-model-serverless")
166164
with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
@@ -173,7 +171,7 @@ def test_deploy_model_with_serverless_inference_config(
173171
model_data,
174172
ROLE,
175173
entry_point=script_path,
176-
framework_version=sklearn_latest_version,
174+
framework_version="1.0-1",
177175
sagemaker_session=sagemaker_session,
178176
)
179177
predictor = model.deploy(

tests/integ/test_xgboost.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,9 @@ def test_training_with_network_isolation(
121121
]
122122

123123

124-
@pytest.mark.skip(reason="re:Invent keynote3 blocker. Revisit after release")
125124
def test_xgboost_serverless_inference(
126125
xgboost_training_job,
127126
sagemaker_session,
128-
xgboost_latest_version,
129127
):
130128
endpoint_name = unique_name_from_base("test-xgboost-deploy-model-serverless")
131129
with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
@@ -139,7 +137,7 @@ def test_xgboost_serverless_inference(
139137
model_data=model_data,
140138
role=ROLE,
141139
entry_point=os.path.join(DATA_DIR, "xgboost_abalone", "abalone.py"),
142-
framework_version=xgboost_latest_version,
140+
framework_version="1.5-1",
143141
)
144142

145143
xgboost.deploy(

tests/unit/sagemaker/image_uris/test_huggingface_llm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"2.0.0": "2.1.1-tgi2.0.0-gpu-py310-cu121-ubuntu22.04",
4343
"2.0.1": "2.1.1-tgi2.0.1-gpu-py310-cu121-ubuntu22.04",
4444
"2.0.2": "2.3.0-tgi2.0.2-gpu-py310-cu121-ubuntu22.04",
45+
"2.2.0": "2.3.0-tgi2.2.0-gpu-py310-cu121-ubuntu22.04-v2.0",
4546
},
4647
"inf2": {
4748
"0.0.16": "1.13.1-optimum0.0.16-neuronx-py310-ubuntu22.04",

tests/unit/test_estimator.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4402,7 +4402,7 @@ def test_register_default_image_without_instance_type_args(sagemaker_session):
44024402
framework = "TENSORFLOW"
44034403
framework_version = "2.9"
44044404
nearest_model_name = "resnet50"
4405-
4405+
model_card = {"ModelCardStatus": ModelCardStatusEnum.DRAFT, "ModelCardContent": "{}"}
44064406
estimator.register(
44074407
content_types=content_types,
44084408
response_types=response_types,
@@ -4425,6 +4425,7 @@ def test_register_default_image_without_instance_type_args(sagemaker_session):
44254425
"marketplace_cert": False,
44264426
"sample_payload_url": sample_payload_url,
44274427
"task": task,
4428+
"model_card": model_card,
44284429
}
44294430
sagemaker_session.create_model_package_from_containers.assert_called_with(
44304431
**expected_create_model_package_request
@@ -4454,6 +4455,7 @@ def test_register_inference_image(sagemaker_session):
44544455
framework = "TENSORFLOW"
44554456
framework_version = "2.9"
44564457
nearest_model_name = "resnet50"
4458+
model_card = {"ModelCardStatus": ModelCardStatusEnum.DRAFT, "ModelCardContent": "{}"}
44574459

44584460
estimator.register(
44594461
content_types=content_types,
@@ -4480,6 +4482,7 @@ def test_register_inference_image(sagemaker_session):
44804482
"marketplace_cert": False,
44814483
"sample_payload_url": sample_payload_url,
44824484
"task": task,
4485+
"model_card": model_card,
44834486
}
44844487
sagemaker_session.create_model_package_from_containers.assert_called_with(
44854488
**expected_create_model_package_request

0 commit comments

Comments
 (0)