Amazon SageMaker AI получил OpenAI-compatible API для конечных точек реального времени
Сегодня Amazon SageMaker AI добавляет поддержку OpenAI-compatible API для конечных точек инференса в реальном времени. Если вы используете OpenAI SDK, LangChain или Strands Agents, теперь можно вызывать модели в SageMaker AI, изменив только URL конечной точки. Не нужен собственный клиент, обертка SigV4 или переписывание кода.
Обзор
С этим запуском конечные точки SageMaker AI открывают путь /openai/v1, который принимает запросы Chat Completions и возвращает ответы как есть из контейнера, включая потоковую передачу. OpenAI endpoints включены для всех конечных точек и inference components с использованием стандартных API и SDK SageMaker AI.
SageMaker AI маршрутизирует запросы по имени конечной точки в URL, поэтому любой OpenAI-compatible клиент работает сразу после подключения. Теперь для конечных точек можно создавать bearer token с ограниченным сроком действия и использовать их с OpenAI-клиентами.
Рабочий пример с развертыванием и вызовом приведен в сопровождающем notebook на GitHub.
«Мы запускаем AI coding agents, которые используют нескольких провайдеров LLM через gateway для LLM (Bifrost), говорящий на протоколе OpenAI chat completions. Возможность bearer token позволяет добавить SageMaker как заменяющую OpenAI-compatible inference endpoint — без собственного SigV4 signing — так что все работает нативно с нашим gateway, Vercel AI SDK и стандартными клиентами OpenAI», — говорит Giorgio Piatti (AI/ML Engineer — Caffeine.AI).
Сценарии использования
Agentic workflows на собственной инфраструктуре
Если вы строите многошаговых AI-агентов с помощью таких фреймворков, как Strands Agents или LangChain, теперь можно запускать эти процессы полностью на своих конечных точках SageMaker AI. Ваши агенты вызывают модели через тот же OpenAI-compatible интерфейс, под который они были построены, но инференс выполняется на выделенных GPU-инстансах в вашем аккаунте.
Хостинг нескольких моделей через единый интерфейс
Если вы запускаете несколько моделей — например, Llama для общих задач, дообученный Mistral для предметной области и более маленькую модель для классификации, — их можно разместить на одной конечной точке SageMaker AI с помощью inference components. Каждая модель получает собственное распределение ресурсов, и к каждой можно обращаться через один и тот же OpenAI SDK. Не нужны отдельные API-клиенты или логика маршрутизации в коде приложения.
Обслуживание дообученных моделей без изменения кода
Если вы дообучаете open source модели под свой сценарий, их можно развернуть в SageMaker AI и вызывать через тот же OpenAI-compatible интерфейс, который уже используют ваши приложения. Единственное изменение — URL конечной точки. Остальная часть приложения — вызовы SDK, потоковая логика, форматирование промптов — остается прежней.
Обзор решения
В этой статье рассматриваются следующие темы:
- Как работает аутентификация по bearer token с конечными точками SageMaker AI.
- Развертывание и вызов одно-модельной конечной точки.
- Развертывание и вызов inference components для многомодельных развертываний.
- Интеграция с фреймворком Strands Agents.
Требования
Чтобы повторить этот walkthrough, вам понадобятся:
- Аккаунт AWS с правами на создание конечных точек SageMaker AI.
- SageMaker Python SDK (
pip install sagemaker). - OpenAI Python SDK (
pip install openai). - Модель, хранящаяся в Amazon Simple Storage Service (Amazon S3). Например, Qwen3-4B, загруженная с Hugging Face.
- Роль исполнения AWS Identity and Access Management (IAM) для создания конечных точек с политикой
AmazonSageMakerFullAccess. - Роль исполнения IAM с разрешениями
sagemaker:CallWithBearerTokenиsagemaker:InvokeEndpointдля вызова конечной точки.
Аутентификация с помощью bearer token
OpenAI-compatible конечные точки SageMaker AI используют аутентификацию по bearer token. SageMaker Python SDK включает генератор токенов, который создает временные токены со сроком действия до 12 часов на основе ваших существующих учетных данных AWS. Дополнительные секреты или 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))
Генератор токенов использует любые учетные данные AWS, доступные в вашей среде: учетные данные IAM user, instance profile на Amazon Elastic Compute Cloud (Amazon EC2) или сессию AWS IAM Identity Center (SSO).
Функция generate_token создает временный bearer token для аутентификации с API SageMaker. По умолчанию токены действуют 12 часов, но это можно изменить через параметр expiry, передав значение timedelta в диапазоне от 1 секунды до 12 часов. Функция принимает регион, необязательный aws_credentials_provider и длительность действия. Если регион AWS не указан, используется переменная окружения AWS_REGION. Если provider учетных данных не задан, они определяются через цепочку учетных данных AWS по умолчанию, которая ищет данные в нескольких источниках, включая переменные окружения, ~/.aws/credentials, ~/.aws/config, container credentials и instance profiles. Полный порядок разрешения см. в документации 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"))
Разрешения 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": "*"
}
]
}
В качестве лучшей практики всегда ограничивайте Resource конкретными ARN конечных точек для InvokeEndpoint, а не используйте wildcard. Bearer token, созданный этой ролью, наследует тот же уровень доступа, поэтому узко ограниченная политика уменьшает радиус поражения, если токен случайно станет доступен посторонним. Обратите внимание, что для CallWithBearerToken поле Resource должно быть wildcard ("*"). Ограничения на уровне ресурса оно не поддерживает.
Как работает токен
Bearer token представляет собой base64-encoded SigV4 pre-signed URL. Когда вы вызываете generate_token, SageMaker AI SDK формирует запрос к сервису SageMaker AI для действия CallWithBearerToken, локально подписывает его с использованием ваших учетных данных AWS и кодирует получившийся signed URL в портативную строку токена. Во время генерации токена сетевой вызов не выполняется. Подпись создается полностью на стороне клиента. Когда вы предъявляете этот токен конечной точке SageMaker AI, сервис декодирует его, проверяет SigV4 signature, убеждается, что срок действия токена не истек, и подтверждает, что исходная IAM-сущность имеет необходимые разрешения. Эффективный срок жизни токена равен меньшему из значения expiry и оставшегося срока действия учетных данных AWS, использованных для подписи.
Лучшая практика безопасности: Bearer token несет ту же авторизацию, что и базовые учетные данные AWS, с помощью которых он был создан. Обращайтесь с токенами так же осторожно, как с учетными данными. Ограничьте IAM-роль, используемую для генерации токенов, минимально необходимыми разрешениями, а именно sagemaker:InvokeEndpoint и sagemaker:CallWithBearerToken только на тех ARN конечных точек, к которым нужен доступ вызывающему. Не генерируйте токены из ролей с чрезмерными правами, например с политиками AdministratorAccess или SageMakerFullAccess.
Не храните токены на диске, в переменных окружения, в файлах конфигурации, базах данных или распределенных кэшем. Не логируйте токены и передавайте их только по защищенным протоколам связи, таким как HTTPS. Генерация токена — локальная операция без сетевых накладных расходов, поэтому рекомендуется создавать свежий токен в момент использования или применять показанный выше паттерн httpx.Auth с автообновлением. Это снижает риск утечки токена и помогает использовать токен с максимальным оставшимся сроком действия. В качестве лучшей практики задавайте срок жизни токена как можно короче, но не короче, чем требуется вашей нагрузке.
Развертывание одно-модельной конечной точки
Одно-модельная конечная точка размещает одну модель и обслуживает запросы напрямую. В следующем примере Qwen3-4B развертывается с использованием SageMaker AI vLLM Deep Learning Container на инстансе ml.g6.2xlarge.
Примечание: конечные точки 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 configuration
REGION = "us-west-2"
# Automatically resolve account ID and default SageMaker execution role
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 Model ID
MODEL_HF_ID = "Qwen/Qwen3-4B"
# SageMaker vLLM Deep Learning Container
VLLM_IMAGE = f"763104351884.dkr.ecr.{REGION}.amazonaws.com/vllm:0.20.2-gpu-py312-cu130-ubuntu22.04-sagemaker"
# Instance type (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}")
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 suffix: {TIMESTAMP}")
print(f"Model: {SME_MODEL_NAME}")
print(f"Endpoint config: {SME_ENDPOINT_CONFIG_NAME}")
print(f"Endpoint: {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"Model created: {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"Endpoint configuration created: {SME_ENDPOINT_CONFIG_NAME}")
sagemaker_client.create_endpoint(
EndpointName=SME_ENDPOINT_NAME,
EndpointConfigName=SME_ENDPOINT_CONFIG_NAME,
)
print(f"Endpoint creation initiated: {SME_ENDPOINT_NAME}")
print("Waiting for endpoint to reach InService status (this takes 5-10 minutes)...")
waiter = sagemaker_client.get_waiter("endpoint_in_service")
waiter.wait(
EndpointName=SME_ENDPOINT_NAME,
WaiterConfig={"Delay": 30, "MaxAttempts": 40},
)
print(f"Endpoint is InService: {SME_ENDPOINT_NAME}")
Конечная точка переходит в состояние InService через несколько минут. Когда она готова, она обслуживает как стандартный путь SageMaker AI /invocations, так и OpenAI-compatible путь /openai/v1/chat/completions.
Вызов одно-модельной конечной точки
Когда конечная точка работает, вызовите ее с помощью OpenAI Python SDK. Base URL имеет такой формат:
https://runtime.sagemaker.<REGION>.amazonaws.com/endpoints/<ENDPOINT_NAME>/openai/v1
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"Base 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()
Поле model передается в контейнер как есть. Поскольку SageMaker AI маршрутизирует запросы по имени конечной точки в URL, это поле можно оставить пустым или задать его так, чтобы оно совпадало с именем модели, которое ожидает контейнер.
Развертывание конечной точки с inference component
С помощью inference components можно разместить несколько моделей на одной конечной точке, каждая с выделенным распределением вычислительных ресурсов. В этом случае модель связывается с компонентом, а не с конфигурацией конечной точки:
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"Model: {IC_MODEL_NAME}")
print(f"Endpoint config: {IC_ENDPOINT_CONFIG_NAME}")
print(f"Endpoint: {IC_ENDPOINT_NAME}")
print(f"Inference comp: {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"Model created: {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"Endpoint configuration created: {IC_ENDPOINT_CONFIG_NAME}")
sagemaker_client.create_endpoint(
EndpointName=IC_ENDPOINT_NAME,
EndpointConfigName=IC_ENDPOINT_CONFIG_NAME,
)
print(f"Endpoint creation initiated: {IC_ENDPOINT_NAME}")
print("Waiting for endpoint to reach InService status (this takes 5-10 minutes)...")
waiter = sagemaker_client.get_waiter("endpoint_in_service")
waiter.wait(
EndpointName=IC_ENDPOINT_NAME,
WaiterConfig={"Delay": 30, "MaxAttempts": 40},
)
print(f"Endpoint is 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"Inference component creation initiated: {IC_NAME}")
print("Waiting for inference component to reach InService status...")
while True:
desc = sagemaker_client.describe_inference_component(InferenceComponentName=IC_NAME)
status = desc["InferenceComponentStatus"]
if status == "InService":
print(f"Inference component is InService: {IC_NAME}")
break
elif status == "Failed":
raise RuntimeError(f"Inference component failed: {desc.get('FailureReason', 'unknown')}")
time.sleep(30)
На той же конечной точке можно создавать дополнительные inference components, чтобы размещать несколько моделей с независимым масштабированием и распределением ресурсов.
Вызов inference components
Чтобы вызвать конкретный inference component, укажите его имя в пути URL:
https://runtime.sagemaker.<REGION>.amazonaws.com/endpoints/<ENDPOINT>/inference-components/<IC_NAME>/openai/v1
Следующий пример показывает два inference components на общей конечной точке, каждый из которых вызывается отдельным OpenAI client, использующим общий пул соединений:
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")
Общий httpx.Client позволяет обоим экземплярам OpenAI client переиспользовать одни и те же TLS-сессии и connection pool.
Интеграция со Strands Agents
Strands Agents — это open source SDK для создания AI-агентов. Поскольку Strands Agents поддерживает OpenAI-compatible поставщиков моделей, теперь можно запускать многоагентные рабочие процессы полностью на собственной инфраструктуре SageMaker AI. Это дает гибкость agentic-приложений при контроле, который обеспечивают выделенные конечные точки. Ваши данные не покидают ваш аккаунт, а вы сами выбираете, какая именно версия модели будет работать у ваших агентов.
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],
)
Очистка ресурсов
Чтобы избежать постоянных расходов, удалите конечные точки и связанные ресурсы, когда закончите работу. Конечные точки 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>")
Заключение
С поддержкой OpenAI-compatible API Amazon SageMaker AI убирает барьер интеграции между тем, где сейчас находятся большинство AI-приложений, и инфраструктурой, нужной им для масштабирования. Вы можете сохранить существующий код, использовать любой OpenAI-compatible framework и запускать инференс на выделенных конечных точках с тем уровнем контроля над GPU, масштабированием и размещением данных, который вам нужен. Чтобы начать, разверните модель на real-time endpoint SageMaker AI с помощью поддерживаемого контейнера, установите SageMaker Python SDK и укажите URL конечной точки в вашем OpenAI client. Подробнее см. раздел Use SageMaker AI with OpenAI-compatible APIs в руководстве Amazon SageMaker AI Developer Guide или откройте консоль Amazon SageMaker AI, чтобы создать первую конечную точку.
Материал — перевод статьи с английского.
Оригинал: Announcing OpenAI-compatible API support for Amazon SageMaker AI endpoints