MLX no Apple Silicon: quando você precisa do seu próprio modelo, não o da Apple
O framework Foundation Models da Apple coloca um único modelo nas suas mãos: o do sistema, lacrado, gratuito e atualizado no cronograma da Apple. Para a maior parte do trabalho de linguagem on-device, essa é a ferramenta certa, e tentar ir além dela é um erro. Mas alguns trabalhos exigem um modelo que você escolhe: um LLM open-weight específico, uma versão que você fixa, um fine-tune treinado com seus próprios dados ou uma capacidade que o modelo do sistema não tem. Quando você precisa do seu próprio modelo rodando on-device, a camada abaixo do Foundation Models é o MLX1.
O MLX é o framework de arrays da Apple para machine learning no Apple Silicon, com uma API em Swift (MLX Swift) que você incorpora diretamente em um app2. Ele não é um framework de sistema que você chama; é uma biblioteca que você distribui, junto com os pesos do modelo. Essa diferença é toda a troca, e entendê-la é como você decide se vale descer uma camada ou ficar onde a Apple colocou você.
TL;DR
- O MLX é um framework de arrays no estilo do NumPy, construído para o Apple Silicon, com avaliação lazy, transformações de função componíveis e um backend Metal2.
- O modelo de memória unificada é o motivo de funcionar em um celular. Os arrays vivem em um único pool de memória que a CPU e a GPU compartilham, então o MLX roda em ambas sobre os mesmos buffers, sem o imposto de cópia de host para device3.
- Rode um LLM open-weight on-device com
LLMModelFactory, apontando para um modelo quantizado comomlx-community/Llama-3.2-3B-Instruct-4bit, e então gere texto através de umaChatSession4. - Faça o fine-tune com adaptadores LoRA: treine um pequeno adaptador, distribua o
adapters.safetensors, e oload(into:)troca as camadasLineardo modelo base porLoRALinearem tempo de execução5. - O custo do seu próprio modelo: tamanho do app (os pesos são grandes), pressão de memória, ausência de integração com o sistema, e você é dono de cada atualização. O Foundation Models não tem nenhum desses custos porque a Apple os paga.
O que é o MLX e por que o Apple Silicon o torna possível
O MLX oferece arrays e operações que se parecem com o NumPy, além das transformações de que o machine learning precisa: diferenciação automática, vetorização e avaliação lazy que constrói um grafo de computação e só o executa quando você lê um resultado2. Por si só, isso descreve uma dúzia de frameworks. O que faz o MLX rodar um modelo de bilhões de parâmetros em um dispositivo no seu bolso é o modelo de memória.
Em uma GPU de desktop, os dados ficam na RAM do sistema e você os copia por um barramento até a memória separada da GPU para computar, e depois copia os resultados de volta. Essa cópia é o imposto, e para um modelo grande ele é brutal. O Apple Silicon tem memória unificada: um único pool que a CPU, a GPU e o Neural Engine endereçam diretamente. O MLX é construído em torno desse fato3. Um array não está “na CPU” ou “na GPU”; ele está na memória, e qualquer processador opera sobre ele no próprio lugar. Sem cópias, sem imposto de barramento. Um modelo de 3 bilhões de parâmetros quantizado para 4 bits cabe em alguns gigabytes e roda sem as idas e vindas que tornariam o mesmo trabalho impraticável em uma máquina de GPU dedicada com memória semelhante. A decisão de hardware que a Apple tomou anos atrás é a razão de a inferência on-device de um modelo de verdade ser viável; e a arquitetura tile-based de memória unificada é o substrato sobre o qual o MLX se apoia.
Rodando um LLM on-device
O caminho de “quero um modelo específico” até o texto na tela é curto. A camada de LLM do MLX Swift carrega um modelo quantizado do Hugging Face Hub e o roda4:
let container = try await LLMModelFactory.shared.loadContainer(
from: HubClient.default,
using: TokenizersLoader(),
configuration: .init(id: "mlx-community/Llama-3.2-3B-Instruct-4bit")
)
let session = ChatSession(container)
let response = try await session.respond(to: "Summarize this in one line: \(text)")
Para uma UI token a token, gere um stream e renderize os fragmentos conforme eles chegam4:
let input = try await container.prepare(input: UserInput(prompt: prompt))
let stream = try await container.generate(input: input, parameters: GenerateParameters())
for await event in stream {
if case let .chunk(text) = event { /* append to UI */ }
}
Dois detalhes carregam a maior parte do peso prático. Primeiro, o 4bit no ID do modelo não é um adorno opcional: a quantização é o que faz o modelo caber na memória e rodar em velocidade utilizável em um dispositivo. Você distribui pesos de 4 bits (ou menos), não em precisão total. Segundo, os pesos são grandes mesmo quantizados, então você decide deliberadamente se os empacota no app (instantâneo, mas um download pesado) ou os baixa no primeiro lançamento (binário enxuto, mas com uma espera e um caminho de falha para tratar). O Foundation Models nunca coloca essa questão porque o modelo já está no dispositivo. Com o MLX, os pesos são problema seu.
Fine-tuning: um adaptador LoRA, não um novo modelo
A razão para trazer o seu próprio modelo raramente é o modelo base em si; é ensiná-lo o seu domínio. Um fine-tune completo de um modelo de bilhões de parâmetros on-device não é o caminho. O LoRA (low-rank adaptation) é: você treina um pequeno conjunto de pesos de adaptador que ajustam o comportamento do modelo base, deixando o base intocado. O adaptador tem megabytes, não gigabytes5.
O MLX Swift carrega um adaptador treinado de um diretório que contém adapter_config.json e adapters.safetensors, e então o aplica a um modelo já carregado em um container5:
let adapter = try LoRAContainer.from(directory: adapterURL)
await container.update { context in
try? adapter.load(into: context.model) // swaps Linear layers for LoRALinear
}
O load(into:) substitui as camadas Linear padrão do modelo por camadas LoRALinear que incorporam os deltas de baixo posto do adaptador, de modo que a inferência agora reflete o seu fine-tune. Como o modelo vive dentro do container, você aplica o adaptador através de container.update, e pode trocar adaptadores a quente em tempo de execução (unload(from:) em um, load(into:) em outro) para dar a um único modelo base comportamentos diferentes por recurso. O padrão espelha o que a Apple oferece para o modelo do sistema através dos adaptadores personalizados do Foundation Models: a diferença é que aqui você é dono do modelo base, do pipeline de treinamento e do resultado, em vez de adaptar um modelo que você não consegue enxergar.
A decisão: Foundation Models, MLX ou nuvem
Três camadas, e escolher errado custa a você capacidade ou uma pilha de trabalho evitável.
- Foundation Models quando o modelo do sistema dá conta da tarefa. Gratuito, privado, zero pesos para distribuir, zero memória para gerenciar e integração com o sistema que você ganha de graça. O padrão é aqui. As tarefas de linguagem on-device para as quais a Apple o construiu (resumir, classificar, extrair, reescrever, saída estruturada) pertencem a esta camada, ponto final.
- MLX quando você precisa de um modelo que o sistema não oferece: um LLM open-weight específico, uma versão fixada que não muda sob uma atualização de OS, um fine-tune de domínio ou uma arquitetura (um modelo de visão e linguagem, um modelo não textual) fora do escopo do Foundation Models. Você paga em tamanho do app, memória e responsabilidade, e compra controle.
- Nuvem quando o modelo genuinamente precisa ser grande: raciocínio de fronteira, análise de contexto longo, qualquer coisa que os maiores modelos fazem e que um modelo on-device de poucos bilhões de parâmetros não consegue. O on-device não é um substituto para um modelo de fronteira; é um ponto diferente na curva.
A leitura honesta: o MLX é um passo deliberado para baixo por um motivo específico, não um padrão melhor. Se você não consegue nomear a capacidade que falta no Foundation Models para o seu recurso, você não precisa do MLX, e distribuí-lo significa carregar gigabytes de pesos e um orçamento de memória que você não precisava ter.
Quando não recorrer ao MLX
- O modelo do sistema já faz isso. Releia as tarefas do Foundation Models. Se a sua está na lista, pare por aqui.
- Você não pode arcar com os pesos. Um modelo pequeno quantizado ainda é um ativo grande. Se o tamanho do app ou o download no primeiro lançamento é uma restrição real para os seus usuários, essa restrição pode decidir a questão sozinha.
- Você precisa do caminho de menor consumo do Neural Engine para um modelo fixo. Para um modelo conhecido e já distribuído que não muda, o Core ML e seu conversor têm como alvo o Neural Engine com o menor consumo e a menor latência. O MLX brilha pela flexibilidade e pela iteração em nível de pesquisa; o Core ML brilha para um modelo de produção travado. São ferramentas diferentes, e “ML on-device” não é uma única decisão.
- Você não vai mantê-lo. O seu próprio modelo significa que você é dono das atualizações dele, da segurança dele e da deriva dele. A Apple atualiza o modelo do sistema por você. Se você não tem equipe para ser dono de um modelo, não adote um.
A habilidade que o MLX recompensa é a contenção sobre quando usá-lo. O framework é genuinamente notável: um modelo de linguagem de verdade, com fine-tune para o seu domínio, rodando inteiramente no dispositivo, sem servidor e sem custo por token, em um hardware cuja arquitetura de memória foi construída exatamente para isso. Essa capacidade vale o esforço quando você já nomeou o motivo. Recorra a ela sem um, e você terá trocado o modelo gratuito, mantido e integrado da Apple por uma cópia mais pesada e sem manutenção, da qual agora você é dono. O discernimento é o trabalho inteiro.
FAQ
O que é o framework MLX da Apple?
O MLX é um framework de arrays para machine learning no Apple Silicon, com uma API no estilo do NumPy, transformações de função componíveis (diferenciação automática, vetorização), computação lazy e um backend Metal2. O MLX Swift é a API em Swift para incorporá-lo em apps, de modo que você possa rodar e fazer o fine-tune dos seus próprios modelos on-device.
Como o MLX usa a memória unificada do Apple Silicon?
Os arrays do MLX vivem em memória compartilhada, então as operações rodam na CPU ou na GPU sem copiar dados entre pools de memória separados3. Essa propriedade de zero transferência é exatamente o que torna a arquitetura de memória unificada do Apple Silicon eficiente para a execução de modelos on-device.
Posso rodar um LLM open-weight on-device com o MLX?
Sim. LLMModelFactory.shared.loadContainer(from:using:configuration:) carrega um modelo quantizado como mlx-community/Llama-3.2-3B-Instruct-4bit do Hugging Face Hub; a ChatSession oferece respond(to:) para chamadas únicas, e container.generate(input:parameters:) transmite eventos .chunk(text) para saída incremental4.
Como faço o fine-tune de um modelo com o MLX?
Com um adaptador LoRA, em vez de um novo modelo. LoRAContainer.from(directory:) carrega um adaptador de um diretório que contém adapter_config.json e adapters.safetensors; aplicado através de container.update, ele troca as camadas Linear do modelo por camadas LoRALinear e pode trocar adaptadores a quente em tempo de execução5.
MLX vs Foundation Models vs Core ML: qual eu devo usar?
O padrão é Foundation Models quando o modelo do sistema da Apple dá conta da tarefa (gratuito, privado, zero pesos para distribuir)1. Recorra ao MLX apenas quando você precisa de um modelo que o sistema não oferece: um LLM open-weight específico, uma versão fixada, um fine-tune de domínio ou uma arquitetura fora do escopo do Foundation Models. Use o Core ML para um modelo de produção travado que precisa do caminho de menor consumo do Neural Engine, e a nuvem quando o modelo genuinamente precisa ser de escala de fronteira.
Quando eu não deveria recorrer ao MLX?
Quando o modelo do sistema já faz isso, quando você não pode arcar com a distribuição de gigabytes de pesos, quando um modelo fixo seria melhor servido pelo caminho de menor consumo do Neural Engine via Core ML, ou quando você não tem equipe para ser dono das atualizações, da segurança e da deriva de um modelo. O MLX é um passo deliberado para baixo por um motivo nomeado, não um padrão melhor.
-
Posicionamento do MLX em relação ao framework Foundation Models: o Foundation Models expõe o modelo de sistema on-device fixo da Apple (veja Apple Foundation Models: o framework de LLM on-device); o MLX roda modelos que você seleciona e faz o fine-tune. Os dois atendem a necessidades diferentes em camadas diferentes da pilha on-device. ↩↩
-
Apple Machine Learning Research, MLX e MLX Swift. O MLX é um framework de arrays para machine learning no Apple Silicon, com uma API no estilo do NumPy, transformações de função componíveis (diferenciação automática, vetorização), computação lazy e um backend Metal. O MLX Swift é a API em Swift para incorporá-lo em apps. ↩↩↩↩
-
Documentação do MLX, memória unificada. Os arrays do MLX vivem em memória compartilhada; as operações podem rodar na CPU ou na GPU sem transferir dados entre pools de memória separados, que é a propriedade que torna a arquitetura de memória unificada do Apple Silicon eficiente para a execução de modelos on-device. Contexto sobre o hardware: TBDR e memória unificada do Apple Silicon. ↩↩↩
-
Apple Machine Learning Research, MLX Swift Examples / MLX Swift LM.
LLMModelFactory.shared.loadContainer(from:using:configuration:)carrega um modelo quantizado (por exemplomlx-community/Llama-3.2-3B-Instruct-4bit) do Hugging Face Hub; aChatSessionfornecerespond(to:)para chamadas únicas, econtainer.generate(input:parameters:)produz um stream de eventos.chunk(text)para saída incremental viaGenerateParameterseUserInput. ↩↩↩↩ -
Apple Machine Learning Research, referência de adaptadores LoRA do MLX Swift LM.
LoRAContainer.from(directory:)carrega um adaptador de um diretório que contémadapter_config.jsoneadapters.safetensors; aplicado através decontainer.update,adapter.load(into: context.model)substitui as camadasLineardo modelo por camadasLoRALinear, eunload(from:)remove uma delas para que os adaptadores possam ser trocados a quente em tempo de execução. Compare com o caminho do modelo de sistema da Apple em adaptadores personalizados do Foundation Models. ↩↩↩↩ -
Trabalho prático do autor com o MLX: um loop autônomo de pesquisa em ML rodando experimentos de treinamento com orçamento fixo no Apple Silicon via MLX, modificando autonomamente a arquitetura e os hiperparâmetros para minimizar os bits-per-byte de validação e mantendo apenas as melhorias. O comportamento de memória unificada e de quantização descrito aqui reflete essa experimentação. ↩