diff --git a/sagemaker-core/src/sagemaker/core/clarify/__init__.py b/sagemaker-core/src/sagemaker/core/clarify/__init__.py index 84d2cb3a8d..0f26c3aea6 100644 --- a/sagemaker-core/src/sagemaker/core/clarify/__init__.py +++ b/sagemaker-core/src/sagemaker/core/clarify/__init__.py @@ -379,12 +379,13 @@ "image/jpeg", "image/png", "application/x-npy", + "application/x-parquet", ), ), SchemaOptional("accept_type"): And( str, Use(str.lower), - lambda s: s in ("text/csv", "application/jsonlines", "application/json"), + lambda s: s in ("text/csv", "application/jsonlines", "application/json", "application/x-parquet"), ), SchemaOptional("label"): Or(str, int), SchemaOptional("probability"): Or(str, int), @@ -1020,11 +1021,13 @@ def __init__( Must be set with ``instance_count``, ``model_name`` accept_type (str): The model output format to be used for getting inferences with the shadow endpoint. Valid values are ``"text/csv"`` for CSV, - ``"application/jsonlines"`` for JSON Lines, and ``"application/json"`` for JSON. + ``"application/jsonlines"`` for JSON Lines, ``"application/json"`` for JSON, and + ``"application/x-parquet"`` for Parquet. Default is the same as ``content_type``. content_type (str): The model input format to be used for getting inferences with the shadow endpoint. Valid values are ``"text/csv"`` for CSV, - ``"application/jsonlines"`` for JSON Lines, and ``"application/json"`` for JSON. + ``"application/jsonlines"`` for JSON Lines, ``"application/json"`` for JSON, and + ``"application/x-parquet"`` for Parquet. Default is the same as ``dataset_format``. content_template (str): A template string to be used to construct the model input from dataset instances. It is only used, and required, when ``model_content_type`` is @@ -1160,10 +1163,10 @@ def __init__( ) self.predictor_config["endpoint_name_prefix"] = endpoint_name_prefix if accept_type is not None: - if accept_type not in ["text/csv", "application/jsonlines", "application/json"]: + if accept_type not in ["text/csv", "application/jsonlines", "application/json", "application/x-parquet"]: raise ValueError( f"Invalid accept_type {accept_type}." - f" Please choose text/csv or application/jsonlines." + f" Please choose text/csv, application/jsonlines, application/json, or application/x-parquet." ) if time_series_model_config and accept_type == "text/csv": raise ValueError( @@ -1179,10 +1182,11 @@ def __init__( "image/jpg", "image/png", "application/x-npy", + "application/x-parquet", ]: raise ValueError( f"Invalid content_type {content_type}." - f" Please choose text/csv or application/jsonlines." + f" Please choose a valid content_type." ) if content_type == "application/jsonlines": if content_template is None: diff --git a/sagemaker-core/src/sagemaker/core/transformer.py b/sagemaker-core/src/sagemaker/core/transformer.py index 93a35dc075..1918df9d95 100644 --- a/sagemaker-core/src/sagemaker/core/transformer.py +++ b/sagemaker-core/src/sagemaker/core/transformer.py @@ -409,6 +409,9 @@ def submit(request): from sagemaker.core.utils.code_injection.codec import transform as transform_util transformed = transform_util(serialized_request, "CreateTransformJobRequest") + # TransformJob does not accept 'tags'/'Tags', so we must pop them to avoid pydantic ValidationError + transformed.pop("tags", None) + transformed.pop("Tags", None) self.latest_transform_job = TransformJob(**transformed) if wait: @@ -714,7 +717,16 @@ def _get_transform_request( transform_request["Environment"] = env if tags is not None: - transform_request["Tags"] = tags + from sagemaker.core.common_utils import format_tags + formatted_tags = format_tags(tags) + + if isinstance(formatted_tags, list): + formatted_tags = [ + {"Key": t.get("Key", t.get("key", "")), "Value": t.get("Value", t.get("value", ""))} + if isinstance(t, dict) else t + for t in formatted_tags + ] + transform_request["Tags"] = formatted_tags if data_processing is not None: transform_request["DataProcessing"] = data_processing