Por que personalizar um modelo menor em vez de usar um modelo de fronteira
Catálogos de varejo raramente chegam com atributos limpos e estruturados. Nomes, descrições e categorias de produtos vêm de fontes diferentes e mudam o tempo todo. Busca, recomendação e navegação dependem de tags consistentes — mas rotular milhares de SKUs manualmente é lento e difícil de manter padronizado. Um modelo de fronteira até gera tags com engenharia de prompt, mas um fluxo de rotulagem em alto volume tem um objetivo bem mais estreito: devolver os atributos certos no esquema certo, de forma consistente.
Quando a taxonomia é estável e a saída pode ser pontuada de forma programática, personalizar um modelo open-weight menor costuma ser a melhor escolha. Neste guia, você vai personalizar o Qwen3-8B com fine-tuning supervisionado (SFT) e depois otimizá-lo com aprendizado por reforço com recompensas verificáveis (RLVR), usando GRPO (Group Relative Policy Optimization). O treinamento roda no Amazon SageMaker serverless model customization, e o modelo final é servido em um endpoint de inferência assíncrona.
Prós e contras
✅ O que você ganha
- Custo por requisição menor: você não paga por capacidades amplas que o fluxo não usa.
- Aderência ao esquema: o modelo aprende o formato exato de saída diretamente.
- Treinamento sem gerenciar GPU: o SageMaker provisiona e libera a capacidade sozinho.
- Otimização de trade-off: o RLVR ajusta recall × precisão com recompensa explícita.
⚠️ O que você NÃO ganha
- Flexibilidade de prompts: o modelo é especializado na tarefa, não generalista.
- Infraestrutura zero no serving: o endpoint assíncrono usa instância provisionada (ml.g6.2xlarge).
- Métrica de negócio direta: as métricas medem qualidade de tag, não conversão.
Visão geral da arquitetura
O fluxo é dividido em três preocupações: preparação de dados, customização serverless e inferência. Os dados são transformados uma única vez em ativos versionados; o SFT ensina o esquema de rotulagem; o RLVR otimiza o comportamento contra uma recompensa determinística. O pacote final é hospedado para inferência.
Requisitos
| Componente | Mínimo | Recomendado |
|---|---|---|
| Python | 3.11+ | 3.11+ |
| AWS CLI | v2 | v2 |
| SDK | SageMaker Python SDK v3 | v3 + pandas |
| Região | Suporte a SFT/RLVR de Qwen3-8B | Quota de endpoint ml.g6.2xlarge |
| Dados | Amazon Sales Dataset (Kaggle) | Catálogo próprio transformado |
Passo 1: preparar os dados de fine-tuning
O exemplo parte do Amazon Sales Dataset no Kaggle, com mais de 1.000 registros de produtos. Para a rotulagem, os campos úteis são nome, categoria e descrição. O processamento roda como um SageMaker Processing job, para que a preparação seja repetível e auditável: lê o arquivo do S3, normaliza texto e caminhos de categoria, remove linhas inválidas e mapeia as informações para o alvo de nove categorias.
Cada linha do JSONL de SFT contém um array messages com três turnos: system (o esquema), user (nome e categoria do produto) e assistant (as tags esperadas). Os turnos de sistema e usuário formam o prompt; o turno final do assistente é o alvo supervisionado. Os arquivos são registrados como datasets versionados no SageMaker AI Registry:
from sagemaker.ai_registry.dataset import DataSet, CustomizationTechnique
train_dataset = DataSet.create(
name="amazon-sft-train",
source="s3://amzn-s3-demo-bucket/sft/train.jsonl",
customization_technique=CustomizationTechnique.SFT,
wait=True,
)
TRAINING_DATASET_ARN = train_dataset.arnPasso 2: ensinar o esquema ao Qwen3-8B com SFT serverless
O SFTTrainer do SDK v3 submete o job de customização, aplica LoRA, consome os ARNs dos datasets e publica a saída em um model package group. Sem o argumento de compute, o SageMaker usa capacidade serverless gerenciada pela AWS:
from sagemaker.train.sft_trainer import SFTTrainer
from sagemaker.train.common import TrainingType
trainer = SFTTrainer(
model="huggingface-reasoning-qwen3-8b",
training_type=TrainingType.LORA,
model_package_group=model_package_group,
training_dataset=TRAINING_DATASET_ARN,
validation_dataset=VALIDATION_DATASET_ARN,
sequence_length="4K",
s3_output_path=S3_OUTPUT_PATH,
role=ROLE_ARN,
)
trainer.hyperparameters.max_epochs = 3
trainer.hyperparameters.global_batch_size = 8
trainer.hyperparameters.lora_rank = 16
trainer.hyperparameters.merge_weights = True
training_job = trainer.train(wait=True)O SFT é o maior salto de qualidade porque demonstra diretamente o comportamento de entrada/saída desejado. O RLVR entra depois para otimizar o trade-off restante, não para reaprender o formato do zero.
Passo 3: converter exemplos para RLVR
Após o SFT, o modelo segue o esquema mas ainda pode perder atributos esperados ou acrescentar tags desnecessárias. Para cada linha do SFT, mantenha os turnos de sistema e usuário no prompt e mova o conteúdo final do assistente para reward_model.ground_truth:
messages = json.loads(line)["messages"]
rlvr_row = {
"id": f"amazon-tagging-{split}-{index:05d}",
"prompt": messages[:-1],
"data_source": "amazon_tagging",
"reward_model": {
"style": "rule",
"ground_truth": messages[-1]["content"],
},
"extra_info": {"answer": messages[-1]["content"], "split": split},
}Passo 4: otimizar com RLVR serverless e GRPO
O RLVR parte do modelo SFT e usa uma função de recompensa determinística para pontuar candidatos. O GRPO gera um grupo de oito conclusões por prompt (rollout_n=8), pontua cada uma de forma independente e computa vantagens relativas ao grupo, com regularização KL para limitar o desvio do modelo SFT de referência:
trainer = RLVRTrainer(
model=SFT_MODEL_PACKAGE_ARN,
training_type=TrainingType.LORA,
model_package_group=rlvr_model_package_group,
custom_reward_function=REWARD_EVALUATOR_ARN,
training_dataset=training_dataset,
validation_dataset=validation_dataset,
s3_output_path=S3_OUTPUT_PATH,
role=ROLE_ARN,
)
trainer.hyperparameters.rollout_n = 8
trainer.hyperparameters.global_batch_size = 128
trainer.hyperparameters.max_epochs = 4
trainer.hyperparameters.learning_rate = 1e-5
trainer.hyperparameters.max_prompt_length = 2048
training_job = trainer.train(wait=False)A recompensa combina cinco componentes com pesos explícitos: 0,30 × recall + 0,30 × precisão + 0,30 × acurácia + 0,05 × match_quality + 0,05 × formatação. Um cronograma progressivo muda a ênfase durante o treino — as primeiras iterações favorecem recall (para não perder atributos) e as finais aumentam a precisão (para evitar tags desnecessárias).
Passo 5: servir o modelo com inferência assíncrona
Treino e inferência usam infraestruturas diferentes. O serving usa um endpoint de Asynchronous Inference no ml.g6.2xlarge, ideal para enriquecimento de catálogo em lote — as requisições entram em fila e os resultados são gravados no S3. A imagem vLLM customizada é usada apenas na inferência:
sm_client.create_endpoint_config(
EndpointConfigName=endpoint_config_name,
ProductionVariants=[{
"VariantName": "AllTraffic",
"ModelName": model_name,
"InitialInstanceCount": 1,
"InstanceType": "ml.g6.2xlarge",
}],
AsyncInferenceConfig={"OutputConfig": {"S3OutputPath": "s3://amzn-s3-demo-bucket/async-output"}},
)Passo 6: invocar e avaliar
A invocação usa requisição compatível com OpenAI, com temperature=0.1 e max_tokens=1024 para geração estável. Para payloads maiores, envie o corpo via S3 e consulte o OutputLocation.
Resultados e o que significam
| Modelo | Overall | Recall | Precisão | Acurácia |
|---|---|---|---|---|
| Baseline | 0,354 | 0,327 | 0,397 | 0,327 |
| SFT | 0,6827 | 0,6689 | 0,652 | 0,6689 |
| GRPO | 0,6941 | 0,703 | 0,638 | 0,686 |
O SFT é o principal motor de qualidade: o Overall salta de 0,354 para 0,6827, com recall de 0,327 para 0,6689. O GRPO faz um trade-off mais fino — o Overall sobe para 0,6941 e o recall para 0,703, enquanto a precisão cai levemente de 0,652 para 0,638. Na prática: se perder atributos válidos custa mais que gerar algumas tags extras, o GRPO compensa. Se tags desnecessárias prejudicam mais o fluxo, ajuste os pesos da recompensa para favorecer precisão.
Troubleshooting
- ❌ Modelo não segue o esquema → Verifique se o turno
assistantdo SFT contém o formato exato das nove categorias. - ❌ Precisão caiu após o GRPO → Esperado com pesos de recompensa focados em recall; ajuste os pesos para favorecer precisão.
- ❌ Job não inicia → Confirme região e combinação modelo/técnica suportadas para SFT/RLVR de Qwen3-8B.
- ❌ Endpoint não sobe → Verifique a quota de hosting para ml.g6.2xlarge.
- ❌ Payload grande falha → Envie o corpo via S3 (InputLocation) em vez de inline.
FAQ
- Por que não usar um modelo de fronteira? Em fluxo de alto volume com esquema fixo, você paga por capacidades que não usa a cada requisição.
- O que é “serverless” aqui? Refere-se ao caminho de treinamento; o endpoint de inferência usa instância provisionada.
- Preciso de GPU própria? Não para o treino — o SageMaker gerencia a capacidade.
- O GRPO substitui o SFT? Não. O SFT ensina o formato; o RLVR otimiza o trade-off de qualidade.
- Essas métricas medem conversão? Não. Valide impacto de negócio com completude de atributos e cobertura de busca/filtro.



