

# Conceitos básicos
<a name="nova-sagemaker-inference-getting-started"></a>

Este guia mostra como implantar modelos personalizados do Amazon Nova nos endpoints em tempo real do SageMaker, configurar parâmetros de inferência e invocar seus modelos para testes.

## Pré-requisitos
<a name="nova-sagemaker-inference-prerequisites"></a>

Confira abaixo os pré-requisitos para implantar modelos do Amazon Nova na inferência do SageMaker:
+ Crie uma Conta da AWS: se você ainda não tiver uma, consulte [Criar uma conta da AWS](https://docs.aws.amazon.com//sagemaker/latest/dg/gs-set-up.html#sign-up-for-aws).
+ Permissões necessárias do IAM - certifique-se de que seu usuário ou perfil do IAM tenha as seguintes políticas gerenciadas:
  + `AmazonSageMakerFullAccess`
  + `AmazonS3FullAccess`
+ Versões obrigatórias de SDKs/CLI - as seguintes versões de SDK foram testadas e validadas com modelos do Amazon Nova na inferência do SageMaker:
  + SageMaker Python SDK v3.0.0\+ (`sagemaker>=3.0.0`) para abordagem de API baseada em recursos.
  + Boto3 versão 1.35.0\+ (`boto3>=1.35.0`) para chamadas diretas de API. Os exemplos neste guia usam essa abordagem.
+ Aumento da cota de serviço: solicite um aumento da cota de serviço do Amazon SageMaker para o tipo de instância de ML que você planeja usar para seu endpoint da Inferência do SageMaker (por exemplo, `ml.p5.48xlarge for endpoint usage`). Para obter uma lista dos tipos de instâncias compatíveis, consulte [Modelos e instâncias compatíveis](nova-model-sagemaker-inference.md#nova-sagemaker-inference-supported). Para solicitar um aumento, consulte [Solicitar um aumento de cota](https://docs.aws.amazon.com//servicequotas/latest/userguide/request-quota-increase.html). Para obter mais informações sobre cotas de instâncias do SageMaker, consulte [Endpoints e cotas do SageMaker](https://docs.aws.amazon.com//general/latest/gr/sagemaker.html).

**dica**  
Para fazer uma rápida implantação de ponta a ponta, você pode executar o [notebook Inferência do SageMaker para o Nova Model personalizado](https://github.com/aws-samples/amazon-nova-samples/blob/main/customization/Nova_2.0/05_deployment/Custom-Nova-Model-SageMaker-Inference.ipynb) para implantar um modelo personalizado do Amazon Nova na inferência do SageMaker em um único notebook.

## Etapa 1: configurar as credenciais da AWS
<a name="nova-sagemaker-inference-step1"></a>

Configure suas credenciais da AWS usando um dos seguintes métodos:

**Opção 1: AWS CLI (recomendado)**

```
aws configure
```

Insira o ID da chave de acesso da AWS, a chave secreta e nome da região padrão quando solicitado.

**Opção 2: arquivo de credenciais da AWS**

Crie ou edite `~/.aws/credentials`:

```
[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY
```

**Opção 3: variáveis de ambiente**

```
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
```

**nota**  
Para obter mais informações sobre as credenciais da AWS, consulte [Definições do arquivo de credenciais e configurações](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-files.html).

**Inicializar clientes da AWS**

Crie um script ou caderno Python com o código abaixo para inicializar o AWS SDK e verificar suas credenciais:

```
import boto3

# AWS Configuration - Update these for your environment
REGION = "us-east-1"  # Supported regions: us-east-1, us-west-2
AWS_ACCOUNT_ID = "YOUR_ACCOUNT_ID"  # Replace with your AWS account ID

# Initialize AWS clients using default credential chain
sagemaker = boto3.client('sagemaker', region_name=REGION)
sts = boto3.client('sts')

# Verify credentials
try:
    identity = sts.get_caller_identity()
    print(f"Successfully authenticated to AWS Account: {identity['Account']}")
    
    if identity['Account'] != AWS_ACCOUNT_ID:
        print(f"Warning: Connected to account {identity['Account']}, expected {AWS_ACCOUNT_ID}")

except Exception as e:
    print(f"Failed to authenticate: {e}")
    print("Please verify your credentials are configured correctly.")
```

Se a autenticação tiver êxito, você deverá ver um resultado confirmando o ID da sua conta da AWS.

## Etapa 2: criar um perfil de execução do SageMaker
<a name="nova-sagemaker-inference-step2"></a>

Um perfil de execução do SageMaker é um perfil do IAM que concede ao SageMaker permissões para acessar recursos da AWS em seu nome, como buckets do Amazon S3 para artefatos de modelos e o CloudWatch para registro em log.

**Criação do perfil de execução**

**nota**  
A criação de perfis do IAM requer as permissões `iam:CreateRole` e `iam:AttachRolePolicy`. Antes de continuar, certifique-se de que seu usuário ou perfil do IAM tenha essas permissões.

O código abaixo cria um perfil do IAM com as permissões necessárias para implantar modelos personalizados do Amazon Nova:

```
import json

# Create SageMaker Execution Role
role_name = f"SageMakerInference-ExecutionRole-{AWS_ACCOUNT_ID}"

trust_policy = {
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {"Service": "sagemaker.amazonaws.com"},
            "Action": "sts:AssumeRole"
        }
    ]
}

iam = boto3.client('iam', region_name=REGION)

# Create the role
role_response = iam.create_role(
    RoleName=role_name,
    AssumeRolePolicyDocument=json.dumps(trust_policy),
    Description='SageMaker execution role with S3 and SageMaker access'
)

# Attach required policies
iam.attach_role_policy(
    RoleName=role_name,
    PolicyArn='arn:aws:iam::aws:policy/AmazonSageMakerFullAccess'
)

iam.attach_role_policy(
    RoleName=role_name,
    PolicyArn='arn:aws:iam::aws:policy/AmazonS3FullAccess'
)

SAGEMAKER_EXECUTION_ROLE_ARN = role_response['Role']['Arn']
print(f"Created SageMaker execution role: {SAGEMAKER_EXECUTION_ROLE_ARN}")
```

**Uso de um perfil de execução existente (opcional)**

Se já tiver um perfil de execução do SageMaker, você poderá usá-lo:

```
# Replace with your existing role ARN
SAGEMAKER_EXECUTION_ROLE_ARN = "arn:aws:iam::YOUR_ACCOUNT_ID:role/YOUR_EXISTING_ROLE_NAME"
```

Para encontrar perfis existentes do SageMaker em sua conta:

```
iam = boto3.client('iam', region_name=REGION)
response = iam.list_roles()
sagemaker_roles = [role for role in response['Roles'] if 'SageMaker' in role['RoleName']]
for role in sagemaker_roles:
    print(f"{role['RoleName']}: {role['Arn']}")
```

**Importante**  
O perfil de execução deve ter uma relação de confiança com `sagemaker.amazonaws.com` e permissões para acessar os recursos do Amazon S3 e do SageMaker.

Para obter mais informações sobre perfis de execução do SageMaker, consulte [Perfis do SageMaker](https://docs.aws.amazon.com//sagemaker/latest/dg/sagemaker-roles.html).

## Etapa 3: configurar parâmetros de modelos
<a name="nova-sagemaker-inference-step3"></a>

Configure os parâmetros de implantação para seu modelo do Amazon Nova. Essas configurações controlam o comportamento do modelo, a alocação de recursos e as características de inferência. Para ver uma lista dos tipos de instâncias compatíveis e dos valores de CONTEXT\_LENGTH e MAX\_CONCURRENCY compatíveis para cada um, consulte [Modelos e instâncias compatíveis](nova-model-sagemaker-inference.md#nova-sagemaker-inference-supported). Para obter a lista completa de atributos adicionais do contêiner, como padrões de amostragem, decodificação especulativa e quantização, consulte [Atributos do contêiner de inferência](nova-sagemaker-inference-container-features.md).

**Parâmetros obrigatórios**
+ `IMAGE`: o URI da imagem do contêiner do Docker para o contêiner de inferência do Amazon Nova. Será fornecido pela AWS.
+ `CONTEXT_LENGTH`: tamanho do contexto do modelo.
+ `MAX_CONCURRENCY`: número máximo de sequências por iteração; define o limite de quantas solicitações (prompts) de usuários individuais podem ser processadas simultaneamente em um único lote na GPU. Intervalo: inteiro maior que 0.

**Configure sua implantação**

```
# AWS Configuration
REGION = "us-east-1"  # Must match region from Step 1

# ECR Account mapping by region
ECR_ACCOUNT_MAP = {
    "us-east-1": "708977205387",
    "us-west-2": "176779409107"
}

# Container Image
IMAGE = f"{ECR_ACCOUNT_MAP[REGION]}.dkr.ecr.{REGION}.amazonaws.com/nova-inference-repo:SM-Inference-latest"
print(f"IMAGE = {IMAGE}")

# Required parameters
CONTEXT_LENGTH = "8000"        # Maximum total context length
MAX_CONCURRENCY = "8"          # Maximum concurrent sequences

# Build environment variables for the container
environment = {
    'CONTEXT_LENGTH': CONTEXT_LENGTH,
    'MAX_CONCURRENCY': MAX_CONCURRENCY,
    # Optional: add container feature environment variables here.
    # See "Inference Container Features" for the full list.
    # Examples:
    # 'DEFAULT_TEMPERATURE': '0.7',
    # 'DEFAULT_MAX_NEW_TOKENS': '512',
    # 'QUANTIZATION_DTYPE': 'fp8',
}

print("Environment configuration:")
for key, value in environment.items():
    print(f"  {key}: {value}")
```

**Configurar parâmetros específicos da implantação**

Agora configure os parâmetros específicos para a implantação de modelos do Amazon Nova, incluindo o local dos artefatos do modelo e a seleção do tipo de instância.

**Definir identificador de implantação**

```
# Deployment identifier - use a descriptive name for your use case
JOB_NAME = "my-nova-deployment"
```

**Especificar o local dos artefatos dos modelos**

Forneça o URI do Amazon S3 em que os artefatos treinados dos modelos do Amazon Nova foram armazenados. Deve ser o local da saída da tarefa de treinamento de modelo ou de ajuste fino.

```
# S3 location of your trained Nova model artifacts
# Replace with your model's S3 URI - must end with /
MODEL_S3_LOCATION = "s3://your-bucket-name/path/to/model/artifacts/"
```

**Selecionar a variante do modelo e o tipo de instância**

```
# Configure model variant and instance type
TESTCASE = {
    "model": "micro",              # Options: micro, lite, lite2
    "instance": "ml.g5.12xlarge"   # Refer to "Supported models and instances" section
}

# Generate resource names
INSTANCE_TYPE = TESTCASE["instance"]
MODEL_NAME = JOB_NAME + "-" + TESTCASE["model"] + "-" + INSTANCE_TYPE.replace(".", "-")
ENDPOINT_CONFIG_NAME = MODEL_NAME + "-Config"
ENDPOINT_NAME = MODEL_NAME + "-Endpoint"

print(f"Model Name: {MODEL_NAME}")
print(f"Endpoint Config: {ENDPOINT_CONFIG_NAME}")
print(f"Endpoint Name: {ENDPOINT_NAME}")
```

**Convenções de nomenclatura**

O código gera automaticamente nomes consistentes para os recursos da AWS:
+ Nome do modelo: .: `{JOB_NAME}-{model}-{instance-type}`
+ Configuração de endpoint: `{MODEL_NAME}-Config`
+ Nome do endpoint: `{MODEL_NAME}-Endpoint`

## Etapa 4: criar recursos do SageMaker e implantar o endpoint
<a name="nova-sagemaker-inference-step4"></a>

O SageMaker oferece duas abordagens para implantação de modelos em endpoints de tempo real. Escolha a abordagem adequada para o seu caso de uso:
+ **Componentes de inferência** (recomendado): implanta os modelos como componentes de inferência em um endpoint. Essa abordagem permite hospedar vários modelos em um único endpoint, escalar modelos de modo independente e otimizar a utilização de recursos.
+ **Endpoints de modelo único**: implanta um único modelo diretamente em um endpoint usando um objeto de modelo e uma configuração do endpoint. Essa abordagem é mais simples de ser configurada e é adequada para desenvolvimento, testes ou workloads que exijam apenas um modelo por endpoint.

### Opção A: criar com componentes de inferência
<a name="nova-sagemaker-inference-step4-ic"></a>

Com componentes de inferência, primeiro você cria um endpoint e depois implanta nele o modelo como um componente de inferência. Isso separa o modelo da infraestrutura do endpoint, o que oferece mais flexibilidade.

**Criar a configuração do endpoint**

Crie uma configuração do endpoint que defina a infraestrutura sem especificar um modelo. O tipo e a quantidade de instâncias são gerenciados no nível do endpoint:

```
# Create Endpoint Configuration for inference components
INFERENCE_COMPONENT_NAME = MODEL_NAME + "-IC"

try:
    config_response = sagemaker.create_endpoint_config(
        EndpointConfigName=ENDPOINT_CONFIG_NAME,
        ProductionVariants=[
            {
                'VariantName': 'primary',
                'InstanceType': INSTANCE_TYPE,
                'InitialInstanceCount': 1,
                'RoutingConfig': {
                    'RoutingStrategy': 'LEAST_OUTSTANDING_REQUESTS'
                }
            }
        ],
        Tags=[
            {
                'Key': 'sagemaker:nova-inference-component',
                'Value': 'true'
            }
        ]
    )
    print("Endpoint configuration created successfully!")
    print(f"Config ARN: {config_response['EndpointConfigArn']}")

except sagemaker.exceptions.ClientError as e:
    print(f"Error creating endpoint configuration: {e}")
```

**Criar e implantar o endpoint**

```
import time

try:
    endpoint_response = sagemaker.create_endpoint(
        EndpointName=ENDPOINT_NAME,
        EndpointConfigName=ENDPOINT_CONFIG_NAME
    )
    print("Endpoint creation initiated successfully!")
    print(f"Endpoint ARN: {endpoint_response['EndpointArn']}")
except Exception as e:
    print(f"Error creating endpoint: {e}")

# Wait for endpoint to be InService
print("Waiting for endpoint to be InService...")
print("This typically takes 5-10 minutes...\n")

while True:
    try:
        response = sagemaker.describe_endpoint(EndpointName=ENDPOINT_NAME)
        status = response['EndpointStatus']
        
        if status == 'Creating':
            print(f"⏳ Status: {status} - Provisioning infrastructure...")
        elif status == 'InService':
            print(f"✅ Status: {status}")
            print(f"\nEndpoint '{ENDPOINT_NAME}' is ready.")
            break
        elif status == 'Failed':
            print(f"❌ Status: {status}")
            print(f"Failure Reason: {response.get('FailureReason', 'Unknown')}")
            break
        else:
            print(f"Status: {status}")
    except Exception as e:
        print(f"Error checking endpoint status: {e}")
        break
    
    time.sleep(30)
```

**Criar o componente de inferência**

Quando o endpoint estiver InService, implante o modelo do Amazon Nova como componente de inferência:

```
try:
    ic_response = sagemaker.create_inference_component(
        InferenceComponentName=INFERENCE_COMPONENT_NAME,
        EndpointName=ENDPOINT_NAME,
        VariantName='primary',
        Specification={
            'Container': {
                'Image': IMAGE,
                'ArtifactUrl': MODEL_S3_LOCATION,
                'Environment': environment
            },
            'ComputeResourceRequirements': {
                'NumberOfCpuCoresRequired': 15,
                'NumberOfAcceleratorDevicesRequired': 4,
                'MinMemoryRequiredInMb': 25000
            }
        },
        RuntimeConfig={
            'CopyCount': 1
        }
    )
    print("Inference component creation initiated!")
    print(f"Inference Component ARN: {ic_response['InferenceComponentArn']}")

except sagemaker.exceptions.ClientError as e:
    print(f"Error creating inference component: {e}")
```

Principais parâmetros:
+ `InferenceComponentName`: identificador exclusivo do componente de inferência
+ `EndpointName`: o endpoint no qual o componente será implantado
+ `Image`: URI de imagem de contêiner do Docker para inferência do Amazon Nova
+ `ArtifactUrl`: local do Amazon S3 dos seus artefatos de modelos
+ `Environment`: variáveis de ambiente configuradas na Etapa 3
+ `NumberOfCpuCoresRequired`: número de núcleos de CPU necessários por cópia do modelo
+ `NumberOfAcceleratorDevicesRequired`: número de dispositivos aceleradores (GPUs) necessários por cópia do modelo
+ `MinMemoryRequiredInMb`: memória mínima em MB necessária por cópia do modelo
+ `CopyCount`: número de cópias do modelo a serem implantadas

**Monitorar a implantação de componentes de inferência**

```
# Wait for inference component to be InService
print("Waiting for inference component deployment...")
print("This typically takes 10-20 minutes as the model is loaded...\n")

while True:
    try:
        ic_desc = sagemaker.describe_inference_component(
            InferenceComponentName=INFERENCE_COMPONENT_NAME
        )
        ic_status = ic_desc['InferenceComponentStatus']
        
        if ic_status == 'Creating':
            print(f"⏳ Status: {ic_status} - Loading model artifacts...")
        elif ic_status == 'InService':
            print(f"✅ Status: {ic_status}")
            print(f"\nInference component '{INFERENCE_COMPONENT_NAME}' is ready!")
            break
        elif ic_status == 'Failed':
            print(f"❌ Status: {ic_status}")
            print(f"Failure Reason: {ic_desc.get('FailureReason', 'Unknown')}")
            break
        else:
            print(f"Status: {ic_status}")
    except Exception as e:
        print(f"Error checking inference component status: {e}")
        break
    
    time.sleep(30)
```

**nota**  
Ao invocar o endpoint na etapa 5, você deve incluir o parâmetro `InferenceComponentName`nas chamadas de invocação. Veja mais detalhes na etapa 5.

### Opção B: criar com endpoints de modelo único
<a name="nova-sagemaker-inference-step4-single"></a>

Com endpoints de modelo único, você cria um objeto de modelo do SageMaker, uma configuração do endpoint e depois implanta o endpoint. Essa abordagem empacota o modelo diretamente na configuração do endpoint.

**Criar o modelo do SageMaker**

O código abaixo cria um modelo do SageMaker que faz referência aos artefatos do seu modelo do Amazon Nova:

```
try:
    model_response = sagemaker.create_model(
        ModelName=MODEL_NAME,
        PrimaryContainer={
            'Image': IMAGE,
            'ModelDataSource': {
                'S3DataSource': {
                    'S3Uri': MODEL_S3_LOCATION,
                    'S3DataType': 'S3Prefix',
                    'CompressionType': 'None'
                }
            },
            'Environment': environment
        },
        ExecutionRoleArn=SAGEMAKER_EXECUTION_ROLE_ARN,
        EnableNetworkIsolation=True
    )
    print("Model created successfully!")
    print(f"Model ARN: {model_response['ModelArn']}")
    
except sagemaker.exceptions.ClientError as e:
    print(f"Error creating model: {e}")
```

Principais parâmetros:
+ `ModelName`: identificador exclusivo do seu modelo
+ `Image`: URI de imagem de contêiner do Docker para inferência do Amazon Nova
+ `ModelDataSource`: local do Amazon S3 dos seus artefatos de modelos
+ `Environment`: variáveis de ambiente configuradas na Etapa 3
+ `ExecutionRoleArn`: perfil do IAM da Etapa 2
+ `EnableNetworkIsolation`: defina como True para aumentar a segurança (impede que o contêiner faça chamadas de rede de saída)

**Criar a configuração do endpoint**

Em seguida, crie uma configuração do endpoint que defina sua infraestrutura de implantação:

```
# Create Endpoint Configuration
try:
    production_variant = {
        'VariantName': 'primary',
        'ModelName': MODEL_NAME,
        'InitialInstanceCount': 1,
        'InstanceType': INSTANCE_TYPE,
    }
    
    config_response = sagemaker.create_endpoint_config(
        EndpointConfigName=ENDPOINT_CONFIG_NAME,
        ProductionVariants=[production_variant]
    )
    print("Endpoint configuration created successfully!")
    print(f"Config ARN: {config_response['EndpointConfigArn']}")
    
except sagemaker.exceptions.ClientError as e:
    print(f"Error creating endpoint configuration: {e}")
```

Principais parâmetros:
+ `VariantName`: identificador para essa variante de modelo (use “primary” para implantações de modelo único)
+ `ModelName`: faz referência ao modelo criado acima
+ `InitialInstanceCount`: número de instâncias a serem implantadas (comece com 1 e escale posteriormente, se necessário)
+ `InstanceType`: tipo de instância de ML selecionado na Etapa 3

**Implementar o endpoint**

```
import time

try:
    endpoint_response = sagemaker.create_endpoint(
        EndpointName=ENDPOINT_NAME,
        EndpointConfigName=ENDPOINT_CONFIG_NAME
    )
    print("Endpoint creation initiated successfully!")
    print(f"Endpoint ARN: {endpoint_response['EndpointArn']}")
except Exception as e:
    print(f"Error creating endpoint: {e}")
```

**Monitorar a criação do endpoint**

O código abaixo pesquisa o status do endpoint até a conclusão da implantação:

```
# Monitor endpoint creation progress
print("Waiting for endpoint creation to complete...")
print("This typically takes 15-30 minutes...\n")

while True:
    try:
        response = sagemaker.describe_endpoint(EndpointName=ENDPOINT_NAME)
        status = response['EndpointStatus']
        
        if status == 'Creating':
            print(f"⏳ Status: {status} - Provisioning infrastructure and loading model...")
        elif status == 'InService':
            print(f"✅ Status: {status}")
            print("\nEndpoint creation completed successfully!")
            print(f"Endpoint Name: {ENDPOINT_NAME}")
            print(f"Endpoint ARN: {response['EndpointArn']}")
            break
        elif status == 'Failed':
            print(f"❌ Status: {status}")
            print(f"Failure Reason: {response.get('FailureReason', 'Unknown')}")
            print("\nFull response:")
            print(response)
            break
        else:
            print(f"Status: {status}")
        
    except Exception as e:
        print(f"Error checking endpoint status: {e}")
        break
    
    time.sleep(30)  # Check every 30 seconds
```

**Verificar a criação de recursos**

Você pode verificar se os recursos foram criados com êxito:

```
# Describe the model
model_info = sagemaker.describe_model(ModelName=MODEL_NAME)
print(f"Model Status: {model_info['ModelName']} created")

# Describe the endpoint configuration
config_info = sagemaker.describe_endpoint_config(EndpointConfigName=ENDPOINT_CONFIG_NAME)
print(f"Endpoint Config Status: {config_info['EndpointConfigName']} created")
```

**Verificar se o endpoint está pronto**

Independentemente da abordagem escolhida, você pode verificar a configuração do endpoint:

```
# Get detailed endpoint information
endpoint_info = sagemaker.describe_endpoint(EndpointName=ENDPOINT_NAME)

print("\n=== Endpoint Details ===")
print(f"Endpoint Name: {endpoint_info['EndpointName']}")
print(f"Endpoint ARN: {endpoint_info['EndpointArn']}")
print(f"Status: {endpoint_info['EndpointStatus']}")
print(f"Creation Time: {endpoint_info['CreationTime']}")
print(f"Last Modified: {endpoint_info['LastModifiedTime']}")

# Get endpoint config for instance type details
endpoint_config_name = endpoint_info['EndpointConfigName']
endpoint_config = sagemaker.describe_endpoint_config(EndpointConfigName=endpoint_config_name)

# Display production variant details
for variant in endpoint_info['ProductionVariants']:
    print(f"\nProduction Variant: {variant['VariantName']}")
    print(f"  Current Instance Count: {variant['CurrentInstanceCount']}")
    print(f"  Desired Instance Count: {variant['DesiredInstanceCount']}")
    # Get instance type from endpoint config
    for config_variant in endpoint_config['ProductionVariants']:
        if config_variant['VariantName'] == variant['VariantName']:
            print(f"  Instance Type: {config_variant['InstanceType']}")
            break
```

**Solução de problemas de falhas na criação de endpoints**

Motivos de falha comuns:
+ **Capacidade insuficiente**: o tipo de instância solicitada não está disponível na sua região.
  + Solução: tente um tipo de instância diferente ou solicite um aumento da cota
+ **Permissões do IAM**: o perfil de execução não tem as permissões necessárias
  + Solução: verifique se o perfil tem acesso aos artefatos dos modelos do Amazon S3 e às permissões necessárias do SageMaker
+ **Artefatos do modelo não encontrados**: o URI do Amazon S3 está incorreto ou inacessível
  + Solução: verifique o URI do Amazon S3, as permissões do bucket e se você está na região correta
+ **Limites de recursos**: limites da conta excedidos para endpoints ou instâncias
  + Solução: solicite um aumento de cota de serviço por meio do Service Quotas ou do AWS Support

**nota**  
Se você precisar excluir um endpoint com falha e começar de novo:  

```
sagemaker.delete_endpoint(EndpointName=ENDPOINT_NAME)
```

## Etapa 5: invocar o endpoint
<a name="nova-sagemaker-inference-step5"></a>

Quando seu endpoint estiver InService, você poderá enviar solicitações de inferência para gerar predições do seu modelo do Amazon Nova. O SageMaker oferece suporte a endpoints síncronos (em tempo real com os modos de streaming/não streaming) e endpoints assíncronos (baseados no Amazon S3 para processamento em lote).

**Configurar o cliente de runtime**

Crie um cliente de runtime do SageMaker com as configurações de tempo limite apropriadas:

```
import json
import boto3
import botocore
from botocore.exceptions import ClientError

# Configure client with appropriate timeouts
config = botocore.config.Config(
    read_timeout=120,      # Maximum time to wait for response
    connect_timeout=10,    # Maximum time to establish connection
    retries={'max_attempts': 3}  # Number of retry attempts
)

# Create SageMaker Runtime client
runtime_client = boto3.client('sagemaker-runtime', config=config, region_name=REGION)
```

**Criar uma função de inferência universal**

A função a seguir lida com solicitações de streaming e não streaming. Ela usa a variável `INFERENCE_COMPONENT_NAME` definida na etapa 4. Se você implantou usando componentes de inferência (opção A), a variável foi definida como `MODEL_NAME + "-IC"`. Se você implantou usando endpoints de modelo único (opção B), a variável não foi definida, então defina-a como `None` antes de executar esta etapa:

```
# Only needed if you followed Option B (single model endpoints) in Step 4:
# INFERENCE_COMPONENT_NAME = None

def invoke_nova_endpoint(request_body):
    """
    Invoke Nova endpoint with automatic streaming detection.
    Supports both inference component and single model endpoint deployments.
    
    Args:
        request_body (dict): Request payload containing prompt and parameters
    
    Returns:
        dict: Response from the model (for non-streaming requests)
        None: For streaming requests (prints output directly)
    """
    body = json.dumps(request_body)
    is_streaming = request_body.get("stream", False)
    
    # Build invoke parameters
    invoke_params = {
        'EndpointName': ENDPOINT_NAME,
        'ContentType': 'application/json',
        'Body': body
    }
    
    # Add InferenceComponentName if using inference components
    if INFERENCE_COMPONENT_NAME:
        invoke_params['InferenceComponentName'] = INFERENCE_COMPONENT_NAME
    
    try:
        print(f"Invoking endpoint ({'streaming' if is_streaming else 'non-streaming'})...")
        
        if is_streaming:
            response = runtime_client.invoke_endpoint_with_response_stream(**invoke_params)
            
            event_stream = response['Body']
            for event in event_stream:
                if 'PayloadPart' in event:
                    chunk = event['PayloadPart']
                    if 'Bytes' in chunk:
                        data = chunk['Bytes'].decode()
                        print("Chunk:", data)
        else:
            # Non-streaming inference
            invoke_params['Accept'] = 'application/json'
            response = runtime_client.invoke_endpoint(**invoke_params)
            
            response_body = response['Body'].read().decode('utf-8')
            result = json.loads(response_body)
            print("✅ Response received successfully")
            return result
    
    except ClientError as e:
        error_code = e.response['Error']['Code']
        error_message = e.response['Error']['Message']
        print(f"❌ AWS Error: {error_code} - {error_message}")
    except Exception as e:
        print(f"❌ Unexpected error: {str(e)}")
```

**Exemplo 1: conclusão de chat sem streaming**

Use o formato de chat para interações conversacionais:

```
# Non-streaming chat request
chat_request = {
    "messages": [
        {"role": "user", "content": "Hello! How are you?"}
    ],
    "max_tokens": 100,
    "max_completion_tokens": 100,  # Alternative to max_tokens
    "stream": False,
    "temperature": 0.7,
    "top_p": 0.9,
    "top_k": 50,
    "logprobs": True,
    "top_logprobs": 3,
    "allowed_token_ids": None,  # List of allowed token IDs
    "truncate_prompt_tokens": None,  # Truncate prompt to this many tokens
    "stream_options": None
}

response = invoke_nova_endpoint(chat_request)
```

**Resposta de exemplo:**

```
{
    "id": "chatcmpl-123456",
    "object": "chat.completion",
    "created": 1234567890,
    "model": "default",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "Hello! I'm doing well, thank you for asking. I'm here and ready to help you with any questions or tasks you might have. How can I assist you today?"
            },
            "logprobs": {
                "content": [
                    {
                        "token": "Hello",
                        "logprob": -0.123,
                        "top_logprobs": [
                            {"token": "Hello", "logprob": -0.123},
                            {"token": "Hi", "logprob": -2.456},
                            {"token": "Hey", "logprob": -3.789}
                        ]
                    }
                    # Additional tokens...
                ]
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 12,
        "completion_tokens": 28,
        "total_tokens": 40
    }
}
```

**Exemplo 2: conclusão de texto simples**

Use o formato de conclusão para geração de texto simples:

```
# Simple completion request
completion_request = {
    "prompt": "The capital of France is",
    "max_tokens": 50,
    "stream": False,
    "temperature": 0.0,
    "top_p": 1.0,
    "top_k": -1,  # -1 means no limit
    "logprobs": 3,  # Number of log probabilities to return
    "allowed_token_ids": None,  # List of allowed token IDs
    "truncate_prompt_tokens": None,  # Truncate prompt to this many tokens
    "stream_options": None
}

response = invoke_nova_endpoint(completion_request)
```

**Resposta de exemplo:**

```
{
    "id": "cmpl-789012",
    "object": "text_completion",
    "created": 1234567890,
    "model": "default",
    "choices": [
        {
            "text": " Paris.",
            "index": 0,
            "logprobs": {
                "tokens": [" Paris", "."],
                "token_logprobs": [-0.001, -0.002],
                "top_logprobs": [
                    {" Paris": -0.001, " London": -5.234, " Rome": -6.789},
                    {".": -0.002, ",": -4.567, "!": -7.890}
                ]
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 6,
        "completion_tokens": 2,
        "total_tokens": 8
    }
}
```

**Exemplo 3: conclusão de chat com streaming**

```
# Streaming chat request
streaming_request = {
    "messages": [
        {"role": "user", "content": "Tell me a short story about a robot"}
    ],
    "max_tokens": 200,
    "stream": True,
    "temperature": 0.7,
    "top_p": 0.95,
    "top_k": 40,
    "logprobs": True,
    "top_logprobs": 2,
    "stream_options": {"include_usage": True}
}

invoke_nova_endpoint(streaming_request)
```

**Exemplo de saída de streaming:**

```
Chunk: data: {"id":"chatcmpl-029ca032-fa01-4868-80b7-c4cb1af90fb9","object":"chat.completion.chunk","created":1772060532,"model":"default","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}],"prompt_token_ids":null}
Chunk: data: {"id":"chatcmpl-029ca032-fa01-4868-80b7-c4cb1af90fb9","object":"chat.completion.chunk","created":1772060532,"model":"default","choices":[{"index":0,"delta":{"content":" Once"},"logprobs":{"content":[{"token":"\u2581Once","logprob":-0.6078429222106934,"bytes":[226,150,129,79,110,99,101],"top_logprobs":[{"token":"\u2581Once","logprob":-0.6078429222106934,"bytes":[226,150,129,79,110,99,101]},{"token":"\u2581In","logprob":-0.7864127159118652,"bytes":[226,150,129,73,110]}]}]},"finish_reason":null,"token_ids":null}]}
Chunk: data: {"id":"chatcmpl-029ca032-fa01-4868-80b7-c4cb1af90fb9","object":"chat.completion.chunk","created":1772060532,"model":"default","choices":[{"index":0,"delta":{"content":" upon"},"logprobs":{"content":[{"token":"\u2581upon","logprob":-0.0012345,"bytes":[226,150,129,117,112,111,110],"top_logprobs":[{"token":"\u2581upon","logprob":-0.0012345,"bytes":[226,150,129,117,112,111,110]},{"token":"\u2581a","logprob":-6.789,"bytes":[226,150,129,97]}]}]},"finish_reason":null,"token_ids":null}]}
Chunk: data: {"id":"chatcmpl-029ca032-fa01-4868-80b7-c4cb1af90fb9","object":"chat.completion.chunk","created":1772060532,"model":"default","choices":[{"index":0,"delta":{"content":" a"},"logprobs":{"content":[{"token":"\u2581a","logprob":-0.0001234,"bytes":[226,150,129,97],"top_logprobs":[{"token":"\u2581a","logprob":-0.0001234,"bytes":[226,150,129,97]},{"token":"\u2581time","logprob":-9.123,"bytes":[226,150,129,116,105,109,101]}]}]},"finish_reason":null,"token_ids":null}]}
Chunk: data: {"id":"chatcmpl-029ca032-fa01-4868-80b7-c4cb1af90fb9","object":"chat.completion.chunk","created":1772060532,"model":"default","choices":[{"index":0,"delta":{"content":" time"},"logprobs":{"content":[{"token":"\u2581time","logprob":-0.0023456,"bytes":[226,150,129,116,105,109,101],"top_logprobs":[{"token":"\u2581time","logprob":-0.0023456,"bytes":[226,150,129,116,105,109,101]},{"token":",","logprob":-6.012,"bytes":[44]}]}]},"finish_reason":null,"token_ids":null}]}

# Additional chunks...

Chunk: data: {"id":"chatcmpl-029ca032-fa01-4868-80b7-c4cb1af90fb9","object":"chat.completion.chunk","created":1772060532,"model":"default","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":15,"completion_tokens":87,"total_tokens":102}}
Chunk: data: [DONE]
```

**Exemplo 4: conclusão do chat multimodal**

Use o formato multimodal para entradas de imagem e texto:

```
# Multimodal chat request (if supported by your model)
multimodal_request = {
    "messages": [
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What's in this image?"},
                {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
            ]
        }
    ],
    "max_tokens": 150,
    "temperature": 0.3,
    "top_p": 0.8,
    "stream": False
}

response = invoke_nova_endpoint(multimodal_request)
```

**Resposta de exemplo:**

```
{
    "id": "chatcmpl-345678",
    "object": "chat.completion",
    "created": 1234567890,
    "model": "default",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "The image shows..."
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 1250,
        "completion_tokens": 45,
        "total_tokens": 1295
    }
}
```

## Etapa 6: limpar os recursos (opcional)
<a name="nova-sagemaker-inference-step6"></a>

Para evitar cobranças desnecessárias, exclua os recursos da AWS que você criou durante este tutorial. Os endpoints do SageMaker são cobrados enquanto estão em execução, mesmo que você não esteja ativamente fazendo solicitações de inferência.

**Importante**  
A exclusão de recursos é permanente e não poderá ser desfeita. Antes de continuar, certifique-se de que não precisará mais desses recursos.

**Inicializar o cliente de limpeza**

```
import boto3
import time

# Initialize SageMaker client
sagemaker = boto3.client('sagemaker', region_name=REGION)
```

**Excluir o componente de inferência (se usar a opção A)**

Se você implantou usando componentes de inferência, exclua o componente de inferência antes de excluir o endpoint:

```
# Delete inference component (Option A only)
try:
    print("Deleting inference component...")
    sagemaker.delete_inference_component(InferenceComponentName=INFERENCE_COMPONENT_NAME)
    print(f"✅ Inference component '{INFERENCE_COMPONENT_NAME}' deletion initiated")
except Exception as e:
    print(f"❌ Error deleting inference component: {e}")

# Wait for inference component to be deleted before proceeding
print("Waiting for inference component deletion...")
while True:
    try:
        sagemaker.describe_inference_component(InferenceComponentName=INFERENCE_COMPONENT_NAME)
        time.sleep(10)
    except sagemaker.exceptions.ClientError as e:
        if e.response['Error']['Code'] == 'ValidationException':
            print("✅ Inference component successfully deleted")
            break
        else:
            print(f"Error: {e}")
            break
```

**Excluir o endpoint**

```
try:
    print("Deleting endpoint...")
    sagemaker.delete_endpoint(EndpointName=ENDPOINT_NAME)
    print(f"✅ Endpoint '{ENDPOINT_NAME}' deletion initiated")
    print("Charges will stop once deletion completes (typically 2-5 minutes)")
except Exception as e:
    print(f"❌ Error deleting endpoint: {e}")
```

**nota**  
A exclusão do endpoint é assíncrona. Você pode monitorar o status da exclusão:  

```
import time

print("Monitoring endpoint deletion...")
while True:
    try:
        response = sagemaker.describe_endpoint(EndpointName=ENDPOINT_NAME)
        status = response['EndpointStatus']
        print(f"Status: {status}")
        time.sleep(10)
    except sagemaker.exceptions.ClientError as e:
        if e.response['Error']['Code'] == 'ValidationException':
            print("✅ Endpoint successfully deleted")
            break
        else:
            print(f"Error: {e}")
            break
```

**Excluir a configuração do endpoint**

Depois que o endpoint for excluído, remova a configuração dele:

```
try:
    print("Deleting endpoint configuration...")
    sagemaker.delete_endpoint_config(EndpointConfigName=ENDPOINT_CONFIG_NAME)
    print(f"✅ Endpoint configuration '{ENDPOINT_CONFIG_NAME}' deleted")
except Exception as e:
    print(f"❌ Error deleting endpoint configuration: {e}")
```

**Excluir o modelo (opção B apenas)**

Se você usou endpoints de modelo único, remova o objeto de modelo do SageMaker:

```
try:
    print("Deleting model...")
    sagemaker.delete_model(ModelName=MODEL_NAME)
    print(f"✅ Model '{MODEL_NAME}' deleted")
except Exception as e:
    print(f"❌ Error deleting model: {e}")
```