Tarjeta de título principal para Laya en Apple Silicon que muestra «El port de MLX: 13,42 ms, cero tokens de salida», con la línea de pie de página «Mediciones del autor del port en un M3 Max declarado; carga del modelo excluida.» y el logotipo de OrcaRouter en la esquina inferior derecha.
Guides & Insights

Laya en Apple Silicon: lo que te aporta el port a MLX y lo que no

Autor

Alistair Wren

Fecha de publicación

Últimos modelos · 20Ver todos los modelos
Benchmarks: Artificial Analysis · actualizado a diario
Volver a todas las publicaciones

Laya es un modelo de decisión que nunca escribe una frase. Convai Innovations publicó sus pesos en Hugging Face el 18/09/2026, y al día siguiente un desarrollador llamado mizorewww publicó Laya-MLX — un port independiente que ejecuta los tres checkpoints de Laya de forma nativa en Apple Silicon a través de MLX, sin PyTorch, sin runtime de Transformers y sin ninguna llamada a la nube. Ese port reporta una mediana de 13,42 ms para una pregunta breve en inglés en el checkpoint de 421M, 7,39 ms en el multilingüe de 322M y cero tokens de salida, en un M3 Max. Mientras tanto, Kev, la otra familia abierta que persigue la misma idea de decisión tipada, está construida sobre Qwen3.5-4B-Base y necesitó todo un segundo backend antes de poder usarse en un Mac, porque PyTorch no tiene kernels para sus capas DeltaNet en la GPU de Apple. Dos proyectos, la misma semana, el mismo objetivo, y solo uno de ellos se portó sin problemas. Esa diferencia es la historia, y es una historia de runtime más que una historia de modelo.

La razón por la que esto merece un artículo hoy no es que Laya sea una novedad. Es que hasta el 2026-09-19 no había forma de ejecutar un modelo de decisiones tipadas en un Mac sin arrastrar consigo todo un stack de PyTorch, y la pregunta que un lector realmente tiene —¿puedo ejecutar esto en mi portátil y a qué renuncio?— por fin tiene una respuesta medible. Así que este artículo trata sobre la ruta de servicio, los números que hay detrás y los puntos donde los números dejan de significar lo que parecen.

Primero, lo que Laya no es

Laya no es un LLM. No es autorregresivo: una única pasada bidireccional hacia delante sobre el estado más tus preguntas, y de ahí salen respuestas tipadas. No hay decodificación token a token, ni cadena de pensamiento, ni JSON generado que parsear, ni tokens de salida que facturar. Las tres primitivas de respuesta son choice (elegir una de N opciones con nombre), score (un nivel de rúbrica ordinal) y noul (una probabilidad calibrada de que algo sea verdadero).

Eso importa para cómo lees cada número de este artículo. Cuando el port reporta 13,42 ms, no está reportando 13,42 ms para producir unos cientos de tokens como lo haría un benchmark de generación. Está reportando la operación completa. Comparar la latencia de un modelo de decisión con los tokens por segundo de un LLM es comparar dos tareas diferentes, y cualquier artículo que lo haga —incluido el post viral «50 veces más rápido que Jev» que circuló tras el lanzamiento— está haciendo una afirmación que el trabajo subyacente no respalda.

Screenshot of the Hugging Face model page for convaiinnovations/laya, showing the Apache 2.0 licence, the tags Text Classification, Transformers, Safetensors, system-one and calibrated-decisions, a model size of 0.4B params, the description of Laya as a multilingual, non-autoregressive System 1 decision model that never generates text, and the start of the checkpoint table listing convaiinnovations/laya on a ModernBERT-large backbone at 421M parameters with 512-token context.

Lo que el puerto realmente midió

Estas cifras son del propio autor del port, tomadas en una máquina declarada, y deben leerse con la máquina y el método adjuntos. Laya-MLX las midió en un M3 Max con 40 núcleos de GPU y 128 GiB de memoria unificada, en FP16, excluyendo la carga del modelo.

• Una pregunta breve, P50 — 13,42 ms en el checkpoint inglés de 421M, 7,39 ms en el checkpoint multilingüe de 322M.

• Una pregunta breve, P95 — 13,92 ms y 7,79 ms respectivamente.

• Rendimiento de 50 preguntas — 146,8 preguntas por segundo y 395,0 preguntas por segundo.

• Asignación máxima de MLX — 943,6 MiB y 687,6 MiB.

El límite de la medición temporal es la parte que vale la pena leer dos veces. Incluye la preparación del prompt, la tokenización, la construcción de tensores, la inferencia sincronizada, la calibración y el formato de resultados. Excluye la carga del modelo. La ejecución de rendimiento de 50 preguntas usó batch_size=64, mientras que la API usa por defecto 16, así que ese par de números describe una carga de trabajo deliberadamente por lotes en lugar de lo que cuesta una única llamada interactiva. Distintas longitudes de entrada, distintos números de preguntas y distintas condiciones de ejecución alteran el resultado. Esas salvedades son la diferencia entre un número y un benchmark, y el propio puerto las declara.

El mínimo de memoria es la cifra sobre la que la mayoría de los lectores actuará, y es la menos ambigua del conjunto: menos de un gigabyte de asignación máxima de MLX para una única pregunta corta, en ambos checkpoints. Eso no es una afirmación sobre la huella total de tu Mac — el sistema operativo, tu terminal y el proceso de Python se suman a ello —, pero es un mínimo real, y está aproximadamente tres órdenes de magnitud por debajo de lo que exige ejecutar un modelo generativo de tamaño mediano localmente.

La comprobación de fidelidad es el resultado más interesante

Un port rápido que responde de forma distinta al modelo que porta no vale nada, y aquí es donde el proyecto hizo el trabajo que importa. Los tres checkpoints coincidieron con la respuesta seleccionada de upstream en 63 de 63 preguntas de validación, tanto en FP32 como en FP16 — 378 de 378 comparaciones. Cada configuración también ejecutó 100 llamadas repetidas y deterministas sin crecimiento medido de la memoria activa, y los 36 archivos de pesos publicados superaron una verificación remota estricta de checksums.

Lee el alcance con honestidad: eso mide la fidelidad en esos fixtures, no la exactitud sobre todas las preguntas posibles. Te dice que el port es fiel a Laya. No te dice nada sobre si Laya tiene razón.

Independiente, mantenido por la comunidad, y aún así no está en la lista

El port dice esto sobre sí mismo, dos veces: es un port independiente de MLX, no una versión oficial de Convai Innovations. El entrenamiento y el ajuste fino de RLCD permanecen en upstream. Los pesos se acreditan a Convai Innovations. Apache-2.0 en ambos lados.

La forma en que el proyecto upstream lo trata es más reveladora que cualquier aviso legal. El README de Laya incluye una lista de Herramientas de la Comunidad y, a fecha de 2026-09-23, contiene cuatro entradas: omp-laya-judge, laya-adk-toolkit, laya-Ascend para NPU de Huawei Ascend, y laya-apple — un runtime para Apple Silicon que usa la GPU de MLX y el Neural Engine. Esa cuarta entrada llegó mediante la pull request #260, fusionada el 2026-09-23. El port del que trata este artículo no está entre las cuatro. La lista de upstream ahora dirige a los lectores de Apple Silicon a un proyecto comunitario distinto del que se publicó primero y tiene las pruebas comparativas.

El propio rastreador de incidencias de Upstream dice el resto. La incidencia #50, «Apple silicon ports», abierta el 2026-09-21, sigue abierta; el mantenedor respondió ese mismo día que el soporte para Apple Silicon se está monitoreando y que ports comunitarios como Laya-MLX están explorando inferencia nativa en Metal, y luego volvió a responder el 2026-09-23 con una frase que vale la pena citar textualmente: «El port de MLX sigue siendo mantenido por la comunidad». La corrección del lado de PyTorch —autocast de MPS y una corrección de RoPE de transformers 4.x— se integró como el pull request #273, fusionado el 2026-09-23, con un revisor en ese hilo que señaló que todavía necesita combinarse con la refactorización de autocast separada en #109, que sigue abierta. Y la incidencia #52, abierta el 2026-09-21, informa de un sidecar de Laya-MLX que creció hasta aproximadamente 21,7 GB de memoria de Metal durante varias horas de funcionamiento, con vmmap atribuyendo unos 21,4 GB al subsistema gráfico y no al heap de Python; propone acotar la caché del asignador y vaciarla después de cada inferencia, y sigue abierta.

Si juntamos todo esto, la respuesta práctica es: este runtime no está avalado por el upstream, según la propia descripción de su mantenedor lo mantiene la comunidad, y la única cuestión de memoria que importa para un sidecar de larga ejecución se está trabajando en público en lugar de resolverse en una versión.

Screenshot of the GitHub repository page for mizorewww/laya-mlx, showing the description 'Native MLX runtime for Laya typed decision models — 7–14 ms short decisions on M3 Max. No text generation, PyTorch, or cloud API.', the Apache-2.0 licence label, 5.9k stars, 432 forks, 4 open issues and 6 open pull requests.

¿Puedo ejecutarlo en mi portátil y a qué renuncio?

La instalación es un único comando pip, y el port publica pesos FP16 preconvertidos, así que no necesitas convertir nada por tu cuenta:

pip install laya-mlx

Luego import laya_mlx as laya, agent = laya.load("aac6fef/laya-mlx"), y llama a agent.predict(state, questions). Los requisitos son Apple Silicon, Python 3.11+ y macOS 14+. El entorno medido fue macOS 27.2, Python 3.12.13 y MLX 0.32.2 — y el port señala que la versión de MLX que utilizó incluía wheels para macOS 14, 15 y 26, mientras que el instalador seleccionó la de 26, y que las versiones compatibles más antiguas de macOS no se probaron en esa máquina.

Lo que renuncias, dimensión por dimensión:

• FP16 frente a FP32 — FP16 es el predeterminado y la fuente de cada número destacado anterior. FP32 proporciona una concordancia numérica más cercana con upstream, y las probabilidades pueden diferir ligeramente entre precisiones incluso cuando la etiqueta seleccionada coincide. Se puede solicitar BF16, pero no forma parte de la matriz de validación publicada, así que trátalo como no probado.

• Suelo de memoria frente a margen de holgura: menos de 1 GiB de asignación máxima de MLX para una pregunta corta es cómodo en cualquier Mac de la serie M. No constituye una afirmación sobre carga sostenida del servidor, y la incidencia #52 es la razón para tener cuidado si planeas ejecutar esto como un sidecar de larga duración en lugar de una llamada a biblioteca.

• Multilingüe frente a inglés — el checkpoint multilingüe de 322M es el más rápido de los dos y el que cubre más de 100 idiomas, pero el port traslada deliberadamente la advertencia de upstream: los checkpoints en inglés no sustituyen al multilingüe. Enrutar entre ellos es el patrón previsto, no un simple extra.

• Bendecido por upstream frente a mantenido por la comunidad: es lo segundo. Nada en las notas de la versión de upstream promete que este port siga funcionando a través de los cambios de upstream.

• Velocidad frente a calibración — un port rápido no arregla un bucket de calibración que se entrega con exceso de confianza. Upstream limita las temperaturas ajustadas a [0.5, 5.0], y el choice:11+ bucket entregado es 0.1006, lo que agudizaría los logits aproximadamente diez veces y reportaría un lanzamiento de moneda como casi certeza. Las temperaturas de calibración ajustadas existen por una razón; ajústalas con tus propios datos de validación reservados antes de ramificar en función de una probabilidad.

Merece la pena tener en cuenta dos límites más, ambos del propio tracker de upstream. action.act_probability actualmente no aporta ninguna señal utilizable: marca 1.0 para casi todas las entradas, y sus logits sin procesar se evaluaron frente a la corrección con un AUROC de 0.30 en 396 decisiones etiquetadas (issue #185). Condiciona a confidence en su lugar, que alcanza 0.77 en los mismos elementos. Y las preguntas noul pueden seguir las etiquetas de sus opciones en lugar del estado (issue #156): la propia tarjeta de upstream informa de un «no» con confianza ante una entrada claramente positiva, de forma más acusada en el checkpoint en inglés. La solución alternativa que sugiere no es recurrir a un modelo diferente, sino reformular la pregunta: plantéala como una choice de dos opciones con claves neutras (A/B) y tu redacción de sí/no como las descripciones de las opciones.

¿Por qué un modelo de decisión se traslada limpiamente y el otro no?

El contraste aquí es arquitectónico, y es lo más útil de este artículo para cualquiera que elija entre las dos familias.

El backbone de Laya es ModernBERT-large, un codificador bidireccional construido enteramente a partir de atención. La atención es lo que mejor se le da a la pila de GPU de Apple, y es en lo que MLX ha invertido sus esfuerzos. Así que el port es una reimplementación de capas que ya tenían rutas rápidas: el codificador, las capas Transformer de la cabeza de decisión, la cabeza de puntuación y la cabeza de acción se ejecutan todas en MLX, y la tokenización sigue pasando por el tokenizador Rust de Hugging Face.

Los backbones de Kev son bases de Qwen3.5, y Qwen3.5 mezcla capas de atención con capas de Gated DeltaNet. DeltaNet es recurrente e ignora las máscaras de atención. Eso tiene dos consecuencias. Primero, cada pregunta tiene que ejecutarse como su propia fila en lugar de compartir una única secuencia enmascarada, algo que el proyecto Kev maneja calculando el estado una vez y reutilizando su caché por fila. Segundo —y esta es la parte que duele en un Mac— no había kernels de PyTorch para esas capas en la GPU de Apple, así que PyTorch recurrió al código de referencia. La tarjeta del modelo jaredpalmer/kev-4b todavía recoge la limitación resultante en lenguaje sencillo: una solicitud de cinco preguntas que tarda 0,17 s en la versión de Kev-4B con Qwen3 tarda 0,78 s en bf16 en un M5.

Comprueba la redacción actual antes de citar eso, porque ha cambiado. El README del repositorio Kev ahora dice que, en su lugar, el servidor ejecuta los modelos Qwen3.5 mediante MLX en Apple Silicon, y publica sus propias cifras de M5 para una solicitud de cinco preguntas con tres opciones cada una sobre un estado de aproximadamente 270 tokens: Kev-4B a 721 ms en un estado nuevo y 136 ms en un estado repetido a través de la caché de prefijos, frente a 3.302 ms y 847 ms en la ruta MPS de PyTorch bf16. Kev-0.8B se sitúa en 149 ms y 28 ms. Los modelos Qwen3 de la generación anterior todavía se ejecutan en PyTorch MPS simple, y el proyecto los considera una buena elección en un Mac.

Ten cuidado de no convertir eso en un resultado de carrera. Estas no son mediciones cara a cara. Los 13,42 ms de Laya-MLX corresponden a una pregunta corta en un M3 Max; los 721 ms de Kev corresponden a cinco preguntas con tres opciones cada una sobre un estado de ~270 tokens en un M5. Diferentes cantidades de preguntas, diferentes cantidades de opciones, diferentes longitudes de estado, diferentes máquinas, diferentes entornos de ejecución. Lo que es verificable y merece compararse es la forma del problema, no un ganador: un codificador de atención pura se porta a Apple Silicon sin dificultad, y un modelo híbrido de atención lineal necesitó todo un segundo backend antes de poder usarse allí.

Para qué sirve realmente un modelo de decisión

Si se dejan de lado los benchmarks, el caso de uso honesto es limitado, y el propio proyecto lo dice: Laya es una base rápida para especializarse, no un motor de decisiones zero-shot. En el propio benchmark de decisiones tipadas de Convai, los dos checkpoints base obtienen 0,362 y 0,342 zero-shot frente a una línea base de clase mayoritaria de 0,461 y una aleatoria de 0,318. Están por debajo de la línea que se obtendría al responder siempre la etiqueta más común. La cifra destacada de 0,766 pertenece a laya-typed-decisions, el checkpoint ajustado con la propia partición de entrenamiento de ese benchmark, y nunca debería citarse como capacidad general.

La comparación publicada por Convai contra TypeSafe Jev 1.13.0 vale la pena leerla exactamente por esta razón, y está etiquetada cuidadosamente de su lado: cada cifra de Laya es lo que el enrutador realmente devuelve, y las cifras de Jev son números publicados por terceros que Convai nunca midió porque no tiene acceso a la API de TypeSafe. En esa comparación, el Laya enrutado obtiene 0.766 frente a 0.727 de Jev en decisiones tipadas, con un ECE posterior a la temperatura de 0.081 frente a 0.246, y una latencia p50 de 32.8 ms frente a 236–276 ms en una Tesla T4 — una diferencia de 7.8x en una pregunta. Ese es el número que se debe citar. La cifra de «50x más rápido que Jev» que se difundió en las redes sociales no aparece en la documentación del proyecto ni en sus benchmarks, y la propia comparación publicada del proyecto no la respalda. Jev también lidera donde lidera: en Banking77, Jev obtiene 0.870 frente a 0.425 de Laya, porque las opciones de Laya comparten un presupuesto fijo de tokens y 77 etiquetas dejan aproximadamente de tres a cuatro tokens cada una.

Así que la forma de un despliegue real es una cabeza de decisión que es barata, local y estrecha — enrutar un ticket, puntuar la urgencia, responder a una puerta de sí/no — con algo generativo detrás para la parte que necesita escribir. El modelo de decisión toma la llamada tipada en milisegundos y escala. La mitad generativa es un modelo diferente en un runtime diferente, y ahí es donde un enrutador se gana su lugar: más de 200 modelos detrás de una sola clave al precio de lista del proveedor sin recargo, así que un cambio de precio del proveedor está activo el mismo día, y conmutación por error automática cuando un proveedor se degrada a mitad de ejecución. OrcaRouter no sirve a Laya, y no sirve a Kev ni a Jev — la familia Qwen3.5 está en nuestra lista de modelos, y los modelos de decisión en sí no lo están. Lo que cubrimos es la mitad generativa de esa pila, que es la mitad a la que llamas en cada solicitud que la cabeza de decisión escala.

Hay una razón más para mantener las dos mitades separadas en lugar de recurrir a un solo modelo que haga ambas cosas. Una cabeza de decisión local que no cuesta tokens de salida y nunca toca la red es un tipo de dependencia distinto del de una llamada a una API: sigue funcionando cuando la red no funciona, y su coste no escala con la cantidad de texto que lee. Esa es la propiedad por la que vale la pena pagar. Todo lo demás en este artículo trata sobre cuánto pagas por ella en fidelidad, memoria y mantenimiento.

¿Quién debería ejecutarlo y quién debería esperar?

Ejecuta Laya-MLX si tienes un Mac de la serie M, tus decisiones están restringidas —una elección entre opciones con nombre, una puntuación de rúbrica, una compuerta de sí/no— y o bien tienes etiquetas con las que hacer ajuste fino, o estás preparado para ajustar tú mismo las temperaturas de calibración. La instalación es un solo comando, el mínimo de memoria está por debajo de un gigabyte, y el trabajo de fidelidad ya se ha hecho y publicado.

Espera si necesitas garantías de soporte de upstream, si ejecutas un sidecar de larga duración y quieres que la cuestión del crecimiento de la memoria se resuelva en una versión en lugar de en un issue abierto, o si tus preguntas son de final abierto. Un codificador no autorregresivo que responde «qué debería hacer a continuación» no es una versión más pequeña de un LLM que hace lo mismo. Es un instrumento diferente, y solo se lee bien cuando la pregunta ya está formulada para él.

A generated two-column scoreboard for Laya-MLX on Apple Silicon. Left column 'Laya 421M English': One short question P50 13.42 ms, P95 13.92 ms, 50-question throughput 146.8 q/s, Peak MLX allocation 943.6 MiB, Output tokens zero, Precision FP16. Right column 'Laya 322M multilingual': P50 7.39 ms, P95 7.79 ms, 395.0 q/s, 687.6 MiB, zero output tokens, FP16. Footer 'Port author measurements on a stated M3 Max (40-core GPU, 128 GiB); model loading excluded.', with the OrcaRouter logo in the bottom-right corner.

Comparados en este artículo1

Detectado en este artículo · Benchmarks: Artificial Analysis · actualizado a diario