|
22 | 22 | "4. Clean up resources\n", |
23 | 23 | "\n", |
24 | 24 | "**Prerequisites:**\n", |
25 | | - "- AWS credentials with SageMaker and Bedrock access in `us-east-1`\n", |
| 25 | + "- AWS credentials with SageMaker and Bedrock access\n", |
26 | 26 | "- `sagemaker-serve` and `sagemaker-train` packages installed\n", |
27 | 27 | "- An IAM role with Bedrock and SageMaker permissions" |
28 | 28 | ] |
|
46 | 46 | "import random\n", |
47 | 47 | "import boto3\n", |
48 | 48 | "\n", |
| 49 | + "# Set your region — Nova fine-tuning is available in us-east-1\n", |
49 | 50 | "REGION = \"us-east-1\"\n", |
50 | 51 | "os.environ[\"AWS_DEFAULT_REGION\"] = REGION\n", |
| 52 | + "os.environ[\"SAGEMAKER_REGION\"] = REGION\n", |
51 | 53 | "\n", |
52 | 54 | "from sagemaker.core.helper.session_helper import get_execution_role\n", |
53 | 55 | "\n", |
|
78 | 80 | "source": [ |
79 | 81 | "s3 = boto3.client(\"s3\", region_name=REGION)\n", |
80 | 82 | "\n", |
| 83 | + "# Ensure the bucket exists\n", |
| 84 | + "try:\n", |
| 85 | + " s3.head_bucket(Bucket=bucket)\n", |
| 86 | + "except Exception:\n", |
| 87 | + " s3.create_bucket(\n", |
| 88 | + " Bucket=bucket,\n", |
| 89 | + " CreateBucketConfiguration={\"LocationConstraint\": REGION},\n", |
| 90 | + " )\n", |
| 91 | + " print(f\"Created bucket: {bucket}\")\n", |
| 92 | + "\n", |
81 | 93 | "train_key = \"nova-example/train.jsonl\"\n", |
82 | 94 | "train_uri = f\"s3://{bucket}/{train_key}\"\n", |
83 | 95 | "\n", |
|
98 | 110 | "cell_type": "markdown", |
99 | 111 | "metadata": {}, |
100 | 112 | "source": [ |
101 | | - "## Step 2: Fine-tune Nova Micro with SFTTrainer\n", |
| 113 | + "## Step 2: Create model package group\n", |
| 114 | + "\n", |
| 115 | + "SFTTrainer requires a model package group to register the fine-tuned model.\n", |
| 116 | + "We create one if it doesn't already exist." |
| 117 | + ] |
| 118 | + }, |
| 119 | + { |
| 120 | + "cell_type": "code", |
| 121 | + "execution_count": null, |
| 122 | + "metadata": {}, |
| 123 | + "outputs": [], |
| 124 | + "source": [ |
| 125 | + "sm = boto3.client(\"sagemaker\", region_name=REGION)\n", |
| 126 | + "\n", |
| 127 | + "MODEL_PACKAGE_GROUP = f\"nova-example-{account_id}\"\n", |
| 128 | + "\n", |
| 129 | + "try:\n", |
| 130 | + " sm.describe_model_package_group(ModelPackageGroupName=MODEL_PACKAGE_GROUP)\n", |
| 131 | + " print(f\"Model package group already exists: {MODEL_PACKAGE_GROUP}\")\n", |
| 132 | + "except sm.exceptions.ClientError:\n", |
| 133 | + " sm.create_model_package_group(\n", |
| 134 | + " ModelPackageGroupName=MODEL_PACKAGE_GROUP,\n", |
| 135 | + " ModelPackageGroupDescription=\"Nova fine-tuning example models\",\n", |
| 136 | + " )\n", |
| 137 | + " print(f\"Created model package group: {MODEL_PACKAGE_GROUP}\")" |
| 138 | + ] |
| 139 | + }, |
| 140 | + { |
| 141 | + "cell_type": "markdown", |
| 142 | + "metadata": {}, |
| 143 | + "source": [ |
| 144 | + "## Step 3: Fine-tune Nova Micro with SFTTrainer\n", |
102 | 145 | "\n", |
103 | 146 | "This launches a SageMaker training job. It typically takes 15-30 minutes to complete." |
104 | 147 | ] |
|
115 | 158 | " model=\"nova-textgeneration-micro\",\n", |
116 | 159 | " training_dataset=train_uri,\n", |
117 | 160 | " accept_eula=True,\n", |
118 | | - " model_package_group=\"nova-example-models\",\n", |
| 161 | + " model_package_group=MODEL_PACKAGE_GROUP,\n", |
119 | 162 | ")\n", |
120 | 163 | "\n", |
121 | 164 | "# Set wait=True to block until training completes\n", |
|
130 | 173 | "cell_type": "markdown", |
131 | 174 | "metadata": {}, |
132 | 175 | "source": [ |
133 | | - "## Step 3: Deploy to Bedrock with BedrockModelBuilder\n", |
| 176 | + "## Step 4: Deploy to Bedrock with BedrockModelBuilder\n", |
134 | 177 | "\n", |
135 | 178 | "The builder handles the full deployment flow:\n", |
136 | 179 | "- Fetches the model package from the training job\n", |
|
165 | 208 | "deployment_name = f\"{custom_model_name}-dep\"\n", |
166 | 209 | "\n", |
167 | 210 | "print(f\"Deploying as: {custom_model_name}\")\n", |
168 | | - "print(f\"This will poll for model creation and deployment — may take several minutes...\")\n", |
| 211 | + "print(\"This will poll for model creation and deployment — may take several minutes...\")\n", |
169 | 212 | "\n", |
170 | 213 | "response = builder.deploy(\n", |
171 | 214 | " custom_model_name=custom_model_name,\n", |
|
182 | 225 | "cell_type": "markdown", |
183 | 226 | "metadata": {}, |
184 | 227 | "source": [ |
185 | | - "## Step 4: Test inference (optional)\n", |
| 228 | + "## Step 5: Test inference (optional)\n", |
186 | 229 | "\n", |
187 | 230 | "Once the deployment is Active, you can invoke it via the Bedrock Runtime API." |
188 | 231 | ] |
|
220 | 263 | "cell_type": "markdown", |
221 | 264 | "metadata": {}, |
222 | 265 | "source": [ |
223 | | - "## Step 5: Cleanup\n", |
| 266 | + "## Step 6: Cleanup\n", |
224 | 267 | "\n", |
225 | 268 | "Delete the deployment and custom model to avoid ongoing charges." |
226 | 269 | ] |
|
0 commit comments