Documentação

Notas de conversão

Esta página descreve a exportação Core ML comum. O grafo ANE reescrito separadamente e a paletização de pesos opcional estão documentados em ANE_ENGINEERING.md.

A exportação carrega checkpoints originais do Laya em módulos PyTorch FP32, verifica estritamente todas as chaves do state-dict, traça uma implementação somente de inferência e salva um Core ML ML Program. Os próprios arquivos de checkpoint publicados contêm predominantemente tensores FP16; FP32 aqui descreve a computação de exportação/referência, não pesos de origem de maior precisão. Não é realizado treinamento, poda nem quantização de pesos. FP16 é uma escolha de precisão de conversão; FP32 pode ser selecionado para diagnóstico.

O runtime usa o tokenizer do checkpoint, o layout do prompt, os marcadores de opção, o embedding de tipo de pergunta, a decision head, a action head e as temperaturas de calibração. choice, score, noul, critérios estruturados, contabilização de tokens e zero tokens gerados seguem a API do upstream. O encoder é bidirecional: cada pergunta ainda executa sua própria sequência do encoder. Não há cache de hidden-state de estado compartilhado.

Escolhas de conversão validadas

  • coremltools==9.0, torch==2.7.0, numpy==2.1.3, Python 3.12.
  • Rastreamento TorchScript com verificação de grafo, modo de avaliação, pesos originais carregados em módulos FP32.
  • ML Program, alvo de implantação macOS 15 / iOS 18. A execução real foi testada em um M3 Max rodando macOS 27.2; a execução em iPhone/iPad e em macOS mais antigo não foi testada.
  • Os comprimentos de sequência padrão são escolhidos entre 16, 32, 64, 96, 128, 192, 256, 384, 512, 768, 1024, limitados pelo limite de contexto do checkpoint. O runtime preenche até o menor comprimento disponível e mascara esses tokens adicionados.
  • O tamanho de batch padrão é um, com 32 slots de marcador. Mais perguntas rodam em blocos. --batch-size e --max-options produzem assinaturas exportadas diferentes.
  • Formas fixas estão disponíveis para uma carga de trabalho conhecida. Entradas que excedem o comprimento ou a capacidade de opções de uma exportação geram um erro; elas não são truncadas silenciosamente para caber em uma exportação menor. O truncamento de contexto do checkpoint original é preservado.

A Apple documenta a conversão TorchScript e as formas de entrada enumeradas. Várias entradas enumeradas precisam do mesmo número de formas, correspondidas por índice; esta exportação emparelha IDs de entrada e máscaras de atenção de acordo.

Falhas mantidas para reprodutibilidade

Estas são observações nesta máquina e neste sistema operacional, não afirmações sobre toda versão do Core ML.

  1. O operador booleano __or__ do PyTorch não foi convertido. As chamadas explícitas torch.logical_or / torch.logical_and preservam a mesma semântica de máscara.
  2. O NumPy 2.5 rejeitou uma conversão de array para escalar obsoleta dentro do coremltools 9.0. A dependência suportada do projeto está fixada abaixo do NumPy 2.2. O PyTorch foi fixado na versão 2.7.0 testada pelo conversor em vez da 2.7.1.
  3. RangeDim com CPU_AND_GPU forçado produziu grandes erros numéricos e resultados diferentes em entradas idênticas repetidas. A exportação SDPA original correspondia a apenas 47/63 respostas de referência, e a atenção explícita matmul/softmax correspondia a 20/63. FP32 não resolveu a falha observada de GPU com entrada curta. A CPU / seleção automática forneceu saídas corretas para o grafo SDPA.
  4. Comprimentos enumerados restauraram a fidelidade e a repetibilidade da GPU. Um pequeno teste de regressão separado então expôs um SIGTRAP do compilador MPSGraph ao fatiar uma matriz de atenção local booleana constante. O diagnóstico nomeou ElementsAttr::getValues<bool> / FoldStridedSliceOp.
  5. A implementação final fatia posições inteiras e constrói a máscara local booleana depois. Isso remove a armadilha do compilador. Não cura a falha geral de GPU com RangeDim: o experimento seguinte ainda correspondia a apenas 49/63 e não era repetível. Os comprimentos enumerados continuam sendo o padrão.

O runtime rejeita RangeDim + cpu_gpu, a menos que seja explicitamente permitido para um experimento de diagnóstico. Para reproduzir essa configuração que falhou:

laya-coreml convert laya-multilingual models/range-experiment --shape-mode range
python -m benchmarks.validate models/range-experiment \
  --name laya-multilingual --compute-units cpu_gpu --allow-unvalidated-gpu \
  --repeats 10 --output artifacts/range-experiment.json

Espera-se que o teste falhe no ambiente medido. Relatórios brutos de falha e de sucesso são mantidos em benchmarks/results/; relatórios contendo "passed": false não devem ser citados como configurações validadas.

Evidência de dispositivo

CPU_AND_NE significa que a CPU e o Neural Engine são permitidos, não que todo operador roda no Neural Engine. O benchmark registra os dispositivos preferidos/suportados e os custos estimados do compute plan do Core ML. Este é um plano previsto, não um trace de hardware em tempo de execução do Instruments, uma medição de potência ou prova de execução exclusiva no Neural Engine.

Carregando snapshots do Hub

O smoke test de lançamento encontrou um problema de empacotamento separado: carregar um arquivo de pesos com link simbólico a partir do cache compartilhado do Hugging Face fez o compilador nativo do Core ML relatar a ausência de model.mlmodelc/weights/weight.bin. Todos os seis pacotes locais equivalentes carregaram com sucesso. O runtime agora copia pacotes com suporte a symlink para um cache de arquivos regulares endereçado por conteúdo antes de construir o MLModel. Os hashes são verificados antes e depois da cópia e na reutilização; um cache alterado ou danificado gera um erro. Pacotes locais de arquivos regulares não passam por esse caminho de cópia. Consulte USAGE.md para a localização e a substituição do cache.

Reprodutibilidade

Toda exportação inclui coreml_config.json: SHA256 dos pesos originais, revisão da origem, formas, precisão, implementação de atenção, versões das ferramentas, hora da conversão e hashes de cada arquivo de pacote/tokenizer/config. As exportações se recusam a sobrescrever diretórios existentes. Uma exportação com falha remove apenas seu diretório de saída recém-criado.

A golden reference versionada foi gerada a partir da revisão 573e5b62696ba441230cd6be71d593331b5d23af não modificada do upstream Laya, usando FP32 PyTorch MPS. Ela inclui os IDs completos de tokens de entrada e os logits não arredondados. A validação compara esses tokens exatamente e verifica respostas selecionadas, probabilidades calibradas, probabilidades de ação, contabilização de tokens e resultados públicos repetidos.

Para regenerar a golden reference em um ambiente compatível com o upstream:

git clone https://github.com/NandhaKishorM/laya .upstream
git -C .upstream checkout 6a5819129eb220570792e417e49723d697efd76f
python -m benchmarks.reference --upstream .upstream --model-root /path/to/original/checkpoints

As dependências exatas da referência estão registradas no JSON gerado. Elas são separadas do ambiente de exportação fixado; o Transformers não é uma dependência de runtime nem de exportação do laya-coreml.