feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(serve): support fine-tuned models in deployment-config API - #6041

Merged
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type
Jul 22, 2026
Merged

feat(serve): support fine-tuned models in deployment-config API#6041
jam-jee merged 1 commit into
aws:masterfrom
Lokiiiiii:select-recipe-hosting-config-by-instance-type

Conversation

@Lokiiiiii

Copy link
Copy Markdown
Contributor

Summary

Make ModelBuilder.list_deployment_configs / get_deployment_config / set_deployment_config work for fine-tuned (model-customization) models in addition to base/JumpStart models, dispatching internally on _is_model_customization(). For fine-tuned models the recipe's published HostingConfigs are the source of truth; selection is by instance type (recipe configs are largely unnamed).

The base "deployment config" vs recipe "hosting config" distinction stays internal: fine-tuned configs are normalized to the same shape the base response returns (DeploymentConfigName + a nested DeploymentArgs block with ImageUri/InstanceType/Environment/ComputeResourceRequirements and the other base DeploymentArgs keys, present as None when a recipe doesn't provide them), so callers iterate either pathway identically. BenchmarkMetrics/AccelerationConfigs are None (recipes publish none today); an additive IsDefault flag marks the recipe's Default config.

set_deployment_config(instance_type=...) applies the whole matching config (image, env, compute requirements) at build time and raises on an unpublished/ambiguous instance type. list_deployment_configs(instance_type=...) filters to that instance. Configs published with only DefaultInstanceType are matched consistently end-to-end so they aren't silently dropped at build.

Paired dependency

This is the SDK half of a paired change. The consumer is an Amazon-internal SageMaker agent model-deployment skill tracked in internal review CR-289903643 (code.amazon.com/reviews/CR-289903643, not publicly accessible). The two are mutually dependent and are intended to land together.

Testing

python3 -m pytest sagemaker-serve/tests/unit/test_recipe_hosting_config_selection.py (31 tests) plus the base-model regression suites (coverage boost, instance-type inference, nova hosting config, compute requirements) — 102 passed. Includes a shape-parity test tied to the base DeploymentArgs/DeploymentConfigMetadata dataclass slots so it fails if base ever adds a field the fine-tuned shape doesn't mirror.

@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 0b762fc to ab5d838CompareJuly 17, 2026 15:55
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from ab5d838 to 877aea5CompareJuly 17, 2026 16:30
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 877aea5 to 1c7b1fcCompareJuly 17, 2026 17:26
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 1c7b1fc to 8556ed8CompareJuly 17, 2026 17:42
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 8556ed8 to 142a2b6CompareJuly 17, 2026 18:05
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 142a2b6 to 4a55e6fCompareJuly 17, 2026 18:33
@Lokiiiiii
Lokiiiiii marked this pull request as ready for review July 17, 2026 18:37
Make ModelBuilder.list_deployment_configs / get_deployment_config /
set_deployment_config work for fine-tuned (model-customization) models
in addition to base/JumpStart models, dispatching internally on
_is_model_customization(). For fine-tuned models the recipe's published
HostingConfigs are the source of truth; selection is by instance type
(recipe configs are largely unnamed).
The base "deployment config" vs recipe "hosting config" distinction is
internal and does not surface: fine-tuned configs are normalized to a
shape compatible with the base response (DeploymentConfigName plus a
nested DeploymentArgs block, plus BenchmarkMetrics/AccelerationConfigs
and an additive IsDefault flag). The normalized fine-tuned shape always
populates the DeploymentArgs keys (None when unset); the base response
may omit unset keys (its serializer drops empty slots), so the fine-tuned
shape is a superset — callers consuming both pathways should use .get()
for the optional keys (documented on the methods).
set_deployment_config applies the whole matching config (image,
environment, compute requirements) at build time. A caller-provided
image_uri still takes precedence over the config's ImageUri (documented).
Both branches fail fast on bad input: the fine-tuned branch requires
instance_type and raises on an unpublished or ambiguous instance; the
base branch requires config_name AND instance_type and now also rejects
an unpublished config name or an instance the config does not support
(validated against JumpStart metadata) instead of silently recording a
no-op selection.
Instance-type matching honors the config's full offered set, not only
its default. A base config is a multi-instance bundle: list_deployment_
configs(instance_type=X) filters against each config's supported-instance
metadata (supported_inference_instance_types) and materializes matched
configs FOR X, so a config that supports X but defaults to another
instance is neither discarded nor materialized at the wrong instance.
Recipe hosting configs are per-instance bundles by contract, but
SupportedInstanceTypes, when present, is honored for selection and
filtering. list/get/set agree for the same selection: get_deployment_
config() materializes the pinned instance (matching what list returns and
what build deploys), including when the pinned instance came from
SupportedInstanceTypes (differs from the config's default). The pinned
instance is preserved through build. Configs published with only
DefaultInstanceType are matched consistently end to end. The build env
merge tolerates a config that publishes an explicit null Environment.
Config discovery (recipe-level with a top-level HostingConfigs fallback)
is centralized in _extract_hosting_configs_from_hub() and used by BOTH
the selection API and the build path, so a top-level config that is
listable/selectable is also applied at build. Nova models are routed to
their dedicated build path first (per-tier SMI validation + Nova env
precedence), so the top-level fallback never diverts them. An explicit
selection stores a deep copy of the raw config, is applied exactly at
build (or raises if no longer published), and returned configs are copied
so caller mutation cannot corrupt internal state.
This is the SDK half of a paired change; the SageMaker agent
model-deployment skill consumes this unified API. Internal CR:
https://code.amazon.com/reviews/CR-289903643
@Lokiiiiii
Lokiiiiiiforce-pushed the select-recipe-hosting-config-by-instance-type branch from 4a55e6f to ed67e3dCompareJuly 17, 2026 22:01
@jam-jee

Copy link
Copy Markdown
Collaborator

Verified the fortress scan results are not directly relevant to the changes part of this PR.

@jam-jee
jam-jee merged commit 58b31e0 into aws:masterJul 22, 2026
21 of 40 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Jul 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Lokiiiiii@jam-jee