← Todos los articulos

MLX en Apple Silicon: cuándo necesitas tu propio modelo y no el de Apple

El framework Foundation Models de Apple te entrega un solo modelo: el del sistema, sellado, gratuito y actualizado según el calendario de Apple. Para la mayoría del trabajo con lenguaje en el dispositivo esa es la herramienta correcta, e ir más allá es un error. Pero hay trabajos que exigen un modelo que tú elijas: un LLM open-weight específico, una versión que fijes, un ajuste fino entrenado con tus propios datos o una capacidad que el modelo del sistema no tiene. Cuando necesitas tu propio modelo corriendo en el dispositivo, la capa que está por debajo de Foundation Models es MLX1.

MLX es el framework de arrays de Apple para machine learning sobre Apple Silicon, con un API en Swift (MLX Swift) que integras directamente en una app2. No es un framework del sistema al que llamas; es una librería que envías junto con los pesos del modelo. Esa diferencia es todo el intercambio, y entenderla es la forma de decidir si bajas una capa o te quedas donde Apple te puso.

En resumen

  • MLX es un framework de arrays parecido a NumPy, construido para Apple Silicon, con evaluación perezosa, transformaciones de funciones componibles y un backend Metal2.
  • El modelo de memoria unificada es la razón por la que funciona en un teléfono. Los arrays viven en un único pool de memoria que comparten la CPU y la GPU, de modo que MLX corre en ambas sobre los mismos buffers sin el costo de copiar entre host y dispositivo3.
  • Ejecuta un LLM open-weight en el dispositivo con LLMModelFactory, apuntando a un modelo cuantizado como mlx-community/Llama-3.2-3B-Instruct-4bit, y luego genera a través de una ChatSession4.
  • Haz ajuste fino con adaptadores LoRA: entrena un pequeño adaptador, envía adapters.safetensors y load(into:) intercambia las capas Linear del modelo base por LoRALinear en tiempo de ejecución5.
  • El costo de tener tu propio modelo: el tamaño de la app (los pesos son grandes), la presión sobre la memoria, la falta de integración con el sistema, y que cada actualización corre por tu cuenta. Foundation Models no tiene ninguno de esos costos porque los paga Apple.

Qué es MLX y por qué Apple Silicon lo hace posible

MLX te da arrays y operaciones que se parecen a NumPy, además de las transformaciones que necesita el machine learning: diferenciación automática, vectorización y evaluación perezosa que construye un grafo de cómputo y solo lo ejecuta cuando lees un resultado2. Por sí solo, eso describe una docena de frameworks. Lo que hace que MLX ejecute un modelo de varios miles de millones de parámetros en un dispositivo que cabe en tu bolsillo es el modelo de memoria.

En una GPU de escritorio, los datos viven en la RAM del sistema y los copias a través de un bus hacia la memoria separada de la GPU para calcular, y luego copias los resultados de vuelta. Esa copia es el peaje, y para un modelo grande resulta brutal. Apple Silicon tiene memoria unificada: un único pool que la CPU, la GPU y el Neural Engine direccionan directamente. MLX está construido en torno a ese hecho3. Un array no está “en la CPU” ni “en la GPU”; está en la memoria, y cualquier procesador opera sobre él en su sitio. Sin copias, sin peaje de bus. Un modelo de tres mil millones de parámetros cuantizado a 4 bits cabe en unos pocos gigabytes y corre sin los viajes de ida y vuelta que volverían impráctico el mismo trabajo en una máquina con GPU discreta de memoria similar. La decisión de hardware que Apple tomó hace años es la razón por la que la inferencia de un modelo real en el dispositivo es viable, y la arquitectura de memoria unificada basada en tiles es el sustrato sobre el que se apoya MLX.

Ejecutar un LLM en el dispositivo

El camino de “quiero un modelo específico” a texto en pantalla es corto. La capa de LLM de MLX Swift carga un modelo cuantizado desde el Hugging Face Hub y lo ejecuta4:

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 una UI token por token, genera un stream en su lugar y renderiza los fragmentos a medida que llegan4:

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 */ }
}

Dos detalles cargan con casi todo el peso práctico. Primero, el 4bit en el identificador del modelo no es un adorno opcional: la cuantización es lo que hace que el modelo quepa en memoria y corra a una velocidad usable en el dispositivo. Envías pesos de 4 bits (o menos), no de precisión completa. Segundo, los pesos son grandes incluso cuantizados, así que decides deliberadamente si los incluyes dentro de la app (instantáneo, pero una descarga pesada) o si los traes en el primer arranque (binario ligero, pero con una espera y una ruta de error que manejar). Foundation Models nunca plantea esa pregunta porque el modelo ya está en el dispositivo. Con MLX, los pesos son tu problema.

Ajuste fino: un adaptador LoRA, no un modelo nuevo

La razón para traer tu propio modelo rara vez es el modelo base en sí; es enseñarle tu dominio. El ajuste fino completo de un modelo de varios miles de millones de parámetros en el dispositivo no es la jugada. LoRA (adaptación de bajo rango) sí lo es: entrenas un pequeño conjunto de pesos de adaptador que ajustan el comportamiento del modelo base, dejando la base intacta. El adaptador pesa megabytes, no gigabytes5.

MLX Swift carga un adaptador entrenado desde un directorio que contiene adapter_config.json y adapters.safetensors, y luego lo aplica a un modelo ya cargado en un contenedor5:

let adapter = try LoRAContainer.from(directory: adapterURL)
await container.update { context in
    try? adapter.load(into: context.model)   // swaps Linear layers for LoRALinear
}

load(into:) reemplaza las capas Linear estándar del modelo por capas LoRALinear que incorporan los deltas de bajo rango del adaptador, de modo que la inferencia ahora refleja tu ajuste fino. Como el modelo vive dentro del contenedor, aplicas el adaptador a través de container.update, y puedes intercambiar adaptadores en caliente en tiempo de ejecución (descargar uno con unload(from:), cargar otro con load(into:)) para darle a un único modelo base un comportamiento distinto según la función. El patrón es un espejo de lo que Apple ofrece para el modelo del sistema mediante los adaptadores personalizados de Foundation Models: la diferencia es que aquí tú eres dueño del modelo base, del pipeline de entrenamiento y del resultado, en lugar de adaptar un modelo que no puedes ver.

La decisión: Foundation Models, MLX o la nube

Tres capas, y elegir mal te cuesta o capacidad o un montón de trabajo evitable.

  • Foundation Models cuando el modelo del sistema puede hacer la tarea. Gratuito, privado, cero pesos que enviar, cero memoria que gestionar e integración con el sistema que obtienes sin pagar nada. Aquí está el punto de partida por defecto. Las tareas de lenguaje en el dispositivo para las que Apple lo construyó (resumir, clasificar, extraer, reescribir, salida estructurada) van aquí, y punto.
  • MLX cuando necesitas un modelo que el sistema no te da: un LLM open-weight específico, una versión fijada que no cambie bajo tus pies con una actualización del sistema operativo, un ajuste fino de dominio o una arquitectura (un modelo de visión-lenguaje, un modelo que no sea de texto) fuera del alcance de Foundation Models. Pagas en tamaño de app, memoria y propiedad, y a cambio compras control.
  • La nube cuando el modelo de verdad tiene que ser grande: razonamiento de frontera, análisis de contexto largo, cualquier cosa que hagan los modelos más grandes y que un modelo en el dispositivo de unos pocos miles de millones de parámetros no pueda. El dispositivo no es un reemplazo de un modelo de frontera; es un punto distinto en la curva.

La lectura honesta: MLX es un paso atrás deliberado por una razón específica, no un mejor valor por defecto. Si no puedes nombrar la capacidad que le falta a Foundation Models para tu función, no necesitas MLX, y enviarlo significa cargar gigabytes de pesos y un presupuesto de memoria que no tenías por qué asumir.

Cuándo no recurrir a MLX

  • El modelo del sistema ya lo hace. Vuelve a leer las tareas de Foundation Models. Si la tuya está en la lista, detente aquí.
  • No puedes permitirte los pesos. Un modelo pequeño cuantizado sigue siendo un activo grande. Si el tamaño de la app o la descarga en el primer arranque son una restricción real para tus usuarios, esa restricción puede decidir la cuestión por sí sola.
  • Necesitas la ruta de menor consumo del Neural Engine para un modelo fijo. Para un modelo conocido y ya enviado que no cambia, Core ML y su conversor apuntan al Neural Engine con el consumo y la latencia más ajustados. MLX brilla por su flexibilidad y por una iteración de calidad para investigación; Core ML brilla para un modelo de producción cerrado. Son herramientas distintas, y “ML en el dispositivo” no es una sola decisión.
  • No vas a mantenerlo. Tu propio modelo significa que eres dueño de sus actualizaciones, su seguridad y su deriva. Apple actualiza el modelo del sistema por ti. Si no cuentas con el personal para hacerte cargo de un modelo, no adoptes uno.

La habilidad que MLX recompensa es la mesura sobre cuándo usarlo. El framework es genuinamente notable: un modelo de lenguaje real, ajustado a tu dominio, corriendo por completo en el dispositivo sin servidor y sin costo por token, sobre hardware cuya arquitectura de memoria se construyó exactamente para esto. Esa capacidad vale la pena cuando has nombrado la razón. Recurre a ella sin una y habrás cambiado el modelo gratuito, mantenido e integrado de Apple por una copia más pesada y sin mantenimiento de la que ahora eres dueño. El criterio es todo el trabajo.

Preguntas frecuentes

¿Qué es el framework MLX de Apple?

MLX es un framework de arrays para machine learning sobre Apple Silicon, con un API parecido a NumPy, transformaciones de funciones componibles (diferenciación automática, vectorización), cómputo perezoso y un backend Metal2. MLX Swift es el API en Swift para integrarlo en apps, de modo que puedes ejecutar y ajustar tus propios modelos en el dispositivo.

¿Cómo usa MLX la memoria unificada de Apple Silicon?

Los arrays de MLX viven en memoria compartida, así que las operaciones corren en la CPU o en la GPU sin copiar datos entre pools de memoria separados3. Esa propiedad de transferencia cero es justamente lo que hace eficiente la arquitectura de memoria unificada de Apple Silicon para ejecutar modelos en el dispositivo.

¿Puedo ejecutar un LLM open-weight en el dispositivo con MLX?

Sí. LLMModelFactory.shared.loadContainer(from:using:configuration:) carga un modelo cuantizado como mlx-community/Llama-3.2-3B-Instruct-4bit desde el Hugging Face Hub; ChatSession te da respond(to:) para llamadas individuales, y container.generate(input:parameters:) emite eventos .chunk(text) como stream para salida incremental4.

¿Cómo hago el ajuste fino de un modelo con MLX?

Con un adaptador LoRA en lugar de un modelo nuevo. LoRAContainer.from(directory:) carga un adaptador desde un directorio que contiene adapter_config.json y adapters.safetensors; aplicado a través de container.update, intercambia las capas Linear del modelo por capas LoRALinear y puede intercambiar adaptadores en caliente en tiempo de ejecución5.

MLX vs Foundation Models vs Core ML: ¿cuál debo usar?

Parte por defecto de Foundation Models cuando el modelo del sistema de Apple puede hacer la tarea (gratuito, privado, cero pesos que enviar)1. Recurre a MLX solo cuando necesites un modelo que el sistema no te da: un LLM open-weight específico, una versión fijada, un ajuste fino de dominio o una arquitectura fuera del alcance de Foundation Models. Usa Core ML para un modelo de producción cerrado que necesite la ruta de menor consumo del Neural Engine, y la nube cuando el modelo de verdad tenga que ser de escala de frontera.

¿Cuándo no debería recurrir a MLX?

Cuando el modelo del sistema ya lo hace, cuando no puedes permitirte enviar gigabytes de pesos, cuando un modelo fijo estaría mejor servido por la ruta de menor consumo del Neural Engine de Core ML, o cuando no cuentas con el personal para hacerte cargo de las actualizaciones, la seguridad y la deriva de un modelo. MLX es un paso atrás deliberado por una razón nombrada, no un mejor valor por defecto.



  1. Posicionamiento de MLX en relación con el framework Foundation Models: Foundation Models expone el modelo fijo del sistema de Apple en el dispositivo (consulta Apple Foundation Models: el framework de LLM en el dispositivo); MLX ejecuta modelos que tú seleccionas y ajustas. Ambos atienden necesidades distintas en capas distintas del stack en el dispositivo. 

  2. Apple Machine Learning Research, MLX y MLX Swift. MLX es un framework de arrays para machine learning sobre Apple Silicon con un API parecido a NumPy, transformaciones de funciones componibles (diferenciación automática, vectorización), cómputo perezoso y un backend Metal. MLX Swift es el API en Swift para integrarlo en apps. 

  3. Documentación de MLX, memoria unificada. Los arrays de MLX viven en memoria compartida; las operaciones pueden correr en la CPU o en la GPU sin transferir datos entre pools de memoria separados, que es la propiedad que hace eficiente la arquitectura de memoria unificada de Apple Silicon para ejecutar modelos en el dispositivo. Contexto sobre el hardware: la TBDR y la memoria unificada de Apple Silicon

  4. Apple Machine Learning Research, MLX Swift Examples / MLX Swift LM. LLMModelFactory.shared.loadContainer(from:using:configuration:) carga un modelo cuantizado (por ejemplo mlx-community/Llama-3.2-3B-Instruct-4bit) desde el Hugging Face Hub; ChatSession proporciona respond(to:) para llamadas individuales, y container.generate(input:parameters:) produce un stream de eventos .chunk(text) para salida incremental mediante GenerateParameters y UserInput

  5. Apple Machine Learning Research, referencia de adaptadores LoRA de MLX Swift LM. LoRAContainer.from(directory:) carga un adaptador desde un directorio que contiene adapter_config.json y adapters.safetensors; aplicado a través de container.update, adapter.load(into: context.model) reemplaza las capas Linear del modelo por capas LoRALinear, y unload(from:) elimina una para que los adaptadores puedan intercambiarse en caliente en tiempo de ejecución. Compara con la ruta del modelo del sistema de Apple en los adaptadores personalizados de Foundation Models

  6. Trabajo práctico del autor con MLX: un bucle autónomo de investigación en ML que ejecuta experimentos de entrenamiento con presupuesto fijo sobre Apple Silicon mediante MLX, modificando de forma autónoma la arquitectura y los hiperparámetros para minimizar los bits por byte de validación y conservando solo las mejoras. El comportamiento de memoria unificada y cuantización descrito aquí refleja esa experimentación. 

Artículos relacionados

Apple Foundation Models: The On-Device LLM Framework, Explained

Apple's Foundation Models framework: LanguageModelSession, @Generable guided generation, tool calling, availability, and…

18 min de lectura

Inferencia en dispositivo con Core ML: los patrones que realmente llegan a producción

Core ML ejecuta modelos en el Neural Engine, GPU o CPU. Los patrones que llegan a producción: conversión de modelos, sug…

13 min de lectura

Construyendo sistemas de IA: De RAG a agentes

Construí un sistema de agentes de 3.500 líneas con 86 hooks y validación por consenso. Esto es lo que aprendí sobre RAG,…

10 min de lectura