Documentação

Ajuste fino do Laya nas suas próprias decisões

No benchmark typed-decisions os checkpoints base pontuam perto do acaso zero-shot — 0.36 e 0.35 contra uma linha de base aleatória de 0.318 — enquanto o checkpoint ajustado alcança 0.766 nas mesmas 2.000 decisões, acima dos 0.727 publicados do TypeSafe Jev e acima do teto de 0.735 de auto-concordância do professor. O ajuste fino é onde está a maior parte do valor, e o notebook de ajuste fino público roda todo o ciclo nas GPUs 2xT4 gratuitas do Kaggle: construir o conjunto de dados, treinar com RLCD, ajustar as temperaturas de calibração, avaliar e enviar o resultado para o Hub. Esta página percorre esse notebook e aponta as partes que continuam sendo estruturais quando você troca os dados pelos seus próprios.

O outro exemplo completo — uma cabeça de decisão de agente de navegador em uma única GPU de 16 GB, sem API paga — está em Ajuste fino do Laya como cabeça de decisão de agente de navegador.

O que o notebook faz, em ordem

# etapa o que acontece
1 Ambiente verifica que as duas GPUs T4 estão visíveis e alocadas
2 Instalação laya, transformers, datasets e as dependências de treino
3 Pré-processamento os 1.200 casos de treino (6.000 decisões tipadas) viram itens tokenizados com alvos suaves, gravados em disco para as duas ranks de DDP
4 Treino train_ddp.py sob torchrun --nproc_per_node=2, quatro épocas
5 Calibração uma temperatura por tipo, ajustada em uma fatia reservada antes do treino (dentro do script de treino, após a última época)
6 Avaliação a divisão oficial test respondida pelo checkpoint ajustado — 400 casos, 2.000 decisões — com latência por caso
7 Métricas precisão, precisão suave, Brier, ECE, MAE de score, dentro de um nível, KL/TV e percentis de latência; uma tabela comparativa contra o Jev e o teto do professor
8 Publicação (opcional) um model card construído a partir dos próprios números da execução, pasta enviada ao Hub
9 Relatório benchmark_report.json com a tabela de métricas e a precisão por fluxo de trabalho

Configurações do Kaggle: Accelerator GPU T4 x2, Internet On. As saídas caem em /kaggle/working/laya_finetuned_typed_decisions.

A receita de treino

O RLCD treina nas distribuições gold do benchmark, não em rótulos rígidos: cada item carrega a probabilidade que o professor atribuiu a cada opção, e as duas metades da perda leem esse alvo —

  • um termo de gradiente de política sobre projeções de logit ruidoso amostradas (estilo GRPO: quatro amostras por item, ruído de exploração decaindo de 0.4 → 0.1), recompensado por regras de pontuação próprias (esférica 0.75, probabilidade ranqueada 1.0);
  • um termo de entropia cruzada suave com peso total contra a mesma distribuição.

Os ajustes que o notebook define para um cartão de 16 GB:

épocas 4
lote efetivo 64 sequências (8 por micro-lote, 2 GPUs, 4 passos de acumulação)
taxas de aprendizado encoder 2.5e-5, cabeça 1e-4 — AdamW, agenda de cosseno
memória autocast fp16, gradient checkpointing no encoder e na cabeça, clip de norma de gradiente 1.0
orçamento de sequência max_len 1024, head_max_len 256, max_tokens_per_batch 4096

O tempo de execução em 2xT4 é de minutos para a demonstração e de horas para dados reais: cerca de 4–6 minutos para as 6.000 decisões da demonstração, e aproximadamente 4–5 horas para quatro épocas sobre ~30k perguntas.

Para apontá-lo aos seus dados, substitua as duas chamadas de load_dataset e mantenha o esquema das linhas: cada caso carrega state, questions e gold (as probabilidades do professor por pergunta), e o pré-processador os transforma em itens. Os tipos de pergunta são choice, score e noul; qualquer coisa que você consiga expressar com eles sobre um estado vale.

A calibração faz parte da execução

Este é o passo mais provável de ser deixado de fora ao copiar o ciclo, e ele é estrutural no momento em que alguém aplica gating sobre a confiança.

O notebook tira uma fatia de calibração dos dados de treino antes de fragmentá-los entre as ranks (até 400 itens, ou 10%, com semente fixa, idêntica em toda rank). Ajustar temperaturas em itens nos quais a execução já treinou mede o ajuste, não a calibração — o modelo está quase certo e quase confiante neles, então o otimizador não tem nada para suavizar e retorna uma escala degenerada.

Depois da última época, a rank 0 ajusta uma temperatura por tipo de pergunta (choice, score, noul) por LBFGS sobre o log da temperatura, limitada a [0.1, 10] (1.0 para uma fatia com menos de dez itens, 1.2 se o ajuste lançar). Os valores vão para rl_agent_config.json como temperature, e o notebook remove qualquer temperature_by_options herdada na mesma escrita: aqueles valores antigos de bucket têm precedência na inferência e mascarariam silenciosamente o novo ajuste.

O escalonamento por temperatura deixa o argmax — e a precisão — inalterados; o que se move é a confiança. Os checkpoints, como distribuídos, são excessivamente confiantes, então ajuste antes de confiar em qualquer limiar, e avalie o resultado em dados reservados antes de alegar uma melhoria. A regressão de persistência de config roda sem downloads nem treino:

python tests/test_calibration_persistence.py

Avaliar antes de confiar nele

A avaliação é uma passada completa sobre a divisão de teste oficial: 400 casos, 2.000 decisões em Agent Trace Observability, Customer Service, Invoice Processing e Security Incidents. Ela calcula precisão, precisão suave, Brier, ECE (via laya.common.ece_score), MAE de score, dentro de um nível e percentis de latência, depois constrói uma tabela comparativa cujas linhas de referência são fixas:

modelo tipo precisão ECE
TypeSafe Jev 1.13.0 geral 0.727 0.144
ModernBERT-base (149M) especialista 0.646 0.179
Teacher Self-Agreement teto 0.735 —
Laya (checkpoint publicado) ajustado 0.766 —

A linha do Laya da sua própria execução é calculada da mesma forma — o notebook reconstrói a tabela a partir dos próprios números da execução. Dois hábitos que vale copiar: mantenha as fatias que te importam (um idioma, um fluxo de trabalho) dentro dos dados reservados, e reporte a calibração ao lado da precisão, porque o sinal de treino é uma distribuição, não só um rótulo. Quando você tiver números, um post nas Discussões do repositório é o lugar para compartilhá-los; benchmarks e limites conhecidos ficam em BENCHMARKS.md na raiz do repositório.

Enviar para o Hub

A célula de publicação é a última milha do ciclo, e ela é deliberadamente entediante:

  1. Coloque um HF_TOKEN de escrita no Kaggle (Add-ons → Secrets). A célula lança as instruções exatas se ele estiver faltando.
  2. Defina o repositório de destino — a célula distribuída usa por padrão um nome no próprio namespace do projeto, então mude-o antes de rodar.
  3. Rode. Ele escreve um model card cujos números vêm da tabela de comparação desta execução, depois envia model.safetensors, encoder/, tokenizer/, rl_agent_config.json, o card e o relatório de benchmark.

O resultado carrega como qualquer outro checkpoint — não há uma API específica de ajuste fino:

import laya

agent = laya.load("your-org/your-checkpoint")   # the repo you just pushed
result = agent.predict(state, questions)

Um checkpoint_latest/ rotativo é sobrescrito a cada época, então um timeout ou OOM do Kaggle custa uma época em vez da execução.

O que observar

  • O ciclo é tão bom quanto os alvos. O RLCD imita a distribuição de um professor nas suas perguntas; colete as confianças do professor antes do treino (ou junto com ele), e trate a qualidade delas como o teto.
  • A fatia de calibração é pequena de propósito. Até 400 itens ou 10% — o suficiente para três escalares por tipo, não o suficiente para validar contra algo. Reserve seus próprios dados de avaliação.
  • Seus rótulos devem caber nas três primitivas. Se sua decisão não é um choice, uma escala ou uma probabilidade sim/não, molde-a em uma delas primeiro. Duas arestas afiadas já estão documentadas: contagens altas de opções degradam a seleção por confiança (#394), e a negação em escolha forçada pode seguir a pergunta em vez do estado (#377).
  • Entregue a config, não só os pesos. A temperature_by_options removida é a parte que desfaz silenciosamente uma calibração se sobreviver em uma config copiada.