1. Separar o programa, seus parâmetros e o acompanhamento comercial
O código descreve o comportamento do programa. A configuração especifica a carga: modelo, dados, batch, precisão e destino. Os segredos dão acesso aos recursos necessários. Mantenha esses elementos distintos para alterar uma tentativa sem reescrever o código nem copiar um token para um arquivo compartilhado.
A referência de comando Kernodeck permite recuperar o contexto da locação na sua conta. O identificador de tentativa distingue as execuções do seu programa durante esse período. Associe-os nas suas anotações se isso ajudar, mas não peça ao seu script para deduzir o estado do cálculo a partir do status do pagamento.
Tomemos um projeto de classificação de documentos que deve ser iniciado várias vezes sobre uma mesma amostra. O contrato do programa descreve o arquivo de entrada, os parâmetros aceitos, a pasta de saída e a forma de reportar erros. O guia sobre dados detalha a validação do conteúdo; aqui, organizamos a interface que conecta essas etapas.
2. Escrever um contrato de entrada explícito e versionado
Documente os campos obrigatórios e os valores aceitos. Evite valores padrão silenciosos para uma decisão que altera o resultado, como o modelo ou o dispositivo. Um número de esquema distingue a forma da configuração da versão do código; ele não substitui esta última.
Neste exemplo didático, o arquivo JSON contém um esquema, um caminho de entrada, um batch e o dispositivo solicitado. Os caminhos relativos são lidos a partir da pasta de configuração. Essa regra escolhida para o exemplo evita depender do diretório a partir do qual um colega executa o comando.
Ler um JSON válido verifica apenas sua sintaxe. Seu programa deve em seguida verificar os tipos, os campos e as restrições do projeto. Em caso de erro, ele deve parar antes de carregar um recurso custoso, com uma mensagem que nomeie o parâmetro a corrigir.
{
"schema_version": 1,
"input": "../data/pilote.jsonl",
"batch_size": 4,
"device": "cuda"
}3. Preparar um ponto de entrada que recusa erros simples
argparse permite declarar opções e gerar uma ajuda para o seu comando. O exemplo a seguir constitui apenas uma pré-verificação: ele lê a configuração, verifica seus campos e identifica uma pasta de saída já utilizada. Ele não carrega modelo nem dados na memória e não testa a disponibilidade da GPU.
Salve este código didático em prepare_run.py se quiser adaptá-lo. Ele é proposto sem execução atestada. Em seguida, adicione seus controles de negócio na aplicação, em vez de considerar a mensagem final como um resultado de cálculo. O dispositivo cuda continua sendo uma solicitação; o PyTorch também usa esse nome com ROCm.
A recusa de um diretório de saída existente é aqui uma convenção de proteção contra a mistura de tentativas. Um verdadeiro comando de retomada deve receber uma opção e controles distintos. Não transforme um novo lançamento em retomada implícita só porque há arquivos presentes.
import argparse
import json
from pathlib import Path
parser = argparse.ArgumentParser(description="Validar uma execução do projeto")
parser.add_argument("--config", type=Path, required=True)
parser.add_argument("--run-dir", type=Path, required=True)
args = parser.parse_args()
try:
config_path = args.config.resolve()
config = json.loads(config_path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
parser.error(f"Configuração ilegível: {exc}")
expected = {"schema_version", "input", "batch_size", "device"}
if not isinstance(config, dict) or set(config) != expected:
parser.error("Campos esperados: schema_version, input, batch_size, device")
if type(config["schema_version"]) is not int or config["schema_version"] != 1:
parser.error("schema_version deve valer 1")
if type(config["batch_size"]) is not int or config["batch_size"] < 1:
parser.error("batch_size deve ser um inteiro positivo")
if config["device"] not in ("cpu", "cuda"):
parser.error("device deve valer cpu ou cuda")
if not isinstance(config["input"], str) or not config["input"]:
parser.error("input deve ser um caminho não vazio")
input_path = (config_path.parent / config["input"]).resolve()
run_dir = args.run_dir.resolve()
if not input_path.is_file():
parser.error("Arquivo de entrada ausente")
if run_dir.exists():
parser.error("Escolha uma nova pasta de saída")
print(json.dumps({
"status": "configuration_validated",
"input": str(input_path),
"run_dir": str(run_dir),
"device_requested": config["device"],
"batch_size": config["batch_size"]
}, ensure_ascii=False))python prepare_run.py --config config/piloto.json --run-dir runs/piloto-0014. Dar uma identidade às execuções e aos seus resultados
Associe cada execução a um identificador curto e único na sua campanha. Anote a revisão do código, o esquema e os parâmetros efetivamente usados, depois a referência dos dados e do modelo. Guarde esses valores junto com as saídas, para que um resultado não dependa de um arquivo de configuração modificado depois.
Para comparar dois tamanhos de batch, crie dois ensaios e dois diretórios. Mantenha a mesma amostra e identifique a diferença intencional. Os nomes pilote-001 e pilote-002 não explicam por si só o que mudou: o manifesto liga o nome aos parâmetros.
Reserve um formato de balanço legível pelas suas ferramentas. Ele pode distinguir itens recebidos, concluídos, recusados e ainda a processar. Escolha uma regra de sucesso completa e não marque um teste como concluído logo que o primeiro resultado for escrito. O código de retorno do programa deve permanecer coerente com essa conclusão.
Role a tabela para ler todas as colunas.| Arquivo ou estado | Função | Verificação esperada |
|---|---|---|
| manifest.json | Identidade do código, dos dados e dos parâmetros | Valores efetivamente usados, sem segredos. |
| results.jsonl | Uma saída por item aceito | Identificadores conhecidos e formato em conformidade. |
| errors.jsonl | Itens recusados e motivo útil | Sem desaparecimento silencioso nem conteúdo sensível desnecessário. |
| summary.json | Conclusão do teste e contadores | Soma coerente, arquivos relidos antes do status final. |
5. Expor eventos úteis às suas ferramentas
Torne visíveis algumas transições: configuração aceita, dados acessíveis, modelo carregado, primeira saída escrita e fim do processamento. Um registro deve permitir responder "em que ponto está esta execução?" sem copiar os documentos ou prompts. Associe a etapa e o identificador do teste à mensagem.
O módulo logging do Python permite organizar as mensagens por nível e destino. Em seguida, escolha sua própria convenção de eventos e documente-a. Uma aplicação que registra um erro e depois termina com sucesso torna a automação enganosa; por outro lado, cada aviso não significa que o resultado seja inutilizável.
Não confunda evento emitido com resultado duradouro: uma mensagem "backup iniciado" não prova que um arquivo foi relido. Para uma execução longa, o guia dedicado explica a relação entre processo e sessão. Sua interface deve, sobretudo, manter uma conclusão acessível após o fim da conexão interativa.
6. Definir a falha, a retomada e a verificação final
Classifique as falhas úteis: configuração inválida, recurso ausente, erro de cálculo e resultado não conforme. Dê, para cada uma, uma próxima ação. Não instale nova tentativa automática sem decidir quais efeitos podem ser repetidos: reescrever uma saída já aceita e retomar um checkpoint exigem regras diferentes.
Seu procedimento final explica como iniciar, observar, parar, retomar e exportar. Para um processamento de documentos, mantenha a lista dos identificadores concluídos e dos que precisam ser reprocessados. Para um treinamento, use um protocolo que verifique os estados salvos em um novo processo. Uma pasta não vazia não é prova de retomada correta.
Por fim, controle o projeto a partir de uma nova invocação, com uma configuração conhecida e um destino distinto. Verifique as recusas esperadas e, depois, um pequeno percurso completo. A pré-checagem desta página não cobre acessos simultâneos, exposição pública de um serviço nem permissões de armazenamento: esses temas exigem um projeto próprio.