Cartão de título principal para Laya em Apple Silicon com o texto 'O port do MLX: 13,42 ms, zero tokens de saída', com a linha de rodapé 'Medições feitas pelo autor do port em um M3 Max declarado; carregamento do modelo excluído.' e o logotipo OrcaRouter no canto inferior direito.
Guides & Insights

Laya no Apple Silicon: o que o porte do MLX traz de vantagem, e o que não traz

Autor

Alistair Wren

Data de publicação

Modelos mais recentes · 20Ver todos os modelos
Benchmarks: Artificial Analysis · atualizado diariamente
Voltar para todas as publicações

Laya é um modelo de decisão que nunca escreve uma frase. A Convai Innovations publicou seus pesos no Hugging Face em 18 de setembro de 2026, e, no dia seguinte, um desenvolvedor chamado mizorewww publicou Laya-MLX — um porte independente que executa todos os três checkpoints do Laya nativamente em Apple Silicon por meio do MLX, sem PyTorch, sem runtime do Transformers e sem chamada à nuvem. Esse porte relata mediana de 13,42 ms para uma pergunta curta em inglês no checkpoint de 421M, 7,39 ms no multilíngue de 322M e zero tokens de saída, em um M3 Max. Enquanto isso, Kev, a outra família aberta que persegue a mesma ideia de decisão tipada, é construída sobre o Qwen3.5-4B-Base e precisou de todo um segundo backend antes de ser utilizável em um Mac, porque o PyTorch não tem kernels para suas camadas DeltaNet na GPU da Apple. Dois projetos, mesma semana, mesmo objetivo, e apenas um deles foi portado de forma limpa. Essa diferença é a história, e é uma história de runtime, não de modelo.

A razão pela qual isto vale um artigo hoje não é que a Laya seja nova. É que até 2026-09-19 não havia como executar um modelo de decisão tipado em um Mac sem arrastar junto uma stack do PyTorch, e a pergunta que um leitor realmente tem — consigo rodar isto no meu laptop, e do que abro mão — finalmente tem uma resposta mensurável. Então, este artigo é sobre o caminho de serving, os números por trás dele e os pontos em que os números deixam de significar o que parecem.

Primeiro, o que Laya não é

Laya não é um LLM. Trata-se de um sistema não autorregressivo: uma única passagem para a frente bidirecional sobre o estado mais as suas perguntas, e a saída são respostas tipadas. Não há decodificação token a token, nem cadeia de pensamento, nem JSON gerado para analisar, nem tokens de saída para cobrar. As três primitivas de resposta são escolha (escolher uma de N opções nomeadas), pontuação (um nível ordinal de rubrica) e noul (uma probabilidade calibrada de que algo seja verdadeiro).

Isso importa para como você lê cada número neste artigo. Quando o port relata 13.42 ms, ele não está relatando 13.42 ms para produzir algumas centenas de tokens como um benchmark de geração faria. Ele está relatando a operação inteira. Comparar a latência de um modelo de decisão com os tokens por segundo de um LLM é comparar duas tarefas diferentes, e qualquer artigo que faça isso — incluindo o post viral "50x mais rápido que o Jev" que circulou após o lançamento — está fazendo uma afirmação que o trabalho subjacente não sustenta.

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.

O que a porta realmente mediu

Estes números são do próprio autor do port, obtidos numa máquina declarada, e devem ser lidos com a máquina e o método anexados. O Laya-MLX mediu-os num M3 Max com 40 núcleos de GPU e 128 GiB de memória unificada, em FP16, com o carregamento do modelo excluído.

• Uma pergunta curta, P50 — 13,42 ms no checkpoint de inglês de 421M, 7,39 ms no checkpoint multilíngue de 322M.

• Uma pergunta curta, P95 — 13,92 ms e 7,79 ms, respetivamente.

• Taxa de transferência de 50 perguntas — 146,8 perguntas por segundo e 395,0 perguntas por segundo.

• Alocação máxima de MLX — 943,6 MiB e 687,6 MiB.

O limite de temporização é a parte que vale a pena ler duas vezes. Ele inclui a preparação do prompt, a tokenização, a construção de tensores, a inferência sincronizada, a calibração e a formatação dos resultados. Ele exclui o carregamento do modelo. A execução de throughput com 50 perguntas usou batch_size=64, enquanto o padrão da API é 16, então esse par de números descreve uma carga de trabalho deliberadamente em lote, e não o custo de uma única chamada interativa. Diferentes comprimentos de entrada, diferentes números de perguntas e diferentes condições de execução afetam o resultado. Essas ressalvas são a diferença entre um número e um benchmark, e o próprio port as declara.

O piso de memória é o valor com base no qual a maioria dos leitores vai agir, e é o menos ambíguo do conjunto: menos de um gigabyte de alocação de pico do MLX para uma única pergunta curta, em ambos os checkpoints. Isso não é uma afirmação sobre o consumo total do seu Mac — o SO, seu terminal e o processo Python ficam todos ao lado dele —, mas é um piso real, e fica cerca de três ordens de magnitude abaixo do que exige rodar um modelo generativo de porte médio localmente.

A verificação de fidelidade é o resultado mais interessante.

Um port rápido que responde de forma diferente do modelo que porta não tem valor, e é aqui que o projeto fez o trabalho que importa. Todos os três checkpoints corresponderam à resposta selecionada do upstream em 63 de 63 perguntas de validação, tanto em FP32 quanto em FP16 — 378 de 378 comparações. Cada configuração também executou 100 chamadas repetidas e determinísticas, sem crescimento medido de memória ativa, e todos os 36 arquivos de pesos publicados passaram por verificação remota rigorosa de checksum.

Leia o escopo com honestidade: isso mede a fidelidade nesses fixtures, não a exatidão em todas as perguntas possíveis. Isso diz que o porte é fiel ao Laya. Não diz nada sobre se o Laya está certo.

Independente, mantido pela comunidade e ainda não consta na lista

O porte diz isto sobre si mesmo, duas vezes: é um porte independente do MLX, não um lançamento oficial da Convai Innovations. O treinamento e o ajuste fino de RLCD permanecem no upstream. Os pesos são creditados à Convai Innovations. Apache-2.0 nos dois lados.

A forma como o upstream trata isso é mais reveladora do que qualquer aviso de isenção de responsabilidade. O README do Laya contém uma lista de Ferramentas da Comunidade e, em 2026-09-23, ela tem quatro entradas: omp-laya-judge, laya-adk-toolkit, laya-Ascend para NPUs Huawei Ascend, e laya-apple — um runtime para Apple Silicon que usa a GPU MLX e o Neural Engine. Essa quarta entrada chegou por meio do pull request #260, mesclado em 2026-09-23. O porte sobre o qual este artigo trata não está entre os quatro. A lista do upstream agora direciona os leitores de Apple Silicon para um projeto da comunidade diferente daquele que foi lançado primeiro e tem os benchmarks.

O próprio rastreador de issues do upstream diz o resto. A issue #50, "Apple silicon ports", aberta em 2026-09-21, continua aberta; o mantenedor respondeu no mesmo dia que o suporte a Apple Silicon está sendo acompanhado e que ports da comunidade como o Laya-MLX estão explorando inferência nativa em Metal, e então respondeu novamente em 2026-09-23 com uma frase que vale citar exatamente: "The MLX port remains community-maintained." A correção do lado do PyTorch — autocast do MPS e uma correção de RoPE do transformers 4.x — chegou como pull request #273, mesclada em 2026-09-23, com um revisor naquele thread sinalizando que ela ainda precisa ser combinada com a refatoração de autocast separada na #109, que continua aberta. E a issue #52, aberta em 2026-09-21, relata um sidecar do Laya-MLX que cresceu para cerca de 21,7 GB de memória Metal ao longo de várias horas de operação, com vmmap atribuindo cerca de 21,4 GB ao subsistema gráfico em vez do heap do Python; ela propõe limitar o cache do alocador e limpá-lo após cada inferência, e continua aberta.

Juntando tudo isso, a resposta prática é: este runtime não tem o aval do upstream, é mantido pela comunidade segundo a própria descrição do mantenedor, e a única questão de memória que importa para um sidecar de longa duração está sendo trabalhada em público, em vez de corrigida em uma versão.

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.

Posso executá-lo no meu laptop e do que eu abro mão?

A instalação é um único comando pip, e o porte publica pesos FP16 pré-convertidos, então você não converte nada por conta própria:

pip install laya-mlx

Então import laya_mlx as laya, agent = laya.load("aac6fef/laya-mlx"), e chame agent.predict(state, questions). Os requisitos são Apple Silicon, Python 3.11+ e macOS 14+. O ambiente medido foi macOS 27.2, Python 3.12.13 e MLX 0.32.2 — e o port observa que a versão do MLX que ele usou distribuía wheels para macOS 14, 15 e 26, enquanto o instalador selecionou a 26, e que versões mais antigas do macOS suportadas não foram testadas naquela máquina.

Do que você abre mão, dimensão por dimensão:

• FP16 versus FP32 — O FP16 é o padrão e a origem de todos os números de destaque acima. O FP32 proporciona uma concordância numérica mais próxima com o upstream, e as probabilidades podem diferir ligeiramente entre precisões mesmo quando o rótulo selecionado coincide. O BF16 pode ser solicitado, mas não faz parte da matriz de validação publicada, portanto, considere-o como não testado.

• Piso de memória versus margem — menos de 1 GiB de alocação de pico do MLX para uma pergunta curta é confortável em qualquer Mac da série M. Isso não é uma afirmação sobre carga de servidor sustentada, e a issue #52 é o motivo para se ter cuidado se você planeja executar isto como um sidecar de longa duração em vez de uma chamada de biblioteca.

• Multilíngue versus inglês — o checkpoint multilíngue de 322M é o mais rápido dos dois e o que cobre mais de 100 idiomas, mas o port carrega deliberadamente o aviso do upstream: os checkpoints em inglês não substituem o multilíngue. O roteamento entre eles é o padrão pretendido, e não uma mera conveniência.

• Chancelado pelo upstream versus mantido pela comunidade — é a segunda. Nada nas notas de versão do upstream promete que este port continuará funcionando ao longo das mudanças no upstream.

• Velocidade versus calibração — um porte rápido não corrige um bucket de calibração que chega com confiança excessiva. O upstream restringe as temperaturas ajustadas a [0.5, 5.0], e o bucket choice:11+ enviado é 0.1006, o que aguçaria os logits cerca de dez vezes e reportaria um cara ou coroa como quase certeza. Temperaturas de calibração ajustadas existem por um motivo; ajuste-as usando seus próprios dados reservados antes de ramificar com base em uma probabilidade.

Vale a pena carregar mais dois limites, ambos do próprio rastreador do upstream. action.act_probability atualmente não carrega nenhum sinal utilizável — ele lê 1.0 para quase toda entrada, e seus logits brutos se opuseram à correção com um AUROC de 0.30 em 396 decisões rotuladas (issue #185). Faça o gate em confidence, em vez disso, que alcança 0.77 nos mesmos itens. E as perguntas de noul podem seguir seus rótulos de opção em vez do estado (issue #156) — o próprio card do upstream relata um "no" confiante em entradas claramente positivas, de forma mais acentuada no checkpoint em inglês. A solução alternativa que ele sugere não é recorrer a um modelo diferente, mas reformular a pergunta: fazê-la como uma choice de duas opções com chaves neutras (A/B) e sua formulação de sim/não como as descrições das opções.

Por que um modelo de decisão é portado de forma limpa e o outro não

O contraste aqui é arquitetural, e é a coisa mais útil deste artigo para quem precisa escolher entre as duas famílias.

A espinha dorsal do Laya é o ModernBERT-large, um codificador bidirecional construído inteiramente com atenção. A atenção é o que a pilha de GPU da Apple faz de melhor, e é nisso que a MLX concentrou seus esforços. Portanto, o porte é uma reimplementação de camadas que já tinham caminhos rápidos: o codificador, as camadas Transformer da cabeça de decisão, a cabeça de pontuação e a cabeça de ação rodam todos em MLX, e a tokenização ainda passa pelo tokenizador Rust do Hugging Face.

Os backbones do Kev são bases do Qwen3.5, e o Qwen3.5 mistura camadas de atenção com camadas Gated DeltaNet. O DeltaNet é recorrente e ignora máscaras de atenção. Isso tem duas consequências. Primeiro, cada pergunta tem de rodar como sua própria linha em vez de compartilhar uma única sequência mascarada, o que o projeto Kev resolve calculando o estado uma vez e reutilizando seu cache por linha. Segundo — e esta é a parte que dói num Mac — não havia kernels do PyTorch para essas camadas na GPU da Apple, então o PyTorch recorreu ao código de referência. O jaredpalmer/kev-4b model card ainda carrega o limite resultante em linguagem simples: uma requisição de cinco perguntas que leva 0,17 s na versão Qwen3 do Kev-4B leva 0,78 s em bf16 num M5.

Verifique a redação atual antes de citar isso, pois ela mudou. O README do repositório Kev agora diz que o servidor executa os modelos Qwen3.5 por meio do MLX em Apple Silicon, e publica seus próprios números de M5 para uma solicitação de cinco perguntas com três opções cada em um estado de aproximadamente 270 tokens: Kev-4B a 721 ms em um estado novo e 136 ms em um estado repetido por meio do cache de prefixo, contra 3.302 ms e 847 ms no caminho PyTorch bf16 MPS. O Kev-0.8B fica em 149 ms e 28 ms. Os modelos Qwen3 da geração anterior ainda rodam em PyTorch MPS puro, e o projeto os considera uma ótima escolha em um Mac.

Cuidado para não transformar isso em um resultado de corrida. Estas não são medições frente a frente. Os 13,42 ms do Laya-MLX são uma pergunta curta em um M3 Max; os 721 ms do Kev são cinco perguntas com três opções cada em um estado de ~270 tokens em um M5. Contagens de perguntas diferentes, contagens de opções diferentes, comprimentos de estado diferentes, máquinas diferentes, runtimes diferentes. O que é verificável e vale a pena comparar é a forma do problema, não um vencedor: um encoder de atenção pura é portado para Apple Silicon sem dificuldade, e um modelo híbrido de atenção linear precisou de todo um segundo backend antes de ser utilizável ali.

Para que serve realmente um modelo de decisão

Deixe de lado os benchmarks e o caso de uso honesto é restrito, e o próprio projeto admite isso: Laya é uma base rápida para especializar, não um mecanismo de decisão zero-shot. No benchmark de decisões tipadas da própria Convai, os dois checkpoints base pontuam 0,362 e 0,342 zero-shot contra uma linha de base de classe majoritária de 0,461 e uma aleatória de 0,318. Eles ficam abaixo da linha que você obteria ao responder sempre o rótulo mais comum. O número de destaque 0,766 pertence a laya-typed-decisions, o checkpoint ajustado com fine-tuning no próprio conjunto de treino desse benchmark, e nunca deve ser citado como capacidade geral.

A comparação publicada da Convai com o TypeSafe Jev 1.13.0 vale a pena ser lida exatamente por esse motivo, e é rotulada cuidadosamente do lado deles: cada número do Laya é o que o roteador realmente retorna, e os números do Jev são valores publicados por terceiros que a Convai nunca mediu porque não tem acesso à API do TypeSafe. Nessa comparação, o Laya roteado pontua 0,766 contra os 0,727 do Jev em decisões tipadas, com ECE pós-temperatura de 0,081 contra 0,246, e latência p50 de 32,8 ms contra 236–276 ms em uma Tesla T4 — uma diferença de 7,8x em uma pergunta. Esse é o número a citar. O número "50x mais rápido que o Jev" que se espalhou nas redes sociais não aparece na documentação do projeto nem em seus benchmarks, e a comparação publicada do próprio projeto não o sustenta. O Jev também lidera onde lidera: no Banking77, o Jev pontua 0,870 contra os 0,425 do Laya, porque as opções do Laya compartilham um orçamento fixo de tokens e 77 rótulos deixam aproximadamente três a quatro tokens cada.

Portanto, a forma de um deployment real é uma cabeça de decisão que é barata, local e estreita — encaminhar um ticket, pontuar urgência, responder a um portão de sim/não — com algo generativo por trás dela para a parte que precisa escrever. O modelo de decisão faz a chamada tipada em milissegundos e escala. A metade generativa é um modelo diferente num runtime diferente, e é aí que um roteador ganha o seu lugar: mais de 200 modelos atrás de uma única chave, ao preço de tabela do provedor e sem markup, para que uma alteração de preço de um fornecedor fique ativa no mesmo dia, e failover automático quando um provedor se degrada a meio da execução. O OrcaRouter não serve Laya, e não serve Kev nem Jev — a família Qwen3.5 está na nossa lista de modelos, e os próprios modelos de decisão não estão. O que cobrimos é a metade generativa dessa pilha, que é a metade que você chama em cada pedido que a cabeça de decisão escala.

Há mais um motivo para manter as duas metades separadas em vez de recorrer a um único modelo para fazer as duas coisas. Uma cabeça de decisão local que custa zero tokens de saída e nunca toca uma rede é um tipo diferente de dependência de uma chamada de API: continua funcionando quando a rede não funciona, e seu custo não escala com a quantidade de texto que ela lê. É essa a propriedade pela qual vale a pena pagar. Todo o resto neste artigo trata de quanto você paga por ela em fidelidade, memória e manutenção.

Quem deve executá-lo, e quem deve esperar

Execute o Laya-MLX se você estiver em um Mac da série M, suas decisões forem restritas — uma escolha entre opções nomeadas, uma pontuação de rubrica, um filtro sim/não — e você tiver rótulos para ajuste fino ou estiver preparado para ajustar temperaturas de calibração por conta própria. A instalação é um único comando, o mínimo de memória é inferior a um gigabyte, e o trabalho de fidelidade foi feito e publicado.

Espere, se você precisa de garantias de suporte upstream, se está executando um sidecar de longa duração e quer que a questão do crescimento de memória seja resolvida em uma release em vez de uma issue aberta, ou se suas perguntas são abertas. Um encoder não autorregressivo respondendo a "o que devo fazer a seguir" não é uma versão menor de um LLM fazendo a mesma coisa. É um instrumento diferente, e só lê bem quando a pergunta já está moldada para ele.

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 neste artigo1

Detectado a partir deste artigo · Benchmarks: Artificial Analysis · atualizado diariamente