diff --git a/.gitignore b/.gitignore index 09935a1dc9..1ac75202b2 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,9 @@ scratch/ *.egg examples/tensorflow/distributed_mnist/data *.iml + +# Sphinx documentation +docs/_build/ doc/_build doc/_static doc/_templates diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000000..41a568b194 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.10" + +sphinx: + configuration: docs/conf.py + +formats: + - pdf + - epub + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . + extra_requirements: + - docs \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000..fe8e88c6e1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,12 @@ +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 0000000000..f618f6c891 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,174 @@ +/* What's New Section Styling */ +.whats-new-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 20px; + margin: 30px 0; +} + +.new-feature-card { + background: var(--pst-color-surface); + border: 1px solid var(--pst-color-border); + border-radius: 12px; + padding: 25px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + transition: transform 0.2s ease, box-shadow 0.2s ease; + position: relative; + overflow: hidden; + color: var(--pst-color-text-base); +} + +[data-theme="dark"] .new-feature-card { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +.new-feature-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); +} + +[data-theme="dark"] .new-feature-card:hover { + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4); +} + +.new-feature-card h3 { + margin-top: 0; + margin-bottom: 15px; + font-size: 1.3em; + font-weight: 600; + color: inherit; +} + +.new-feature-card ul { + margin: 15px 0; + padding-left: 20px; +} + +.new-feature-card li { + margin-bottom: 8px; + line-height: 1.5; +} + +/* Feedback Component */ +.feedback-container { + border-top: 1px solid var(--pst-color-border); + margin-top: 40px; + padding: 24px; + background-color: var(--pst-color-surface); + border-radius: 8px; + border: 1px solid var(--pst-color-border); +} + +.feedback-question { + font-size: 20px; + font-weight: 500; + color: var(--pst-color-text-base); + margin-bottom: 20px; + text-align: left; +} + +.feedback-buttons { + display: flex; + justify-content: flex-start; + gap: 12px; +} + +.feedback-btn { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + border: 1px solid var(--pst-color-border); + border-radius: 6px; + background: var(--pst-color-surface); + color: var(--pst-color-text-muted); + font-size: 14px; + cursor: pointer; + transition: all 0.2s ease; +} + +.feedback-btn:hover { + border-color: var(--pst-color-primary); + background: var(--pst-color-surface); +} + +.feedback-btn.selected { + border-color: var(--pst-color-primary); + background: var(--pst-color-primary-bg); + color: var(--pst-color-primary); +} + +.feedback-btn svg { + width: 16px; + height: 16px; +} + +.feedback-thanks { + display: none; + color: #059669; + font-size: 14px; + text-align: center; + margin-top: 16px; +} + +/* Feedback Options */ +.feedback-options { + display: none; + margin-top: 20px; +} + +.feedback-more { + display: flex; + flex-direction: column; + gap: 12px; +} + +.feedback-github-link { + color: #0366d6; + text-decoration: none; + font-size: 14px; + padding: 10px 20px; + border: 1px solid #0366d6; + border-radius: 6px; + transition: all 0.2s; + font-weight: 500; + align-self: flex-start; +} + +.feedback-github-link:hover { + background-color: #0366d6; + color: white; + text-decoration: none; +} + +header { + background-color: white; + + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + position: sticky; + top: 0; + z-index: 50; +} + +h1 { + font-size: 1.875rem; + font-weight: 700; + color: var(--pst-color-text-base); +} + +h2 { + font-size: 1.5rem; + font-weight: 700; + color: var(--pst-color-text-base); +} + +h3 { + font-size: 1.25rem; + font-weight: 500; + color: var(--pst-color-text-base); +} + +p { + font-size: 1.0rem; + color: var(--pst-color-text-base); +} diff --git a/docs/_static/feedback.js b/docs/_static/feedback.js new file mode 100644 index 0000000000..a0e9874aa0 --- /dev/null +++ b/docs/_static/feedback.js @@ -0,0 +1,71 @@ +// Feedback functionality +document.addEventListener('DOMContentLoaded', function() { + // Add feedback component to the very bottom of each page + const article = document.querySelector('article[role="main"]') || document.querySelector('.bd-article') || document.querySelector('main'); + if (article) { + const feedbackHTML = ` +
Revolutionary foundation model fine-tuning with specialized trainers:
+Advanced techniques like LoRA, preference optimization, and RLHF that simply don't exist in V2.
+Separate PyPI packages for specialized capabilities:
+Single classes replace multiple framework-specific implementations:
+[11/18/25 06:56:43] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1364\n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/18/25 06:56:43]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Found credentials in shared credentials file: ~\u001b[38;2;225;0;225m/.aws/\u001b[0m\u001b[38;2;225;0;225mcredentials\u001b[0m \u001b]8;id=890998;file:///Volumes/workplace/sagemaker-python-sdk-staging/mlops-venv/lib/python3.12/site-packages/botocore/credentials.py\u001b\\\u001b[2mcredentials.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=155466;file:///Volumes/workplace/sagemaker-python-sdk-staging/mlops-venv/lib/python3.12/site-packages/botocore/credentials.py#1364\u001b\\\u001b[2m1364\u001b[0m\u001b]8;;\u001b\\\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sagemaker.config INFO - Not applying SDK defaults from location: /Library/Application Support/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /Users/zeidmo/Library/Application Support/sagemaker/config.yaml\n" - ] - } - ], + "source": [ + "# Data Preprocessing with Scikit-learn Processing Job\n", + "\n", + "Run a Scikit-learn processing job to preprocess the Abalone dataset into train, validation, and test splits." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7181fa90", + "metadata": {}, + "outputs": [], "source": [ "from sagemaker.core.processing import (\n", " ScriptProcessor,\n", @@ -54,24 +34,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3942b640", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[11/18/25 06:56:45] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1364\n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/18/25 06:56:45]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Found credentials in shared credentials file: ~\u001b[38;2;225;0;225m/.aws/\u001b[0m\u001b[38;2;225;0;225mcredentials\u001b[0m \u001b]8;id=320044;file:///Volumes/workplace/sagemaker-python-sdk-staging/mlops-venv/lib/python3.12/site-packages/botocore/credentials.py\u001b\\\u001b[2mcredentials.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=76749;file:///Volumes/workplace/sagemaker-python-sdk-staging/mlops-venv/lib/python3.12/site-packages/botocore/credentials.py#1364\u001b\\\u001b[2m1364\u001b[0m\u001b]8;;\u001b\\\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "\n", "sagemaker_session = Session()\n", @@ -114,7 +80,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "7e14a586", "metadata": {}, "outputs": [], @@ -124,18 +90,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "8ae3ecaa", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting code/preprocess.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile code/preprocess.py\n", "\n", @@ -266,26 +224,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "d414442a", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[11/18/25 06:58:25] INFO Creating processing-job with name processing.py:598\n", - " v3-job-1110-sklearn-preprocess-job-2025-11-18-14-58-25-375 \n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/18/25 06:58:25]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Creating processing-job with name \u001b]8;id=362812;file:///Volumes/workplace/sagemaker-python-sdk-staging/sagemaker-core/src/sagemaker/core/processing.py\u001b\\\u001b[2mprocessing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=120987;file:///Volumes/workplace/sagemaker-python-sdk-staging/sagemaker-core/src/sagemaker/core/processing.py#598\u001b\\\u001b[2m598\u001b[0m\u001b]8;;\u001b\\\n", - "\u001b[2;36m \u001b[0m v3-job-\u001b[1;36m1110\u001b[0m-sklearn-preprocess-job-\u001b[1;36m2025\u001b[0m-11-18-14-58-25-375 \u001b[2m \u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Process the training data step using a python script.\n", "# Split the training data set into train, test, and validation datasets\n", @@ -353,33 +295,14 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "f8b6425d", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'InProgress'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "sklearn_processor.latest_job.refresh()\n", "sklearn_processor.latest_job.processing_job_status" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b6c621dc", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/v3-examples/ml-ops-examples/v3-sagemaker-clarify.ipynb b/v3-examples/ml-ops-examples/v3-sagemaker-clarify.ipynb index 6feca5fb5c..d0f8eddaf2 100644 --- a/v3-examples/ml-ops-examples/v3-sagemaker-clarify.ipynb +++ b/v3-examples/ml-ops-examples/v3-sagemaker-clarify.ipynb @@ -11,23 +11,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[11/08/25 18:39:19] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1364\n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/08/25 18:39:19]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Found credentials in shared credentials file: ~\u001b[38;2;225;0;225m/.aws/\u001b[0m\u001b[38;2;225;0;225mcredentials\u001b[0m \u001b]8;id=479005;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/botocore/credentials.py\u001b\\\u001b[2mcredentials.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=274417;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/botocore/credentials.py#1364\u001b\\\u001b[2m1364\u001b[0m\u001b]8;;\u001b\\\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import sys\n", "import pandas as pd\n", @@ -61,25 +47,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Dataset shape: (1000, 12)\n", - "Target distribution: target\n", - "1 503\n", - "0 497\n", - "Name: count, dtype: int64\n", - "Gender distribution: gender\n", - "0.0 598\n", - "1.0 402\n", - "Name: count, dtype: int64\n" - ] - } - ], + "outputs": [], "source": [ "# Create synthetic dataset\n", "X, y = make_classification(\n", @@ -113,17 +83,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model accuracy: 0.920\n" - ] - } - ], + "outputs": [], "source": [ "# Split data\n", "X_train, X_test, y_train, y_test = train_test_split(\n", @@ -146,44 +108,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[11/08/25 18:39:30] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1364\n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/08/25 18:39:30]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Found credentials in shared credentials file: ~\u001b[38;2;225;0;225m/.aws/\u001b[0m\u001b[38;2;225;0;225mcredentials\u001b[0m \u001b]8;id=514072;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/botocore/credentials.py\u001b\\\u001b[2mcredentials.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=337498;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/botocore/credentials.py#1364\u001b\\\u001b[2m1364\u001b[0m\u001b]8;;\u001b\\\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
[11/08/25 18:39:31] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1364\n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/08/25 18:39:31]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Found credentials in shared credentials file: ~\u001b[38;2;225;0;225m/.aws/\u001b[0m\u001b[38;2;225;0;225mcredentials\u001b[0m \u001b]8;id=820880;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/botocore/credentials.py\u001b\\\u001b[2mcredentials.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=366626;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/botocore/credentials.py#1364\u001b\\\u001b[2m1364\u001b[0m\u001b]8;;\u001b\\\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Data uploaded to: s3://sagemaker-us-west-2-529088288990/clarify-test/data/test_data.csv\n", - "Output will be saved to: s3://sagemaker-us-west-2-529088288990/clarify-test/output\n" - ] - } - ], + "outputs": [], "source": [ "# Setup S3 paths\n", "session = Session()\n", @@ -219,17 +146,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Configurations created successfully\n" - ] - } - ], + "outputs": [], "source": [ "# Data configuration\n", "data_config = DataConfig(\n", @@ -266,30 +185,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[11/08/25 18:39:35] INFO Ignoring unnecessary instance type: None. image_uris.py:529\n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/08/25 18:39:35]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Ignoring unnecessary instance type: \u001b[3;38;2;225;0;225mNone\u001b[0m. \u001b]8;id=687743;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/sagemaker/utils/image_uris.py\u001b\\\u001b[2mimage_uris.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=190982;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/sagemaker/utils/image_uris.py#529\u001b\\\u001b[2m529\u001b[0m\u001b]8;;\u001b\\\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Clarify processor created with role: arn:aws:iam::529088288990:role/Admin\n" - ] - } - ], + "outputs": [], "source": [ "# Create Clarify processor\n", "clarify_processor = SageMakerClarifyProcessor(\n", @@ -311,57 +209,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[11/08/25 18:39:36] INFO Analysis Config: {'dataset_type': 'text/csv', 'headers': ['feature_0', clarify.py:1992\n", - " 'feature_1', 'feature_2', 'feature_3', 'feature_4', 'feature_5', \n", - " 'feature_6', 'feature_7', 'feature_8', 'feature_9', 'gender', \n", - " 'target'], 'label': 'target', 'label_values_or_threshold': [1], \n", - " 'facet': [{'name_or_index': 'gender', 'value_or_threshold': [1]}], \n", - " 'methods': {'report': {'name': 'report', 'title': 'Analysis Report'}, \n", - " 'pre_training_bias': {'methods': ['CI', 'DPL']}}} \n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m[11/08/25 18:39:36]\u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Analysis Config: \u001b[1m{\u001b[0m\u001b[38;2;0;135;0m'dataset_type'\u001b[0m: \u001b[38;2;0;135;0m'text/csv'\u001b[0m, \u001b[38;2;0;135;0m'headers'\u001b[0m: \u001b[1m[\u001b[0m\u001b[38;2;0;135;0m'feature_0'\u001b[0m, \u001b]8;id=70589;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/sagemaker/utils/clarify.py\u001b\\\u001b[2mclarify.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=487060;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/sagemaker/utils/clarify.py#1992\u001b\\\u001b[2m1992\u001b[0m\u001b]8;;\u001b\\\n", - "\u001b[2;36m \u001b[0m \u001b[38;2;0;135;0m'feature_1'\u001b[0m, \u001b[38;2;0;135;0m'feature_2'\u001b[0m, \u001b[38;2;0;135;0m'feature_3'\u001b[0m, \u001b[38;2;0;135;0m'feature_4'\u001b[0m, \u001b[38;2;0;135;0m'feature_5'\u001b[0m, \u001b[2m \u001b[0m\n", - "\u001b[2;36m \u001b[0m \u001b[38;2;0;135;0m'feature_6'\u001b[0m, \u001b[38;2;0;135;0m'feature_7'\u001b[0m, \u001b[38;2;0;135;0m'feature_8'\u001b[0m, \u001b[38;2;0;135;0m'feature_9'\u001b[0m, \u001b[38;2;0;135;0m'gender'\u001b[0m, \u001b[2m \u001b[0m\n", - "\u001b[2;36m \u001b[0m \u001b[38;2;0;135;0m'target'\u001b[0m\u001b[1m]\u001b[0m, \u001b[38;2;0;135;0m'label'\u001b[0m: \u001b[38;2;0;135;0m'target'\u001b[0m, \u001b[38;2;0;135;0m'label_values_or_threshold'\u001b[0m: \u001b[1m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1m]\u001b[0m, \u001b[2m \u001b[0m\n", - "\u001b[2;36m \u001b[0m \u001b[38;2;0;135;0m'facet'\u001b[0m: \u001b[1m[\u001b[0m\u001b[1m{\u001b[0m\u001b[38;2;0;135;0m'name_or_index'\u001b[0m: \u001b[38;2;0;135;0m'gender'\u001b[0m, \u001b[38;2;0;135;0m'value_or_threshold'\u001b[0m: \u001b[1m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\u001b[1m]\u001b[0m, \u001b[2m \u001b[0m\n", - "\u001b[2;36m \u001b[0m \u001b[38;2;0;135;0m'methods'\u001b[0m: \u001b[1m{\u001b[0m\u001b[38;2;0;135;0m'report'\u001b[0m: \u001b[1m{\u001b[0m\u001b[38;2;0;135;0m'name'\u001b[0m: \u001b[38;2;0;135;0m'report'\u001b[0m, \u001b[38;2;0;135;0m'title'\u001b[0m: \u001b[38;2;0;135;0m'Analysis Report'\u001b[0m\u001b[1m}\u001b[0m, \u001b[2m \u001b[0m\n", - "\u001b[2;36m \u001b[0m \u001b[38;2;0;135;0m'pre_training_bias'\u001b[0m: \u001b[1m{\u001b[0m\u001b[38;2;0;135;0m'methods'\u001b[0m: \u001b[1m[\u001b[0m\u001b[38;2;0;135;0m'CI'\u001b[0m, \u001b[38;2;0;135;0m'DPL'\u001b[0m\u001b[1m]\u001b[0m\u001b[1m}\u001b[0m\u001b[1m}\u001b[0m\u001b[1m}\u001b[0m \u001b[2m \u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
INFO Creating processing-job with name processing.py:598\n", - " Clarify-Pretraining-Bias-2025-11-09-02-39-36-699 \n", - "\n" - ], - "text/plain": [ - "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[1;38;2;0;105;255mINFO \u001b[0m Creating processing-job with name \u001b]8;id=100415;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/sagemaker/utils/processing.py\u001b\\\u001b[2mprocessing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=219709;file:///Users/mollyhe/.pyenv/versions/3.12.2/lib/python3.12/site-packages/sagemaker/utils/processing.py#598\u001b\\\u001b[2m598\u001b[0m\u001b]8;;\u001b\\\n", - "\u001b[2;36m \u001b[0m Clarify-Pretraining-Bias-\u001b[1;36m2025\u001b[0m-11-09-02-39-36-699 \u001b[2m \u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Pre-training bias analysis job submitted successfully\n" - ] - } - ], + "outputs": [], "source": [ "# Run pre-training bias analysis (no model needed)\n", "try:\n", @@ -381,15 +231,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Status: Completed\n" - ] - } - ], + "outputs": [], "source": [ "# You can go to SageMaker AI console -> Processing jobs and check the job status\n", "# Or you can run the below command\n", @@ -408,19 +250,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Bias analysis config generated successfully\n", - "Config keys: ['dataset_type', 'headers', 'label', 'label_values_or_threshold', 'facet', 'methods']\n", - "✅ All required keys present in config\n" - ] - } - ], + "outputs": [], "source": [ "# Test the internal config generation\n", "from sagemaker.core.clarify import _AnalysisConfigGenerator\n", @@ -458,17 +290,9 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Schema validation passed\n" - ] - } - ], + "outputs": [], "source": [ "# Test schema validation\n", "from sagemaker.core.clarify import ANALYSIS_CONFIG_SCHEMA_V1_0\n", diff --git a/v3-examples/ml-ops-examples/v3-transform-job-example.ipynb b/v3-examples/ml-ops-examples/v3-transform-job-example.ipynb index fb667dac0f..9720b7c82f 100644 --- a/v3-examples/ml-ops-examples/v3-transform-job-example.ipynb +++ b/v3-examples/ml-ops-examples/v3-transform-job-example.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "9fff3165", + "metadata": {}, + "source": [ + "# Batch Transform Job with XGBoost Model\n", + "\n", + "Deploy an XGBoost model and run batch inference using SageMaker Transform Job to generate predictions on validation data." + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/v3-examples/model-customization-examples/ai_registry_example.ipynb b/v3-examples/model-customization-examples/ai_registry_example.ipynb index c33f2ff41f..912ecd8885 100644 --- a/v3-examples/model-customization-examples/ai_registry_example.ipynb +++ b/v3-examples/model-customization-examples/ai_registry_example.ipynb @@ -1,30 +1,38 @@ { "cells": [ { - "cell_type": "code", + "cell_type": "markdown", "id": "initial_id", "metadata": {}, + "source": [ + "# Creating assets for model customization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9dccc2c3", + "metadata": {}, + "outputs": [], "source": [ "from rich.pretty import pprint\n", "\n", "from sagemaker.ai_registry.air_constants import REWARD_FUNCTION, REWARD_PROMPT\n", "from sagemaker.ai_registry.dataset import DataSet, CustomizationTechnique\n", "from sagemaker.ai_registry.evaluator import Evaluator" - ], - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "665a0e71fef89bde", + "metadata": {}, + "outputs": [], "source": [ "# Configure AWS credentials and region\n", "#! ada credentials update --provider=isengard --account=<> --role=Admin --profile=default --once\n", "#! aws configure set region us-west-2" - ], - "id": "665a0e71fef89bde" + ] }, { "cell_type": "markdown", @@ -47,8 +55,10 @@ }, { "cell_type": "code", + "execution_count": null, "id": "2234f21780b91625", "metadata": {}, + "outputs": [], "source": [ "\n", "# 1. S3 Data source\n", @@ -58,57 +68,55 @@ " # or use local filepath as source.\n", " # customization_technique=CustomizationTechnique.SFT\n", " )" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": null, "id": "ee2980471f8ae0c0", "metadata": {}, + "outputs": [], "source": [ "# Refreshes status from hub\n", "dataset.refresh()\n", "pprint(dataset.__dict__)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": null, "id": "30c1b17ad232110b", "metadata": {}, + "outputs": [], "source": [ "versions = dataset.get_versions()\n", "pprint(versions.__dict__)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": null, "id": "332be046d91fcefc", "metadata": {}, + "outputs": [], "source": [ "# delete specific version\n", "dataset.delete(version=\"0.0.4\")\n", "#dataset.delete(version=\"use a version from versions\")\n", "#pprint(versions)\n", "# specified deleted version should not be part of output" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": null, "id": "510d1a015e7a565c", "metadata": {}, + "outputs": [], "source": [ "# deletes all versions of this dataset by default\n", "dataset.delete()" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", @@ -120,16 +128,16 @@ }, { "cell_type": "code", + "execution_count": null, "id": "d89a8741dd64f92e", "metadata": {}, + "outputs": [], "source": [ "#Optional max_results argument for pagination or else use default config\n", "datasets = DataSet.get_all(max_results=2)\n", "for dataset in datasets:\n", " pprint(dataset)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", @@ -141,21 +149,23 @@ }, { "cell_type": "code", + "execution_count": null, "id": "572d4184cf42c7fa", "metadata": {}, + "outputs": [], "source": [ "# Use a dataset from iterator\n", "dataset = next(DataSet.get_all(max_results=2))\n", "for dataset in datasets:\n", " pprint(dataset.__dict__)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": null, "id": "ae056f626cd7e931", "metadata": {}, + "outputs": [], "source": [ "# Use a dataset by name\n", "dataset = DataSet.get(name=\"sdkv3-gen-ds2\")\n", @@ -163,31 +173,29 @@ "\n", "# We can do CRUD operation on this DataSet\n", "# e.g. dataset.delete()" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": null, "id": "44d7a8150b4b7846", "metadata": {}, + "outputs": [], "source": [ "#Create a new version of this dataset\n", "dataset.create_version(source=\"s3://
[11/26/25 17:09:22] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1392\n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sagemaker.config INFO - Not applying SDK defaults from location: /Library/Application Support/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /Users/nargokul/Library/Application Support/sagemaker/config.yaml\n" - ] - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m[11/26/25 17:09:24]\u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Runs on sagemaker us-east-\u001B[1;36m1\u001B[0m, region:us-east-\u001B[1;36m1\u001B[0m \u001B]8;id=46858;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-core/src/sagemaker/core/utils/utils.py\u001B\\\u001B[2mutils.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=786052;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-core/src/sagemaker/core/utils/utils.py#354\u001B\\\u001B[2m354\u001B[0m\u001B]8;;\u001B\\\n" - ], - "text/html": [ - "
[11/26/25 17:09:24] INFO Runs on sagemaker us-east-1, region:us-east-1 utils.py:354\n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m \u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Found credentials in shared credentials file: ~\u001B[38;2;225;0;225m/.aws/\u001B[0m\u001B[38;2;225;0;225mcredentials\u001B[0m \u001B]8;id=763694;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/venv/lib/python3.12/site-packages/botocore/credentials.py\u001B\\\u001B[2mcredentials.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=33577;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/venv/lib/python3.12/site-packages/botocore/credentials.py#1392\u001B\\\u001B[2m1392\u001B[0m\u001B]8;;\u001B\\\n" - ], - "text/html": [ - "
INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1392\n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "'s3://nova-studio-output-data/sft/final/kssharda-sft-lora-lite-2-ui-run-2bn3c-<>8/output/model'\n" - ] - } - ], - "execution_count": 1 + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-11-27T01:09:30.542741Z", "start_time": "2025-11-27T01:09:28.668735Z" } }, - "cell_type": "code", + "outputs": [], "source": [ "\n", "bedrock_model_builder = BedrockModelBuilder(\n", @@ -376,149 +323,20 @@ "bedrock_model_builder.deploy(job_name = \"nargokul-26-01\",\n", " custom_model_name = \"nargokul-26-01\",\n", " role_arn=\"arn:aws:iam::<>:role/Admin\")" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "\u001B[2;36m[11/26/25 17:09:28]\u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Found credentials in shared credentials file: ~\u001B[38;2;225;0;225m/.aws/\u001B[0m\u001B[38;2;225;0;225mcredentials\u001B[0m \u001B]8;id=892830;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/venv/lib/python3.12/site-packages/botocore/credentials.py\u001B\\\u001B[2mcredentials.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=908475;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/venv/lib/python3.12/site-packages/botocore/credentials.py#1392\u001B\\\u001B[2m1392\u001B[0m\u001B]8;;\u001B\\\n" - ], - "text/html": [ - "
[11/26/25 17:09:28] INFO Found credentials in shared credentials file: ~/.aws/credentials credentials.py:1392\n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m[11/26/25 17:09:29]\u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m S3 artifacts path: \u001B]8;id=340743;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py\u001B\\\u001B[2mbedrock_model_builder.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=618013;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py#209\u001B\\\u001B[2m209\u001B[0m\u001B]8;;\u001B\\\n", - "\u001B[2;36m \u001B[0m s3:\u001B[38;2;225;0;225m/\u001B[0m\u001B[38;2;225;0;225m/nova-studio-output-data/sft/final/kssharda-sft-lora-\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;225;0;225mlite-2-ui-run-2bn3c-<>8/output/\u001B[0m\u001B[38;2;225;0;225mmodel\u001B[0m \u001B[2m \u001B[0m\n" - ], - "text/html": [ - "
[11/26/25 17:09:29] INFO S3 artifacts path: bedrock_model_builder.py:209\n", - " s3://nova-studio-output-data/sft/final/kssharda-sft-lora- \n", - " lite-2-ui-run-2bn3c-<>8/output/model \n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m \u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Manifest path: \u001B]8;id=541474;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py\u001B\\\u001B[2mbedrock_model_builder.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=80220;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py#216\u001B\\\u001B[2m216\u001B[0m\u001B]8;;\u001B\\\n", - "\u001B[2;36m \u001B[0m s3:\u001B[38;2;225;0;225m/\u001B[0m\u001B[38;2;225;0;225m/nova-studio-output-data/sft/final/kssharda-sft-lora-\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;225;0;225mlite-2-ui-run-2bn3c-<>8/output/output/\u001B[0m\u001B[38;2;225;0;225mmanifest.\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;225;0;225mjson\u001B[0m \u001B[2m \u001B[0m\n" - ], - "text/html": [ - "
INFO Manifest path: bedrock_model_builder.py:216\n", - " s3://nova-studio-output-data/sft/final/kssharda-sft-lora- \n", - " lite-2-ui-run-2bn3c-<>8/output/output/manifest. \n", - " json \n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m \u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Looking for manifest at \u001B]8;id=356570;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py\u001B\\\u001B[2mbedrock_model_builder.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=618595;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py#223\u001B\\\u001B[2m223\u001B[0m\u001B]8;;\u001B\\\n", - "\u001B[2;36m \u001B[0m s3:\u001B[38;2;225;0;225m/\u001B[0m\u001B[38;2;225;0;225m/nova-studio-output-data/sft/final/kssharda-sft-lora-\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;225;0;225mlite-2-ui-run-2bn3c-<>8/output/output/\u001B[0m\u001B[38;2;225;0;225mmanifest.\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;225;0;225mjson\u001B[0m \u001B[2m \u001B[0m\n" - ], - "text/html": [ - "
INFO Looking for manifest at bedrock_model_builder.py:223\n", - " s3://nova-studio-output-data/sft/final/kssharda-sft-lora- \n", - " lite-2-ui-run-2bn3c-<>8/output/output/manifest. \n", - " json \n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m \u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Manifest content: \u001B[1m{\u001B[0m\u001B[38;2;0;135;0m'checkpoint_s3_bucket'\u001B[0m: \u001B]8;id=291479;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py\u001B\\\u001B[2mbedrock_model_builder.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=238165;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py#229\u001B\\\u001B[2m229\u001B[0m\u001B]8;;\u001B\\\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;0;135;0m's3://customer-escrow-<>-smtj-3ff597fc/kssharda\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;0;135;0m-sft-lora-lite-2-ui-run-2bn3c-<>8/step_4'\u001B[0m, \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;0;135;0m'intermediate_checkpoints'\u001B[0m: \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[1m[\u001B[0m\u001B[38;2;0;135;0m's3://customer-escrow-<>-smtj-3ff597fc/ksshard\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;0;135;0ma-sft-lora-lite-2-ui-run-2bn3c-<>8/step_3'\u001B[0m\u001B[1m]\u001B[0m\u001B[1m}\u001B[0m \u001B[2m \u001B[0m\n" - ], - "text/html": [ - "
INFO Manifest content: {'checkpoint_s3_bucket': bedrock_model_builder.py:229\n", - " 's3://customer-escrow-<>-smtj-3ff597fc/kssharda \n", - " -sft-lora-lite-2-ui-run-2bn3c-<>8/step_4', \n", - " 'intermediate_checkpoints': \n", - " ['s3://customer-escrow-<>-smtj-3ff597fc/ksshard \n", - " a-sft-lora-lite-2-ui-run-2bn3c-<>8/step_3']} \n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "\u001B[2;36m \u001B[0m\u001B[2;36m \u001B[0m\u001B[1;38;2;0;105;255mINFO \u001B[0m Checkpoint URI: \u001B]8;id=545156;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py\u001B\\\u001B[2mbedrock_model_builder.py\u001B[0m\u001B]8;;\u001B\\\u001B[2m:\u001B[0m\u001B]8;id=779715;file:///Users/nargokul/workspace/sagemaker-python-sdk-staging-1/sagemaker-serve/src/sagemaker/serve/bedrock_model_builder.py#236\u001B\\\u001B[2m236\u001B[0m\u001B]8;;\u001B\\\n", - "\u001B[2;36m \u001B[0m s3:\u001B[38;2;225;0;225m/\u001B[0m\u001B[38;2;225;0;225m/customer-escrow-<>-smtj-3ff597fc/kssharda-\u001B[0m \u001B[2m \u001B[0m\n", - "\u001B[2;36m \u001B[0m \u001B[38;2;225;0;225msft-lora-lite-2-ui-run-2bn3c-<>8/\u001B[0m\u001B[38;2;225;0;225mstep_4\u001B[0m \u001B[2m \u001B[0m\n" - ], - "text/html": [ - "
INFO Checkpoint URI: bedrock_model_builder.py:236\n", - " s3://customer-escrow-<>-smtj-3ff597fc/kssharda- \n", - " sft-lora-lite-2-ui-run-2bn3c-<>8/step_4 \n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "{'ResponseMetadata': {'RequestId': '95bc35c0-0f8e-48cb-95e2-00fb77b17b4d',\n", - " 'HTTPStatusCode': 202,\n", - " 'HTTPHeaders': {'date': 'Thu, 27 Nov 2025 01:09:30 GMT',\n", - " 'content-type': 'application/json',\n", - " 'content-length': '88',\n", - " 'connection': 'keep-alive',\n", - " 'x-amzn-requestid': '95bc35c0-0f8e-48cb-95e2-00fb77b17b4d'},\n", - " 'RetryAttempts': 0},\n", - " 'modelArn': 'arn:aws:bedrock:us-east-1:<>:custom-model/imported/pl4keb8mfank'}" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 2 + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "from sagemaker.ai_registry.dataset import DataSet\n", "\n", "dataset = DataSet.get(name=\"arn:aws:sagemaker:us-east-1:<>:hub-content/MDG6N5CA58D0IJMC1OPJOPIKOS2VPPLP0AM6UBOT9D73B8A34HTG/DataSet/nova-2-0-sft-dataset/1.0.0\")\n", "\n", "pprint(dataset.__dict__)" - ], - "outputs": [], - "execution_count": null + ] } ], "metadata": { diff --git a/v3-examples/model-customization-examples/benchmark_demo.ipynb b/v3-examples/model-customization-examples/benchmark_demo.ipynb index 442d93b690..557e01ec35 100644 --- a/v3-examples/model-customization-examples/benchmark_demo.ipynb +++ b/v3-examples/model-customization-examples/benchmark_demo.ipynb @@ -16,7 +16,7 @@ "## Step 1: Discover Available Benchmarks\n", "\n", "Discover the benchmark properties and available options:\n", - "https://docs.aws.amazon.com/sagemaker/latest/dg/nova-model-evaluation.html" + "[Nova Model Evaluation](https://docs.aws.amazon.com/sagemaker/latest/dg/nova-model-evaluation.html)" ] }, { diff --git a/v3-examples/model-customization-examples/sm-studio-nova-training-job-sample-notebook.ipynb b/v3-examples/model-customization-examples/sm-studio-nova-training-job-sample-notebook.ipynb new file mode 100644 index 0000000000..20c51e562e --- /dev/null +++ b/v3-examples/model-customization-examples/sm-studio-nova-training-job-sample-notebook.ipynb @@ -0,0 +1,1087 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "babaeb90", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "novaTrainingJobNotebookHeaderMarkdown" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "# Model Customization using SageMaker Training Job" + ] + }, + { + "cell_type": "markdown", + "id": "a16fc6c1-c18f-4a06-ae98-36b12ec72ab3", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "This notebook provides an end-to-end walkthrough for creating SageMaker Training job using a SageMaker Nova model and deploy it for inference." + ] + }, + { + "cell_type": "markdown", + "id": "940f9af2-cb1e-40be-839d-48db014d67f1", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Setup and Dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84cf410f", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install --upgrade sagemaker --quiet # restart the kernel after running this cell" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "234f7398-fd6b-4d02-a406-0491924c461d", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "import os\n", + "import json\n", + "import boto3\n", + "from rich.pretty import pprint\n", + "from sagemaker.core.helper.session_helper import Session\n", + "\n", + "REGION = boto3.Session().region_name\n", + "sm_client = boto3.client(\"sagemaker\", region_name=REGION)\n", + "\n", + "# Create SageMaker session\n", + "sagemaker_session = Session(sagemaker_client=sm_client)\n", + "\n", + "print(f\"Region: {REGION}\")\n", + "\n", + "# For MLFlow native metrics in Trainer wait, run below line with appropriate region\n", + "os.environ[\"SAGEMAKER_MLFLOW_CUSTOM_ENDPOINT\"] = f\"https://mlflow.sagemaker.{REGION}.app.aws\"" + ] + }, + { + "cell_type": "markdown", + "id": "b9bf5959", + "metadata": {}, + "source": [ + "#### Create Training Dataset\n", + "Below section provides sample code to create the training dataset arn" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39aaeb1d", + "metadata": {}, + "outputs": [], + "source": [ + "from sagemaker.ai_registry.dataset import DataSet\n", + "from sagemaker.ai_registry.dataset_utils import CustomizationTechnique\n", + "\n", + "# Register dataset in SageMaker AI Registry. This creates a versioned dataset that can be referenced by ARN\n", + "dataset = DataSet.create(\n", + " name=\"demo-sft-dataset\",\n", + " source=\"s3://your-bucket/dataset/training_dataset.jsonl\", # source can be S3 or local path\n", + " #customization_technique=CUSTOMIZATION_TECHNIQUE.SFT # or DPO or RLVR\n", + " # Optional technique name for minimal dataset format check.\n", + " wait=True\n", + ")\n", + "\n", + "print(f\"TRAINING_DATASET ARN: {dataset.arn}\")\n", + "# TRAINING_DATASET = dataset.arn" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea22bd22", + "metadata": {}, + "outputs": [], + "source": [ + "# Required Configs\n", + "BASE_MODEL = \"\"\n", + "\n", + "# MODEL_PACKAGE_GROUP_NAME is same as CUSTOM_MODEL_NAME\n", + "MODEL_PACKAGE_GROUP_NAME = \"\"\n", + "\n", + "TRAINING_DATASET = \"\"\n", + "\n", + "S3_OUTPUT_PATH = \"\"\n", + "\n", + "ROLE_ARN = \"\"" + ] + }, + { + "cell_type": "markdown", + "id": "259aca67d3d3863b", + "metadata": {}, + "source": [ + "#### Create Model Package Group" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90a1069d19eeee7", + "metadata": {}, + "outputs": [], + "source": [ + "from sagemaker.core.resources import ModelPackageGroup\n", + "model_package_group = ModelPackageGroup.create(\n", + " model_package_group_name=MODEL_PACKAGE_GROUP_NAME,\n", + " model_package_group_description='' # Required Description\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "1c931764", + "metadata": {}, + "source": [ + "## Part 1: Fine-tuning\n", + "\n", + "### Step 1: Creating the Trainer" + ] + }, + { + "cell_type": "markdown", + "id": "f23e67f7", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "" + }, + "source": [ + "#### Choose one of the following trainer techniques:\n", + "- **Option 1: SFT Trainer (Supervised Fine-Tuning)** \n", + "- **Option 2: Create RLVRTrainer (Reinforcement Learning with Verifiable Rewards)**. \n", + "- **Option 3: DPO Trainer (Direct Preference Optimization)** \n", + "\n", + "**Instructions:** Run only ONE of the trainers, not all of them." + ] + }, + { + "cell_type": "markdown", + "id": "32fd436b", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "SFT" + }, + "source": [ + "#### Create SFT Trainer (Supervised Fine-Tuning)\n", + "\n", + "##### Key Parameters:\n", + "* `model`: base_model id on Sagemaker Hubcontent that is available to finetune (or) ModelPackage artifacts\n", + "* `training_type`: Choose from TrainingType Enum(sagemaker.train.common) either LORA OR FULL. (optional)\n", + "* `model_package_group`: ModelPackage group name or ModelPackageGroup (optional)\n", + "* `mlflow_resource_arn`: MLFlow app ARN to track the training job (optional)\n", + "* `mlflow_experiment_name`: MLFlow app experiment name(str) (optional)\n", + "* `mlflow_run_name`: MLFlow app run name(str) (optional)\n", + "* `training_dataset`: Training Dataset - either Dataset ARN or S3 Path of the dataset (Please note these are required for a training job to run, can be either provided via Trainer or .train()) (optional)\n", + "* `validation_dataset`: Validation Dataset - either Dataset ARN or S3 Path of the dataset (optional)\n", + "* `s3_output_path`: S3 path for the trained model artifacts (optional)\n", + "* `base_job_name` : Unique job name (optional)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "062953d8", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "SFT" + }, + "outputs": [], + "source": [ + "from sagemaker.train.sft_trainer import SFTTrainer\n", + "from sagemaker.train.common import TrainingType\n", + "\n", + "trainer = SFTTrainer(\n", + " model=BASE_MODEL,\n", + " training_type=TrainingType.LORA,\n", + " model_package_group=model_package_group,\n", + " training_dataset=TRAINING_DATASET,\n", + " s3_output_path=S3_OUTPUT_PATH,\n", + " sagemaker_session=sagemaker_session,\n", + " role=ROLE_ARN\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "cd93226c", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "" + }, + "source": [ + "### OR" + ] + }, + { + "cell_type": "markdown", + "id": "1b5603ee", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "RLVR" + }, + "source": [ + "#### Create RLVRTrainer (Reinforcement Learning with Verifiable Rewards)\n", + "\n", + "##### Key Parameters:\n", + "* `model`: base_model id on Sagemaker Hubcontent that is available to finetune (or) ModelPackage artifacts\n", + "* `custom_reward_function`: Custom reward function/Evaluator ARN (optional)\n", + "* `model_package_group`: ModelPackage group name or ModelPackageGroup (optional)\n", + "* `mlflow_resource_arn`: MLFlow app ARN to track the training job (optional)\n", + "* `mlflow_experiment_name`: MLFlow app experiment name(str) (optional)\n", + "* `mlflow_run_name`: MLFlow app run name(str) (optional)\n", + "* `training_dataset`: Training Dataset - either Dataset ARN or S3 Path of the dataset (Please note these are required for a training job to run, can be either provided via Trainer or .train()) (optional)\n", + "* `validation_dataset`: Validation Dataset - either Dataset ARN or S3 Path of the dataset (optional)\n", + "* `s3_output_path`: S3 path for the trained model artifacts (optional)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5aa51a5f", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "RLVR" + }, + "outputs": [], + "source": [ + "from sagemaker.train.rlvr_trainer import RLVRTrainer\n", + "\n", + "trainer = RLVRTrainer(\n", + " model=BASE_MODEL,\n", + " model_package_group=model_package_group,\n", + " training_dataset=TRAINING_DATASET,\n", + " s3_output_path=S3_OUTPUT_PATH,\n", + " sagemaker_session=sagemaker_session,\n", + " role=ROLE_ARN\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "a61dbe9f", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "" + }, + "source": [ + "### OR" + ] + }, + { + "cell_type": "markdown", + "id": "88f8bfde", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "DPO" + }, + "source": [ + "#### Create DPO Trainer (Direct Preference Optimization)\n", + "\n", + "Direct Preference Optimization (DPO) is a method for training language models to follow human preferences. Unlike traditional RLHF (Reinforcement Learning from Human Feedback), DPO directly optimizes the model using preference pairs without needing a reward model.\n", + "\n", + "##### Key Parameters:\n", + "- `model` Base model to fine-tune (from SageMaker Hub)\n", + "- `training_type` Fine-tuning method (LoRA recommended for efficiency)\n", + "- `training_dataset` ARN of the registered preference dataset\n", + "- `model_package_group` Where to store the fine-tuned model\n", + "- `mlflow_resource_arn` MLflow tracking server for experiment logging " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b74c57f8", + "metadata": { + "editable": true, + "jumpStartAlterations": [ + "trainerSelection" + ], + "slideshow": { + "slide_type": "" + }, + "tags": [], + "trainer_type": "DPO" + }, + "outputs": [], + "source": [ + "from sagemaker.train.dpo_trainer import DPOTrainer\n", + "from sagemaker.train.common import TrainingType\n", + "\n", + "trainer = DPOTrainer(\n", + " model=BASE_MODEL,\n", + " training_type=TrainingType.LORA,\n", + " model_package_group=model_package_group,\n", + " training_dataset=TRAINING_DATASET,\n", + " s3_output_path=S3_OUTPUT_PATH,\n", + " sagemaker_session=sagemaker_session,\n", + " role=ROLE_ARN\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "514186e9", + "metadata": {}, + "source": [ + "### Step 2: Get Finetuning Options and Modify" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2f6eeb5e", + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Default Finetuning Options:\")\n", + "pprint(trainer.hyperparameters.to_dict())\n", + "\n", + "# Modify options like object attributes\n", + "trainer.hyperparameters.learning_rate = 0.0002\n", + "\n", + "print(\"\\nModified/User defined Options:\")\n", + "pprint(trainer.hyperparameters.to_dict())" + ] + }, + { + "cell_type": "markdown", + "id": "18f4e5df", + "metadata": {}, + "source": [ + "### Step 3: Start Training" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31690f41", + "metadata": {}, + "outputs": [], + "source": [ + "training_job = trainer.train(wait=True)\n", + "\n", + "TRAINING_JOB_NAME = training_job.training_job_name\n", + "\n", + "pprint(training_job)" + ] + }, + { + "cell_type": "markdown", + "id": "60b77a45", + "metadata": {}, + "source": [ + "### Step 4: Describe Training job" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9277fde0", + "metadata": {}, + "outputs": [], + "source": [ + "from sagemaker.core.resources import TrainingJob\n", + "\n", + "response = TrainingJob.get(training_job_name=TRAINING_JOB_NAME)\n", + "pprint(response)" + ] + }, + { + "cell_type": "markdown", + "id": "evaluation-section", + "metadata": {}, + "source": [ + "# Part 2: Model Evaluation\n", + "\n", + "This section demonstrates the basic user-facing flow for creating and managing evaluation jobs" + ] + }, + { + "cell_type": "markdown", + "id": "cleanup-pipeline", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Step 1: Create BenchmarkEvaluator\n", + "\n", + "Create a BenchmarkEvaluator instance with the desired benchmark. The evaluator will use Jinja2 templates to render a complete pipeline definition.\n", + "\n", + "### Key Parameters:\n", + "- `benchmark`: Benchmark type from the Benchmark enum\n", + "- `model`: Model ARN from SageMaker hub content\n", + "- `s3_output_path`: S3 location for evaluation outputs\n", + "- `mlflow_resource_arn`: MLflow tracking server ARN for experiment tracking (optional)\n", + "- `model_package_group`: Model package group ARN (optional)\n", + "- `source_model_package`: Source model package ARN (optional)\n", + "- `model_artifact`: ARN of model artifact for lineage tracking (auto-inferred from source_model_package) (optional)\n", + "\n", + "**Note:** When you call `evaluate()`, the system will start evaluation job. The evaluator will:\n", + "1. Build template context with all required parameters\n", + "2. Render the pipeline definition from `DETERMINISTIC_TEMPLATE` using Jinja2\n", + "3. Create or update the pipeline with the rendered definition\n", + "4. Start the pipeline execution with empty parameters (all values pre-substituted) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "delete-existing-pipeline", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "from sagemaker.train.evaluate import BenchMarkEvaluator\n", + "from sagemaker.train.evaluate import get_benchmarks, get_benchmark_properties\n", + "from rich.pretty import pprint\n", + "import logging\n", + "logging.basicConfig(\n", + " level=logging.INFO,\n", + " format='%(levelname)s - %(name)s - %(message)s'\n", + ")\n", + "\n", + "# Get available benchmarks\n", + "Benchmark = get_benchmarks()\n", + "pprint(list(Benchmark))\n", + "\n", + "# Print properties for a specific benchmark\n", + "pprint(get_benchmark_properties(benchmark=Benchmark.GEN_QA))\n", + "\n", + "\n", + "# Create evaluator with GEN_QA benchmark\n", + "evaluator = BenchMarkEvaluator(\n", + " benchmark=Benchmark.GEN_QA,\n", + " model=BASE_MODEL,\n", + " s3_output_path=S3_OUTPUT_PATH,\n", + ")\n", + "\n", + "pprint(evaluator)" + ] + }, + { + "cell_type": "markdown", + "id": "run-evaluation", + "metadata": {}, + "source": [ + "## Step 2: Run Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "start-evaluation", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Run evaluation\n", + "execution = evaluator.evaluate()\n", + "\n", + "print(f\"Evaluation job started!\")\n", + "print(f\"Job ARN: {execution.arn}\")\n", + "print(f\"Job Name: {execution.name}\")\n", + "print(f\"Status: {execution.status.overall_status}\")\n", + "\n", + "pprint(execution)" + ] + }, + { + "cell_type": "markdown", + "id": "a3de8255-9f98-444a-99a6-cfe7cc2584af", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Step 3: Monitor Execution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "monitor-evaluation", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "execution.refresh()\n", + "\n", + "print(f\"Current status: {execution.status}\")\n", + "\n", + "# Display individual step statuses\n", + "if execution.status.step_details:\n", + " print(\"\\nStep Details:\")\n", + " for step in execution.status.step_details:\n", + " print(f\" {step.name}: {step.status}\")" + ] + }, + { + "cell_type": "markdown", + "id": "2ebac85a-adee-4f18-935d-478037c7a1f3", + "metadata": {}, + "source": [ + "## Step 4: Wait for Completion\n", + "\n", + "Wait for the pipeline to complete. This provides rich progress updates in Jupyter notebooks:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74b51cca-2024-4276-b05d-48f52e527c06", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "execution.wait(target_status=\"Succeeded\", poll=5, timeout=3600)\n", + "\n", + "print(f\"\\nFinal Status: {execution.status.overall_status}\")" + ] + }, + { + "cell_type": "markdown", + "id": "0d153370-213a-41d0-8a95-f4ffccf8f9aa", + "metadata": {}, + "source": [ + "## Step 5: View Results\n", + "\n", + "Display the evaluation results in a formatted table:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2f470824-7740-48bb-9282-a7b9d0407fff", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "execution.show_results()" + ] + }, + { + "cell_type": "markdown", + "id": "92bda96d-5be7-408f-9b47-ae46772ac03e", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Part 3. Deploying the Model to Bedrock for inference\n", + "\n", + "Trained model artifacts and checkpoints are stored in your designated escrow S3 bucket. You can access the training checkpoint location from the `describe_training_job` response.\n", + "\n", + "By calling `create_custom_model` API, you can create your custom model referencing the model artifacts stored in your S3 escrow bucket." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "784304f4-eb4f-48c8-b572-e5a18c5a9929", + "metadata": {}, + "outputs": [], + "source": [ + "import boto3\n", + "import json\n", + "from urllib.parse import urlparse\n", + "\n", + "bedrock_custom_model_name = \"\" # customize as needed\n", + "\n", + "describe_training_response = sm_client.describe_training_job(TrainingJobName=TRAINING_JOB_NAME)\n", + "\n", + "training_output_s3_uri = describe_training_response['OutputDataConfig']['S3OutputPath']\n", + "\n", + "def get_s3_manifest(training_output_s3_uri):\n", + " try:\n", + " s3_client = boto3.client('s3')\n", + " parsed_uri = urlparse(training_output_s3_uri)\n", + " bucket = parsed_uri.netloc\n", + " key = parsed_uri.path.lstrip('/')\n", + " manifest_key = f\"{key.rstrip('/')}/{TRAINING_JOB_NAME}/output/output/manifest.json\"\n", + "\n", + " print(f\"Fetching manifest from s3://{bucket}/{manifest_key}\")\n", + " response = s3_client.get_object(Bucket=bucket, Key=manifest_key)\n", + "\n", + " manifest_content = response['Body'].read().decode('utf-8')\n", + " manifest = json.loads(manifest_content)\n", + " if 'checkpoint_s3_bucket' not in manifest:\n", + " raise ValueError(\"Checkpoint location not found in manifest\")\n", + " print(f\"Successfully retrieved checkpoint S3 URI: {manifest['checkpoint_s3_bucket']}\")\n", + " return manifest['checkpoint_s3_bucket']\n", + " except s3_client.exceptions.NoSuchKey:\n", + " raise FileNotFoundError(f\"Manifest file not found at s3://{bucket}/{manifest_key}\")\n", + " except json.JSONDecodeError as e:\n", + " raise ValueError(f\"Failed to parse manifest JSON: {str(e)}\")\n", + " except Exception as e:\n", + " raise Exception(f\"Error fetching manifest: {str(e)}\")\n", + "\n", + "s3_checkpoint_path = get_s3_manifest(training_output_s3_uri)\n", + "\n", + "\n", + "bedrock_client = boto3.Session().client(service_name=\"bedrock\", region_name=REGION)\n", + "\n", + "\n", + "s3_checkpoint_path = describe_training_response[\"CheckpointConfig\"][\"S3Uri\"]\n", + "\n", + "try:\n", + " response = bedrock_client.create_custom_model(\n", + " modelName=bedrock_custom_model_name,\n", + " modelSourceConfig={\"s3DataSource\": {\"s3Uri\": s3_checkpoint_path}},\n", + " roleArn=ROLE_ARN,\n", + " # Optionally, add modelTags here\n", + " )\n", + " print(\"Custom model ARN:\", response[\"modelArn\"])\n", + "except Exception as e:\n", + " print(f\"An unexpected error occurred: {e}\")" + ] + }, + { + "cell_type": "markdown", + "id": "f0dc4211-788c-4e5d-844a-58176ac69cea", + "metadata": {}, + "source": [ + "To monitor the job, use the `get_custom_model` operation to retrieve the job status. Please allow some time for the job to complete as this can take upto 20 minutes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3795cd13-57fd-44f7-b2e2-9f51f2df74c4", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "while True:\n", + " custom_model_response = bedrock_client.get_custom_model(modelIdentifier=bedrock_custom_model_name)\n", + " model_status = custom_model_response[\"modelStatus\"]\n", + " print(f\"Custom model status: {model_status}\")\n", + " if model_status == \"Active\":\n", + " break\n", + " elif model_status in [\"Failed\"]:\n", + " raise Exception(f\"Custom model creation failed with status: {model_status}\")\n", + " time.sleep(30)\n", + "print(\"Custom model is ACTIVE.\")\n", + "custom_model_response" + ] + }, + { + "cell_type": "markdown", + "id": "c4ecb46f-26ac-463e-b644-c8eb65173ac2", + "metadata": {}, + "source": [ + "After you create a custom model, you can set up inference using one of the following options:\n", + "1. **Purchase Provisioned Throughput** – Purchase Provisioned Throughput for your model to set up dedicated compute capacity with guaranteed throughput for consistent performance and lower latency.\n", + "For more information about Provisioned Throughput, see [Increase model invocation capacity with Provisioned Throughput in Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/prov-throughput.html). For more information about using custom models with Provisioned Throughput, [see Purchase Provisioned Throughput for a custom model](https://docs.aws.amazon.com/bedrock/latest/userguide/custom-model-use-pt.html).\n", + "2. **Deploy custom model for on-demand inference (only LoRA fine-tuned Amazon Nova models)** – To set up on-demand inference, you deploy the custom model with a custom model deployment. After you deploy the model, you invoke it using the ARN for the custom model deployment. With on-demand inference, you only pay for what you use and you don't need to set up provisioned compute resources.\n", + "For more information about deploying custom models for on-demand inference, see [Deploy a custom model for on-demand inference](https://docs.aws.amazon.com/bedrock/latest/userguide/deploy-custom-model-on-demand.html)." + ] + }, + { + "cell_type": "markdown", + "id": "f7b52193-3624-4485-84c7-86b7f5d0e7fb", + "metadata": {}, + "source": [ + "#### Deploy custom model for inference by using Provisioned Throughput" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f0064c4-7302-47de-a125-a0f07d4e13ad", + "metadata": {}, + "outputs": [], + "source": [ + "provisioned_model_name = \"test-provisioned-model\"\n", + "custom_model_id = custom_model_response[\"modelArn\"]\n", + "\n", + "try:\n", + " response = bedrock_client.create_provisioned_model_throughput(\n", + " modelId=custom_model_id, provisionedModelName=provisioned_model_name, modelUnits=1\n", + " )\n", + " provisioned_model_arn = response[\"provisionedModelArn\"]\n", + " print(\"Provisioned model ARN:\", provisioned_model_arn)\n", + "except Exception as e:\n", + " print(f\"An unexpected error occurred: {e}\")" + ] + }, + { + "cell_type": "markdown", + "id": "ef1671ec-81d7-4fc7-89a5-7ee5a2e8b67b", + "metadata": {}, + "source": [ + "Wait for provisioned model to become ACTIVE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efef8325-fade-49ef-a2bd-ec0215a56f25", + "metadata": {}, + "outputs": [], + "source": [ + "while True:\n", + " response = bedrock_client.get_provisioned_model_throughput(\n", + " provisionedModelId=provisioned_model_arn\n", + " )\n", + " model_status = response[\"status\"]\n", + " print(f\"Provisioned model status: {model_status}\")\n", + " if model_status == \"InService\":\n", + " break\n", + " elif model_status in [\"Failed\"]:\n", + " raise Exception(f\"Provisioned model failed with status: {model_status}\")\n", + " time.sleep(30)\n", + "print(\"Provisioned model is in service.\")\n", + "response" + ] + }, + { + "cell_type": "markdown", + "id": "68a1443e-ef01-4ee1-9f8d-10e9ec3a55a3", + "metadata": {}, + "source": [ + "Finally, you can invoke the model like any other Bedrock-hosted model using the invoke-model API" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80f8ecee-9a5f-46a5-97dc-72a2e6a7c693", + "metadata": {}, + "outputs": [], + "source": [ + "# Invoke model (Inference)\n", + "bedrock_runtime = boto3.client(\"bedrock-runtime\", region_name=REGION)\n", + "\n", + "request_body = {\n", + " \"inferenceConfig\": {\"max_new_tokens\": 1000, \"temperature\": 0.7, \"top_p\": 0.9},\n", + " \"messages\": [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": [\n", + " {\"text\": \"Tell me about Amazon Bedrock in less than 100 words.\"}\n", + " ],\n", + " }\n", + " ],\n", + "}\n", + "\n", + "response = bedrock_runtime.invoke_model(\n", + " modelId=provisioned_model_arn,\n", + " body=json.dumps(request_body),\n", + " contentType=\"application/json\",\n", + " accept=\"application/json\",\n", + ")\n", + "\n", + "response_body = json.loads(response[\"body\"].read())\n", + "print(response_body[\"output\"][\"message\"][\"content\"][0][\"text\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b51edee9-6663-4863-a5f2-c72e9cfe7e9e", + "metadata": {}, + "source": [ + "#### Deploy custom model for On-Demand Inference\n", + "**Important Note:** On-demand inference is currently supported only for LoRA-based fine-tuned models.\n", + "\n", + "Once the custom model has reached Active Status, deploy it for on-demand inference by creating custom model deployment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d8beda2-c96d-40e5-ac86-ff2a58eadd40", + "metadata": {}, + "outputs": [], + "source": [ + "model_deployment_name = \"