Capítulos · 09
Core AI (WWDC26): el nuevo stack de inferencia on-device de Apple
Parte de la Base de conocimiento sobre la ANE. Fuentes (consultadas el 2026-07-12): developer.apple.com/core-ai, las tres sesiones de WWDC26 (324 — Meet Core AI, 325 — Dive into Core AI model authoring and optimization, 326 — Integrate on-device AI models into your app using Core AI), y los tres repos fijados bajo
references/:coreai-models(85e2f2d),coreai-torch(1b3cb3b, v0.4.1),coreai-optimization(5cdb1f1, v0.2.0).
En WWDC26 Apple presentó Core AI: el framework de inferencia que impulsa Apple Intelligence on-device, abierto a los desarrolladores como "the next evolution of on-device AI execution across Apple platforms". Cubre el ciclo de vida completo — autoría en PyTorch → optimización → conversión → compilación AOT → integración con Swift → depuración/perfilado — apuntando a todo, desde modelos de visión pequeños hasta LLMs de 70B parámetros, enteramente en el dispositivo.
Posicionamiento frente a Core ML. WWDC26 tiene cero sesiones de Core ML (verificado contra el listado de WWDC26); Core AI tuvo tres, más [330 — Optimize custom ML operations with Metal tensors]. Apple no anunció una deprecación de Core ML; la cobertura de prensa (InfoQ y otros) describe Core AI como el sucesor para redes neuronales/transformers, con Core ML permaneciendo para el ML clásico y MLX para investigación/pesos personalizados. Requisitos de los repos: iOS/macOS 27.0+, Xcode 27.
1. Arquitectura#
| Pieza | Qué es |
|---|---|
.aimodel |
Asset del modelo fuente, independiente del dispositivo; inspeccionable en el visor de modelos de Xcode (tamaño, distribución de operaciones, firmas de funciones, dimensiones dinámicas marcadas con ?) |
| Specialization | Compilación on-device, por hardware, en la primera carga: segmentar/planificar/optimizar + generar binarios específicos de dispositivo/SO; cacheado (AIModelCache, compartible entre app groups) |
| Compilación AOT | xcrun coreai-build compile MyModel.aimodel --platform iOS — mueve la mayor parte de la compilación a la máquina de desarrollo; el dispositivo solo termina la especialización. Integrado en Xcode |
| Runtime | Usa CPU, GPU y ANE; control de memoria de grano fino (preasignación, rutas de datos zero-copy), ejecución con estado |
| API de Swift | AIModel → loadFunction(named:) → InferenceFunction.run(inputs:) con E/S de NDArray; MutableViews no escapables (non-escapable) para acceso zero-copy seguro en memoria; los estados se pasan como InferenceFunction.MutableViews y se actualizan in-place |
| Distribución | Los modelos se mantienen fuera del app bundle; Background Assets para descarga opcional |
La demo de "Meet Core AI" está directamente en línea con el tema de esta KB: un transformer cuya latencia por paso crecía con la longitud de la secuencia se arregló añadiendo estados de KV cache (búferes NDArray pasados como vistas de estado mutables) — decodificación de latencia constante, el mismo patrón que el doc 06 §4, ahora de primera clase en la API.
Puente con Foundation Models#
CoreAILanguageModel (del paquete Swift coreai-models) conecta un LLM de Core AI personalizado a la API LanguageModelSession de Foundation Models — el mismo streaming y la misma generación guiada/estructurada @Generable que el modelo integrado de Apple (sesión 326; véase también la sesión 339 de WWDC26 "Bring an LLM provider to the Foundation Models framework").
2. El stack de Python#
coreai-torch (conversión) — references/coreai-torch#
- Basado en
torch.export(no entorch.jit.tracecomo en la era de Core ML — doc 05): exportar con soporte dedynamic_shapes→run_decompositions(coreai_torch.get_decomp_table())→TorchConverter().add_exported_program(...).to_coreai()→save_asset("X.aimodel"). - Composite ops (
coreai_torch/composite_ops/):_sdpa.py(incl. variantes causales y sliding-window attention),_rms_norm.py,_rope.py,_gather_mm.py,_gated_delta_update.py— operaciones de alto nivel preservadas a través de la decomp table para que el compilador las mapee a kernels de hardware pre-optimizados (SDPA, LayerNorm/GroupNorm…). Descomponer la atención a mano ya no es tarea del autor. - Conversión multi-entrypoint: varias funciones exportadas → un
.aimodelcon múltiples funciones invocables (por ejemplo, SAM3 reescrito comoimage_encode/text_encode/detect; los embeddings de imagen cacheados dieron ejecuciones posteriores un 76 % más rápidas — sesión 325). - Kernels de Metal personalizados desde Python: el DSL
TorchMetalKernelincrusta código fuente MSL (con una implementación de referencia en PyTorch para tracing/verificación) directamente en el.aimodel. - La verificación numérica contra PyTorch es un flujo de trabajo de primera clase (
coreai.runtime.AIModelen Python, comparar logits, afirmar la diferencia máxima).
coreai-opt (compresión) — references/coreai-optimization#
pip install coreai-opt. El descendiente productizado del linaje ct.optimize / Palettizer-de-argmaxtools (doc 07):
- Esquemas: cuantización INT4/INT8, FP4/FP8, palettization k-means, pruning; post-entrenamiento y QAT; granularidades per-tensor / per-channel / per-grouped-channel.
- API basada en configuración:
QuantizerConfig.presets.w4().without([nn.LayerNorm, "lm_head"]),presets.w8().only_for(nn.Linear, nn.Conv2d)(src/coreai_opt/config/compression_config.py) — compresión selectiva sensible a la sensibilidad en una sola línea. save_intermediates+ el modo de comparación del Core AI Debugger (PSNR/MSE/MAE, verde/amarillo/rojo por capa) = el flujo de trabajo de perfilado de divergencia por capa del doc 07 §3, integrado en el toolchain.
coreai-models (zoo de modelos + recetas) — references/coreai-models#
models/: recetas de exportación para whisper, qwen2/3(+MoE), gemma3, mistral/mixtral, gpt_oss, sam3, stable-diffusion, flux2, clip, clap, depth-anything, yolo, t5, roberta, wav2vec2, vlm… — scriptsuv runde un solo comando (dependencias inline PEP 723;coreai-core==1.0.0b2,coreai-torch==0.4.1fijados).- Recetas mixed-bit declarativas: por ejemplo,
models/qwen3/qwen3_0_6b_mixed_4bit_8bit.yaml— 4-bit per-grouped-channel global (grupo 8), capas sensibles específicas (emparejadas por regex) a 8-bit per-tensor, embeddings omitidos. La receta mixed-bit de argmaxtools (doc 07 §3), entregada como YAML. python/src/coreai_models/: primitivas de autoría reutilizables y clases por modelo con un registro de plataforma explícito (ios_class/macos_classenmodels/registry.py); la CLI de exportación toma--platform iOS.swift/: paquetes de runtime (CoreAILanguageModels, segmentación, etc.) que ocultan el manejo de tensores.skills/: agent skills (Claude Code / Codex / Gemini CLI) — model-authoring, model-compression-exploration, working-with-coreai.
3. ¿Sobreviven los principios de la ANE de la KB? — Sí, verbatim#
El hallazgo más importante para esta KB. coreai_models/primitives/ tiene implementaciones separadas ios/ y macos/ — la división ANE-vs-GPU hecha explícita a nivel del framework:
| Principio de la KB (2022) | Primitivas iOS de Core AI (2026) |
|---|---|
| P1 — layout BC1S | ios/sdpa.py: query/key/value con forma (batch, n_heads*head_dim, 1, seq_len) — exactamente BC1S |
| P1 — Conv2d 1×1, no Linear | ios/mlp.py: "uses Conv2d layers instead of Linear layers for better iOS performance" — MLP gated-SiLU a partir de tres convoluciones 1×1 |
| P2 — chunking por cabeza | docstring de ios/sdpa.py: "iOS requires each attention head to be computed individually to meet hardware constraints" — split por cabeza + softmax por cabeza sobre el eje de las keys (softmax(1)), consciente de GQA (kv_group_size) |
| P3 — minimizar copias | keys traspuestas/permutadas una vez por adelantado antes del bucle por cabeza |
| Higiene de FP16 | escala plegada dentro de K antes de QKᵀ "for numerical stability" |
| KV cache con shapes estáticos | ios/cache.py: cache 5D [n_layers, batch, n_kv_heads*head_dim, 1, max_seq_len], max_seq_len fijo, actualizado con la nueva operación in-place mutable_slice_update. Nota: "On iOS we must update on dim 4 (the last dim), whereas on macOS we use dim 3" — la restricción del último eje (doc 01 §2.2) sigue dando forma al layout |
| Guía de la sesión (325) | "static tensor shapes", "channels-first layouts", "convolutional projections instead of linear layers", "palettization over INT quantization for power efficiency on iOS" |
Mientras tanto, macos/sdpa.py es un envoltorio delgado sobre el coreai_torch.composite_ops.SDPA fusionado — en la GPU, no se necesita ninguna de las cirugías manuales. El registro por plataforma institucionaliza la lección del doc 06 §3 (la elección de SDPA depende de la carga de trabajo/hardware).
Lo que cambió:
- La actualización de slice in-place reemplaza la mezcla con máscara one-hot para los KV caches (
mutable_slice_updateconbegin/endcalculados vs elcache*(1-m)+current*mde WhisperKit). - El toolchain absorbe la descomposición: autoras con operaciones compuestas de alto nivel (SDPA, RMSNorm, RoPE) y el compilador elige el lowering óptimo para el hardware por plataforma — con la opción de bajar a primitivas iOS escritas a mano (como hace coreai-models para los LLMs) o a kernels de Metal personalizados.
torch.export+ dynamic shapes reemplaza el trace-por-shape y los apaños con modelos multifunción.- La compilación AOT + las APIs explícitas de especialización/caché reemplazan el folklore de "hide the first uncached load" (doc 05).
- La historia de Whisper cierra un ciclo: WhisperKit necesitó una reimplementación hecha a mano (doc 06); la receta de Core AI (
models/whisper/export.py) exporta elwhisper-large-v3-turboestándar de HF a través de la decomp table en ~200 líneas.
3.5 Dónde viven realmente las reglas del compilador#
"The toolchain owns the optimization" — pero las reglas están escritas en cuatro capas de apertura decreciente (verificado contra nuestras fuentes fijadas y el wheel coreai-core 1.0.0b2 instalado):
| Capa | Qué reglas | Dónde | ¿Abierta? |
|---|---|---|---|
| coreai-torch (frontend) | Qué sobrevive a la descomposición: _decomp.py lista exactamente 12 operaciones ATen preservadas (scaled_dot_product_attention, silu, instance_norm, pads…). Cómo se traducen las operaciones: _aten_to_core.py, 3.760 líneas de lowerings por operación (por ejemplo, replace_sdpa() en la línea 3426). Tus propias reglas: DSL _torch_metal_kernel.py |
references/coreai-torch/coreai_torch/ |
✅ legible |
| coreai-core (middle-end) | Pasadas de optimización de grafo detrás de .optimize(). El wheel revela el sustrato: coreai/_compiler/ es MLIR (infraestructura de compilador LLVM) con dialectos generados por tblgen coreai, coreaix, udml, debuginfo — de ahí el main.mlirb del .aimodel. Las pasadas se ejecutan en el PassManager de MLIR pero están compiladas dentro de _mlir.so |
pip wheel (binario) | ⚠️ IR inspeccionable, pasadas binarias |
| Framework Core AI del SO (backend) | Especialización: segmentación por unidad de cómputo, asignación de layout, codegen de kernels por chip (el linaje ANECompiler, privado también detrás de Core ML) |
Framework de sistema macOS/iOS 27 (+ puente _coreai_runtime_os.so) |
❌ cerrado, como siempre lo fue el codegen de la ANE |
| Primitivas de coreai-models ("standard library") | Lo que el compilador aún no automatiza: primitives/ios/sdpa.py existe precisamente porque "iOS requires each attention head to be computed individually" — para los LLMs limitados por la ANE, Apple todavía escribe la forma por cabeza en el grafo fuente (registro ios_class/macos_class, --platform iOS) |
references/coreai-models/ |
✅ legible |
Arquitectura clásica de compilador al estilo LLVM: frontend abierto, IR público con pasadas propietarias, backend de hardware cerrado — más una biblioteca estándar abierta que cubre los huecos. La consecuencia práctica: la optimización a nivel de operación se automatiza solo hasta donde alcanzan la decomp table + los lowerings; el modelado de grafo específico del hardware todavía aflora como primitivas de autor cuando el compilador se queda corto, que es donde los principios de esta KB (docs 01–07) siguen siendo conocimiento operativo en lugar de historia.
4. Herramientas: debugger, instruments, gauge#
- Plantilla de Core AI Instruments: subeventos de carga + especialización del modelo, latencia de inferencia a lo largo del tiempo (la demo de "Meet" la usó para detectar el crecimiento cuadrático de la recomputación de KV).
- Core AI Debugger (app de macOS): navegar por la jerarquía de módulos de PyTorch ↔ grafo convertido ↔ líneas de código fuente Python originales; ejecutar en el dispositivo e inspeccionar tensores intermedios; modo de comparación vs la referencia de PyTorch (PSNR por defecto) — análisis de sensibilidad por capa antes de la compresión.
- Core AI debug gauge en Xcode: vista de actividad en streaming para una primera mirada antes de Instruments.
- Guía de despliegue (sesión 326): mantener los modelos grandes fuera del bundle (Background Assets), nunca especializar en el camino caliente, compilar AOT para la UX de la primera ejecución; ejemplo de dimensionamiento — SAM3 (623 MB) + Qwen3-0.6B en iPhone, Qwen3-8B en Mac.
5. Qué significa esto para la KB#
- Las verdades del hardware son permanentes. Alineación del último eje a 64 bytes, channels-first, shapes estáticos, cómputo por cabeza, palettization-para-el-ancho-de-banda — cada principio de 2022 reaparece en el código de primera parte de Apple de 2026. Entender los docs 01–07 es entender por qué las primitivas iOS de Core AI tienen el aspecto que tienen.
- La división del trabajo subió de nivel. Los autores ahora escriben operaciones compuestas y configuraciones de compresión en YAML; el compilador es dueño del lowering. La optimización a mano permanece para la frontera (kernels personalizados, reescritura como SAM3, primitivas específicas de plataforma).
- Esbozo de migración (Core ML → Core AI):
torch.jit.trace→torch.export;.mlpackage→.aimodel;MLModel/MLState→AIModel/InferenceFunction+ estadoMutableViews; recetasct.optimize/argmaxtools→presets/YAML decoreai-opt; pestaña de rendimiento de Xcode→Core AI Instruments + Debugger; modelos multifunción→conversión multi-entrypoint. Comparación completa y guía de decisión: doc 10. - Preguntas abiertas por investigar (no respondidas por el material consultado): el reporte exacto de despacho a la ANE en las nuevas herramientas (equivalente de MLComputePlan), el formato a nivel de operación del
.aimodel, la política de soporte a largo plazo de Core ML, si los proyectos de la clase de WhisperKit migran.