Documentación

Notas de conversión

Esta página describe la exportación ordinaria de Core ML. El grafo ANE reescrito por separado y la paletización de pesos opcional se documentan en ANE_ENGINEERING.md.

La exportación carga los checkpoints originales de Laya en módulos PyTorch FP32, comprueba estrictamente todas las claves del state-dict, traza una implementación solo de inferencia y guarda un ML Program de Core ML. Los propios archivos de checkpoint publicados contienen mayoritariamente tensores FP16; FP32 aquí describe el cómputo de exportación/referencia, no pesos de origen de mayor precisión. No se realiza entrenamiento, poda ni cuantización de pesos. FP16 es una elección de precisión de conversión; FP32 puede seleccionarse para diagnóstico.

El runtime usa el tokenizer del checkpoint, la disposición del prompt, los marcadores de opciones, el embedding de tipo de pregunta, la cabeza de decisión, la cabeza de acción y las temperaturas de calibración. Choice, score, noul, los criterios estructurados, la contabilidad de tokens y los cero tokens generados siguen la API del upstream. El codificador es bidireccional: cada pregunta sigue ejecutando su propia secuencia de codificador. No hay ninguna caché de estados ocultos compartida entre estados.

Elecciones de conversión validadas

  • coremltools==9.0, torch==2.7.0, numpy==2.1.3, Python 3.12.
  • Trazado con TorchScript con comprobación de grafo, modo de evaluación y pesos originales cargados en módulos FP32.
  • ML Program, con destino de despliegue macOS 15 / iOS 18. La ejecución real se probó en un M3 Max con macOS 27.2; la ejecución en iPhone/iPad y en macOS anteriores no se probó.
  • Las longitudes de secuencia por defecto se eligen entre 16, 32, 64, 96, 128, 192, 256, 384, 512, 768 y 1024, limitadas por el límite de contexto del checkpoint. El runtime rellena (padding) hasta la longitud disponible más pequeña y enmascara esos tokens añadidos.
  • El tamaño de lote por defecto es uno, con 32 ranuras de marcador. Más preguntas se ejecutan en fragmentos. --batch-size y --max-options producen firmas exportadas distintas.
  • Hay formas fijas disponibles para una carga de trabajo conocida. Las entradas que superan la longitud o la capacidad de opciones de una exportación generan un error; no se truncan en silencio para ajustarse a una exportación más pequeña. Se conserva el truncamiento de contexto del checkpoint original.

Apple documenta la conversión de TorchScript y las formas de entrada enumeradas. Varias entradas enumeradas necesitan el mismo número de formas, emparejadas por índice; esta exportación empareja en consecuencia los IDs de entrada y las máscaras de atención.

Fallos conservados para reproducibilidad

Son observaciones en esta máquina y este sistema operativo, no afirmaciones sobre todas las versiones de Core ML.

  1. El operador booleano __or__ de PyTorch no se convirtió. torch.logical_or / torch.logical_and explícitos conservan la misma semántica de máscara.
  2. NumPy 2.5 rechazó una conversión obsoleta de array a escalar dentro de coremltools 9.0. La dependencia admitida del proyecto está fijada por debajo de NumPy 2.2. PyTorch se fijó a la versión 2.7.0 probada por el conversor en lugar de a la 2.7.1.
  3. RangeDim con CPU_AND_GPU forzado produjo grandes errores numéricos y resultados distintos con entradas idénticas repetidas. La exportación original con SDPA solo coincidió en 47/63 respuestas de referencia, y la atención explícita con matmul/softmax coincidió en 20/63. FP32 no resolvió el fallo de GPU observado con entradas cortas. La selección de CPU / automática dio salidas correctas para el grafo SDPA.
  4. Las longitudes enumeradas restablecieron la fidelidad y la repetibilidad en GPU. Una prueba de regresión diminuta aparte expuso después un SIGTRAP del compilador de MPSGraph al rebanar (slicing) una matriz constante booleana de atención local. El diagnóstico nombró ElementsAttr::getValues<bool> / FoldStridedSliceOp.
  5. La implementación final rebana posiciones enteras y construye después la máscara local booleana. Esto elimina la trampa del compilador. No cura el fallo general de GPU con RangeDim: el experimento posterior siguió coincidiendo solo en 49/63 y no era repetible. Las longitudes enumeradas siguen siendo la opción por defecto.

El runtime rechaza RangeDim + cpu_gpu a menos que se permita explícitamente para un experimento de diagnóstico. Para reproducir esa configuración fallida:

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

Se espera que la prueba falle en el entorno medido. Los informes sin procesar de fallos y de éxitos se conservan en benchmarks/results/; los informes que contienen "passed": false no deben citarse como configuraciones validadas.

Evidencia de dispositivo

CPU_AND_NE significa que la CPU y el Neural Engine están permitidos, no que todos los operadores se ejecuten en el Neural Engine. El benchmark registra los dispositivos preferidos/admitidos del plan de cómputo de Core ML y los costes estimados. Es un plan previsto, no una traza de hardware de runtime de Instruments, una medición de potencia ni una prueba de ejecución exclusiva en el Neural Engine.

Cargar instantáneas del Hub

La prueba de humo (smoke test) de la versión encontró un problema de empaquetado aparte: cargar un archivo de pesos de enlace simbólico desde la caché compartida de Hugging Face hizo que el compilador nativo de Core ML informara de la falta de model.mlmodelc/weights/weight.bin. Los seis paquetes locales equivalentes se cargaron correctamente. Ahora el runtime copia los paquetes respaldados por enlaces simbólicos a una caché direccionada por contenido de archivos regulares antes de construir MLModel. Los hashes se comprueban antes y después de copiar y al reutilizar; una caché modificada o dañada genera un error. Los paquetes locales de archivos regulares no siguen esta ruta de copia. Consulta USAGE.md para la ubicación de la caché y cómo sobrescribirla.

Reproducibilidad

Todas las exportaciones incluyen coreml_config.json: SHA256 del peso original, revisión del origen, formas, precisión, implementación de atención, versiones de las herramientas, tiempo de conversión y hashes de cada archivo de paquete/tokenizer/configuración. Las exportaciones se niegan a sobrescribir directorios existentes. Una exportación fallida elimina solo su directorio de salida recién creado.

La referencia golden comprometida se generó a partir de la revisión del upstream de Laya sin modificar 573e5b62696ba441230cd6be71d593331b5d23af usando FP32 PyTorch MPS. Incluye los IDs de token de entrada completos y los logits sin redondear. La validación compara esos tokens exactamente y comprueba las respuestas seleccionadas, las probabilidades calibradas, las probabilidades de acción, la contabilidad de tokens y los resultados públicos repetidos.

Para regenerar la referencia golden en un entorno compatible con el 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

Las dependencias exactas de la referencia se registran en el JSON generado. Son distintas del entorno de exportación fijado; Transformers no es una dependencia de runtime ni de exportación de laya-coreml.