宣布 Amazon SageMaker AI 端点支持 OpenAI 兼容 API

TL;DR · AI 摘要
AWS SageMaker AI 现已支持 OpenAI 兼容的 API 接口,用户只需更改端点 URL 即可通过 OpenAI SDK、LangChain 或 Strands Agents 调用 SageMaker 上的模型,无需自定义客户端或代码重写。
核心要点
- SageMaker AI 端点现在提供 /openai/v1 路径,支持 Chat Completions 请求和流式响应,Bearer Token 有效期最长
- 新功能支持多模型部署,每个模型获得独立资源分配,可通过同一 OpenAI SDK 调用。
- 微调模型部署后无需应用代码修改,只需更改端点 URL 即可调用,保持 SDK 调用和流式逻辑不变。
结构提纲
按章节快速跳转。
- §功能概述
SageMaker AI 引入 OpenAI 兼容的 API 支持,用户无需更改代码,只需修改端点 URL 即可调用模型。
- ·认证方式
使用 Bearer Token 认证,SageMaker Python SDK 可生成有效期最长12小时的令牌,无需额外 API 密钥。
- §应用场景
新功能适用于自托管基础设施上的代理工作流、单一界面的多模型部署以及无需代码更改的微调模型服务。
- §解决方案
文章介绍 Bearer Token 认证、单模型端点部署、多模型部署组件以及与 Strands Agents 框架的集成。
- ·准备工作
需要 AWS 账户权限、SageMaker 和 OpenAI Python SDK、存储在 S3 的模型以及特定的 IAM 执行角色权限。
- ·令牌生成
使用 generate_token 函数生成时间限制的 Bearer Token,利用环境中现有的 AWS 凭证。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- SageMaker AI OpenAI 兼容 API
- 功能概述
- /openai/v1 路径支持
- Bearer Token 认证
- 流式响应
- 应用场景
- 代理工作流
- 多模型部署
- 微调模型服务
金句 / Highlights
值得收藏与分享的关键句。
SageMaker AI 端点现在提供 /openai/v1 路径,支持 Chat Completions 请求和流式响应,Bearer Token 有效期最长12小时。
现在可以为您的端点创建有时间限制的 Bearer Token,并将其与您的 OpenAI 客户端一起使用。
如果您运行多个模型 - 例如,用于普通任务的 Llama,用于特定领域工作的微调 Mistral,以及用于分类的小型模型 - 您可以使用推理组件将所有这些模型托管在单个 SageMaker AI 端点上。
令牌生成器使用您环境中可用的任何 AWS 凭证:IAM 用户凭证、Amazon EC2 上的实例配置文件或 AWS IAM Identity Center (SSO) 会话。
我们通过使用 OpenAI 聊天完成协议的 LLM 网关(Bifrost)运行使用多个 LLM 提供商的 AI 编码代理。Bearer Token 功能使我们能够将 SageMaker 添加为即插即用的 OpenAI 兼容推理端点。
今天,Amazon SageMaker AI 引入了对实时推理端点的 OpenAI 兼容 API 支持。如果您使用 OpenAI SDK、LangChain 或 Strands Agents,现在只需更改您的端点 URL 即可在 SageMaker AI 上调用模型。您不需要自定义客户端、SigV4 包装器或代码重写。
概述
通过此次发布,SageMaker AI 端点暴露了一个 /openai/v1 路径,该路径接受 Chat Completions 请求并直接从容器返回响应,包括流式传输。使用标准的 SageMaker AI API 和 SDK,所有端点和推理组件都已启用 OpenAI 端点。
SageMaker AI 基于 URL 中的端点名称进行路由,因此任何 OpenAI 兼容的客户端都能即插即用。您现在可以为您的端点创建有时间限制的 bearer token,并与您的 OpenAI 客户端一起使用。
有关包含部署和调用的工作示例,请参阅配套的 GitHub 笔记本。
"我们通过使用 OpenAI 聊天完成协议的 LLM 网关 (Bifrost) 运行使用多个 LLM 提供商的 AI 编码代理。Bearer token 功能使我们能够将 SageMaker 作为即插即用的 OpenAI 兼容推理端点添加 — 无需自定义 SigV4 签名 — 因此它可以与我们的网关、Vercel AI SDK 和标准 OpenAI 客户端原生工作。" Giorgio Piatti (AI/ML 工程师 – Caffeine.AI) 表示
用例
在自有基础设施上的代理工作流
如果您使用 Strands Agents 或 LangChain 等框架构建多步骤 AI 代理,现在可以完全在您自己的 SageMaker AI 端点上运行这些工作流。您的代理使用构建时相同的 OpenAI 兼容接口调用模型,但推理在您自己账户中的专用 GPU 实例上运行。
使用单一接口托管多模型
如果您运行多个模型 — 例如,用于通用任务的 Llama、用于特定领域工作的微调 Mistral 以及用于分类的小型模型 — 您可以使用推理组件将所有这些模型托管在单个 SageMaker AI 端点上。每个模型都有自己的资源分配,并且都可以通过相同的 OpenAI SDK 调用。您不需要在应用程序代码中使用单独的 API 客户端或路由逻辑。
无需代码更改即可提供微调模型
如果您为特定用例微调开源模型,可以在 SageMaker AI 上部署它们,并通过应用程序已使用的相同 OpenAI 兼容接口调用它们。唯一的变化是端点 URL。应用程序的其余部分 — SDK 调用、流式逻辑、提示格式化 — 保持不变。
解决方案概述
在本文中,我们将介绍以下内容:
- Bearer token 身份验证如何与 SageMaker AI 端点配合工作。
- 部署和调用单模型端点。
- 部署和调用多模型部署的推理组件。
- 与 Strands Agents 框架的集成。
先决条件
要按照本教程操作,您必须具备以下条件:
- 具有创建 SageMaker AI 端点权限的 AWS 账户。
- SageMaker Python SDK (
pip install sagemaker)。 - OpenAI Python SDK (
pip install openai)。 - 存储在 Amazon Simple Storage Service (Amazon S3) 中的模型。例如,从 Hugging Face 下载的 Qwen3-4B。
- 用于创建端点的 AWS Identity and Access Management (IAM) 执行角色,具有
AmazonSageMakerFullAccess策略。 - 具有调用端点的
sagemaker:CallWithBearerToken和sagemaker:InvokeEndpoint权限的 IAM 执行角色。
使用 Bearer Token 进行身份验证
SageMaker AI OpenAI 兼容端点使用 bearer token 身份验证。SageMaker Python SDK 包含一个令牌生成器,可以从您现有的 AWS 凭证创建有时间限制的令牌(有效期最长为 12 小时)。不需要额外的机密或 API 密钥。
令牌包含您的角色或用户凭证,并且需要 sagemaker:CallWithBearerToken 和 sagemaker:InvokeEndpoint 操作权限。
生成令牌
使用以下 Python 脚本生成令牌。
from sagemaker.core.token_generator import generate_token
from datetime import timedelta
token = generate_token(region="us-west-2", expiry=timedelta(minutes=5))Python
令牌生成器使用您环境中可用的任何 AWS 凭证:IAM 用户凭证、Amazon Elastic Compute Cloud (Amazon EC2) 上的实例配置文件或 AWS IAM Identity Center (SSO) 会话。
generate_token 函数生成一个有时间限制的 bearer token,用于与 SageMaker API 进行身份验证。默认情况下,令牌有效期为 12 小时,但您可以使用 expiry 参数覆盖此设置,使用 timedelta 值,范围在 1 秒到 12 小时之间。该函数接受一个区域、一个可选的 aws_credentials_provider 和过期持续时间。如果没有提供 AWS 区域,它会回退到 AWS_REGION 环境变量。如果没有提供凭证提供程序,它会使用默认的 AWS 凭证链解析凭证,该链搜索多个来源,包括环境变量、~/.aws/credentials、~/.aws/config、容器凭证和实例配置文件。有关完整的解析顺序,请参阅 Boto3 凭证文档。
为长时间运行的应用程序自动刷新令牌
对于连续运行的应用程序,您可以使用 httpx 实现自动刷新模式,以便在每个请求上生成新的令牌:
import httpx
from sagemaker.core.token_generator import generate_token
class SageMakerAuth(httpx.Auth):
def __init__(self, region: str):
self.region = region
def auth_flow(self, request):
request.headers["Authorization"] = f"Bearer {generate_token(region=self.region)}"
yield request
http_client = httpx.Client(auth=SageMakerAuth(region="us-west-2"))Python
IAM 权限
调用终端节点的 IAM 角色或用户需要以下权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sagemaker:InvokeEndpoint",
"Resource": "arn:aws:sagemaker:<REGION>:<ACCOUNT_ID>:endpoint/<ENDPOINT_NAME>"
},
{
"Effect": "Allow",
"Action": "sagemaker:CallWithBearerToken",
"Resource": "*"
}
]
}JSON
作为最佳实践,对于 InvokeEndpoint,始终将 Resource 限制为特定的终端节点 ARN,而不是使用通配符。从此角色生成的承载令牌具有相同的访问级别,因此范围受限的策略可以限制令牌意外暴露时的影响范围。请注意,CallWithBearerToken 要求 Resource 字段使用通配符 ("*")。它不支持资源级别的限制。
令牌工作原理
承载令牌是一个 base64 编码的 SigV4 预签名 URL。当您调用 generate_token 时,SageMaker AI SDK 会向 SageMaker AI 服务构造一个 CallWithBearerToken 操作的请求,使用您的 AWS 凭证在本地对其进行签名,并将结果签名 URL 编码为可移植的令牌字符串。令牌生成期间不会进行网络调用。签名完全在客户端进行。当您向 SageMaker AI 终端节点出示此令牌时,服务会解码它,验证 SigV4 签名,确认令牌未过期,并确认原始 IAM 身份具有所需的权限。令牌的有效生命周期是过期值和用于签名的 AWS 凭证的剩余有效期中较短的一个。
安全最佳实践: 承载令牌携带与用于生成它的底层 AWS 凭证相同的授权。像对待凭证一样小心处理令牌。将用于令牌生成的 IAM 角色范围限定为所需的最低权限,特别是仅在调用者需要访问的终端节点 ARN 上设置 sagemaker:InvokeEndpoint 和 sagemaker:CallWithBearerToken。不要从具有广泛权限的角色生成令牌,例如由 AdministratorAccess 或 SageMakerFullAccess 管理策略授予的角色。
不要将令牌存储在磁盘、环境变量、配置文件、数据库或分布式缓存中。不要记录令牌,并且仅通过 HTTPS 等加密通信协议传输它们。令牌生成是本地操作,没有网络开销,因此推荐的做法是在使用点生成新令牌或使用前面示例中显示的自动刷新 httpx.Auth 模式。这避免了令牌泄露的风险,并帮助您使用具有最大剩余有效期的令牌。作为最佳实践,将令牌过期时间设置为您工作负载所需的最短持续时间。
部署单模型终端节点
单模型终端节点托管一个模型并直接处理请求。以下示例使用 SageMaker AI vLLM 深度学习容器在 ml.g6.2xlarge 实例上部署 Qwen3-4B。
注意:无论流量如何,SageMaker AI 终端节点在服务期间都会产生费用。有关更多详细信息,请参阅 Amazon SageMaker AI 定价页面。
import boto3
import sagemaker
import time
from sagemaker.core.helper.session_helper import Session
from sagemaker.core.helper.session_helper import get_execution_role
# AWS 配置
REGION = "us-west-2"
# 自动解析账户 ID 和默认 SageMaker 执行角色
session = Session(boto_session=boto3.Session(region_name=REGION))
ACCOUNT_ID = boto3.client("sts", region_name=REGION).get_caller_identity()["Account"]
EXECUTION_ROLE = get_execution_role(sagemaker_session=session)
# HF 模型 ID
MODEL_HF_ID = "Qwen/Qwen3-4B"
# SageMaker vLLM 深度学习容器
VLLM_IMAGE = f"763104351884.dkr.ecr.{REGION}.amazonaws.com/vllm:0.20.2-gpu-py312-cu130-ubuntu22.04-sagemaker"
# 实例类型 (1x NVIDIA L4 GPU)
INSTANCE_TYPE = "ml.g6.2xlarge"
sagemaker_client = boto3.client("sagemaker", region_name=REGION)
print(f"Region: {REGION}")
print(f"Account ID: {ACCOUNT_ID}")
print(f"Execution role: {EXECUTION_ROLE}")
print(f"Model HF ID: {MODEL_HF_ID}")Python
import time
TIMESTAMP = str(int(time.time()))
SME_MODEL_NAME = f"openai-compat-sme-model-{TIMESTAMP}"
SME_ENDPOINT_CONFIG_NAME = f"openai-compat-sme-epc-{TIMESTAMP}"
SME_ENDPOINT_NAME = f"openai-compat-sme-ep-{TIMESTAMP}"
print(f"时间戳后缀: {TIMESTAMP}")
print(f"模型: {SME_MODEL_NAME}")
print(f"终端节点配置: {SME_ENDPOINT_CONFIG_NAME}")
print(f"终端节点: {SME_ENDPOINT_NAME}")
sagemaker_client.create_model(
ModelName=SME_MODEL_NAME,
ExecutionRoleArn=EXECUTION_ROLE,
PrimaryContainer={
"Image": VLLM_IMAGE,
"Environment": {
"HF_MODEL_ID": MODEL_HF_ID,
"SM_VLLM_TENSOR_PARALLEL_SIZE": "1",
"SM_VLLM_MAX_NUM_SEQS": "4",
"SM_VLLM_ENABLE_AUTO_TOOL_CHOICE": "true",
"SM_VLLM_TOOL_CALL_PARSER": "hermes",
"SAGEMAKER_ENABLE_LOAD_AWARE": "1",
},
},
)
print(f"已创建模型: {SME_MODEL_NAME}")
sagemaker_client.create_endpoint_config(
EndpointConfigName=SME_ENDPOINT_CONFIG_NAME,
ProductionVariants=[
{
"VariantName": "variant1",
"ModelName": SME_MODEL_NAME,
"InstanceType": INSTANCE_TYPE,
"InitialInstanceCount": 1,
}
],
)
print(f"已创建终端节点配置: {SME_ENDPOINT_CONFIG_NAME}")sagemaker_client.create_endpoint(
EndpointName=SME_ENDPOINT_NAME,
EndpointConfigName=SME_ENDPOINT_CONFIG_NAME,
)
print(f"端点创建已启动: {SME_ENDPOINT_NAME}")
print("等待端点达到 InService 状态(这需要 5-10 分钟)...")
waiter = sagemaker_client.get_waiter("endpoint_in_service")
waiter.wait(
EndpointName=SME_ENDPOINT_NAME,
WaiterConfig={"Delay": 30, "MaxAttempts": 40},
)
print(f"端点处于 InService 状态: {SME_ENDPOINT_NAME}")Python
端点将在几分钟内转换为 InService 状态。当准备就绪后,它将同时提供标准的 SageMaker AI /invocations 路径和位于 /openai/v1/chat/completions 的 OpenAI 兼容路径。
调用单模型端点
端点服务启动后,使用 OpenAI Python SDK 调用它。基础 URL 遵循以下格式:
https://runtime.sagemaker.<REGION>.amazonaws.com/endpoints/<ENDPOINT_NAME>/openai/v1
Plain text
from openai import OpenAI
from sagemaker.core.token_generator import generate_token
REGION = "us-west-2"
sme_base_url = f"https://runtime.sagemaker.{REGION}.amazonaws.com/endpoints/{SME_ENDPOINT_NAME}/openai/v1"
client = OpenAI(
base_url=sme_base_url,
api_key=generate_token(region=REGION)
)
print(f"基础 URL: {sme_base_url}")
stream = client.chat.completions.create(
model="",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain how transformers work in machine learning, in three sentences."},
],
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
print()Python
model 字段会传递到容器中。由于 SageMaker AI 基于 URL 中的端点名称路由请求,因此您可以保持此字段为空或将其设置为与您的容器期望的模型名称匹配。
部署推理组件端点
使用推理组件,您可以在单个端点上托管多个模型,每个模型都有专用的计算资源分配。使用推理组件时,模型与组件关联,而不是与端点配置关联:
IC_MODEL_NAME = f"openai-compat-ic-model-{TIMESTAMP}"
IC_ENDPOINT_CONFIG_NAME = f"openai-compat-ic-epc-{TIMESTAMP}"
IC_ENDPOINT_NAME = f"openai-compat-ic-ep-{TIMESTAMP}"
IC_NAME = f"openai-compat-ic-qwen3-4b-{TIMESTAMP}"
print(f"模型: {IC_MODEL_NAME}")
print(f"端点配置: {IC_ENDPOINT_CONFIG_NAME}")
print(f"端点: {IC_ENDPOINT_NAME}")
print(f"推理组件: {IC_NAME}")
sagemaker_client.create_model(
ModelName=IC_MODEL_NAME,
ExecutionRoleArn=EXECUTION_ROLE,
PrimaryContainer={
"Image": VLLM_IMAGE,
"Environment": {
"HF_MODEL_ID": MODEL_HF_ID,
"SM_VLLM_TENSOR_PARALLEL_SIZE": "1",
"SM_VLLM_MAX_NUM_SEQS": "4",
"SM_VLLM_ENABLE_AUTO_TOOL_CHOICE": "true",
"SM_VLLM_TOOL_CALL_PARSER": "hermes",
"SAGEMAKER_ENABLE_LOAD_AWARE": "1",
},
},
)
print(f"模型已创建: {IC_MODEL_NAME}")
sagemaker_client.create_endpoint_config(
EndpointConfigName=IC_ENDPOINT_CONFIG_NAME,
ExecutionRoleArn=EXECUTION_ROLE,
ProductionVariants=[
{
"VariantName": "variant1",
"InstanceType": INSTANCE_TYPE,
"InitialInstanceCount": 1,
}
],
)
print(f"端点配置已创建: {IC_ENDPOINT_CONFIG_NAME}")
sagemaker_client.create_endpoint(
EndpointName=IC_ENDPOINT_NAME,
EndpointConfigName=IC_ENDPOINT_CONFIG_NAME,
)
print(f"端点创建已启动: {IC_ENDPOINT_NAME}")
print("等待端点达到 InService 状态(这需要 5-10 分钟)...")
waiter = sagemaker_client.get_waiter("endpoint_in_service")
waiter.wait(
EndpointName=IC_ENDPOINT_NAME,
WaiterConfig={"Delay": 30, "MaxAttempts": 40},
)
print(f"端点处于 InService 状态: {IC_ENDPOINT_NAME}")
sagemaker_client.create_inference_component(
InferenceComponentName=IC_NAME,
EndpointName=IC_ENDPOINT_NAME,
VariantName="variant1",
Specification={
"ModelName": IC_MODEL_NAME,
"ComputeResourceRequirements": {
"MinMemoryRequiredInMb": 1024,
"NumberOfCpuCoresRequired": 2,
"NumberOfAcceleratorDevicesRequired": 1,
},
},
RuntimeConfig={"CopyCount": 1},
)
print(f"推理组件创建已启动: {IC_NAME}")
print("等待推理组件达到 InService 状态...")
while True:
desc = sagemaker_client.describe_inference_component(InferenceComponentName=IC_NAME)
status = desc["InferenceComponentStatus"]
if status == "InService":
print(f"推理组件处于 InService 状态: {IC_NAME}")
break
elif status == "Failed":
raise RuntimeError(f"推理组件失败: {desc.get('FailureReason', 'unknown')}")
time.sleep(30)Python
您可以在同一端点上创建额外的推理组件,以托管具有独立扩展和资源分配的多个模型。
调用推理组件
要调用特定的推理组件,请在 URL 路径中包含其名称:
https://runtime.sagemaker.<REGION>.amazonaws.com/endpoints/<ENDPOINT>/inference-components/<IC_NAME>/openai/v1
Plain text
以下示例显示了一个共享端点上的两个推理组件,每个推理组件由一个共享连接池的独立 OpenAI 客户端定向:
import httpx
from openai import OpenAI
from sagemaker.core.token_generator import generate_token
shared_http = httpx.Client()
client_a = OpenAI(
base_url=(
f"https://runtime.sagemaker.{REGION}.amazonaws.com"
f"/endpoints/{IC_ENDPOINT_NAME}/inference-components/{IC_NAME}/openai/v1"
),
api_key=generate_token(region=REGION),
http_client=shared_http,
)response = client_a.chat.completions.create(
model="",
messages=[{"role": "user", "content": "What is 42 * 3? Reply with the number."}],
)
print(f"Response: {response.choices[0].message.content}")
print(f"Connection pool active: shared_http is reusable across multiple IC clients")Python
共享的 httpx.Client 允许两个 OpenAI 客户端实例重用相同的 TLS 会话和连接池。
与 Strands Agents 集成
Strands Agents 是一个用于构建 AI 智能体的开源 SDK。由于 Strands Agents 支持 OpenAI 兼容的模型提供商,您现在可以完全在自己的 SageMaker AI 基础设施上运行多智能体工作流。这为您提供了智能体应用程序的灵活性以及专用端点的控制权。您的数据永远不会离开您的账户,并且您可以精确选择智能体运行的模型版本。
from openai import AsyncOpenAI
from strands import Agent, tool
from strands.models.openai import OpenAIModel
from sagemaker.core.token_generator import generate_token
@tool
def calculator(expression: str) -> str:
"""Evaluate a math expression."""
return str(eval(expression))
strands_client = AsyncOpenAI(
base_url=f"https://runtime.sagemaker.{REGION}.amazonaws.com/endpoints/{SME_ENDPOINT_NAME}/openai/v1",
api_key=generate_token(region=REGION),
)
model = OpenAIModel(client=strands_client, model_id="", params={"temperature": 0.7})
coder = Agent(
model=model,
system_prompt=(
"You are an expert Python developer. Write clean, well-documented "
"Python code with type hints. Output ONLY the code, no explanation."
),
tools=[calculator],
)
reviewer = Agent(
model=model,
system_prompt=(
"You are a senior code reviewer. Review Python code for correctness, "
"performance, and PEP 8 style. Give a concise review with specific suggestions."
),
tools=[calculator],
)Python
清理
为避免持续产生费用,请在完成后删除您的端点及相关资源。SageMaker AI 端点在服务期间会产生费用,无论它们是否接收流量。
import boto3
sagemaker_client = boto3.client("sagemaker", region_name="us-west-2")
sagemaker_client.delete_inference_component(InferenceComponentName="<IC_NAME>")
sagemaker_client.delete_endpoint(EndpointName="<ENDPOINT_NAME>")
sagemaker_client.delete_endpoint_config(EndpointConfigName="<ENDPOINT_CONFIG_NAME>")
sagemaker_client.delete_model(ModelName="<MODEL_NAME>")Python
结论
借助 OpenAI 兼容的 API 支持,Amazon SageMaker AI 消除了当今大多数 AI 应用程序所在位置与它们需要扩展的基础设施之间的集成障碍。您可以保留现有代码,使用任何 OpenAI 兼容的框架,并在具有所需 GPU、扩展性和数据驻留控制的专用端点上运行推理。要开始使用,请使用支持的容器在 SageMaker AI 实时端点上部署模型,安装 SageMaker Python SDK,并将您的 OpenAI 客户端指向端点 URL。要了解更多信息,请参阅《Amazon SageMaker AI 开发者指南》中的将 SageMaker AI 与 OpenAI 兼容的 API 一起使用,或打开 Amazon SageMaker AI 控制台 创建您的第一个端点。
- * *