Foundation Models tiene una propiedad incómoda que no arreglan ni los prompts ni la arquitectura: el framework solo funciona donde Apple Intelligence está activo. Un dispositivo algo antiguo, una región sin soporte, o la persona desactivó la función en los ajustes — y tu función sencillamente no existe.
En iOS 27 el rodeo se volvió oficial. El protocolo LanguageModel está abierto, y un modelo exportado con Core AI puede entrar en esa misma LanguageModelSession, con los mismos prompts, herramientas y salida estructurada. Aquí recorro la cadena entera, desde listar modelos en la terminal hasta la primera respuesta en la app.
Esta es la tercera parte; Core AI en sí y lo nuevo en Foundation Models van aparte. Requisitos: macOS 27, iOS 27 y Xcode 27 o posterior.
Cuándo merece la pena de verdad#
Tres motivos que la propia Apple da para traer un modelo que no es suyo:
- necesitas una capacidad especializada que ofrece ese modelo;
- necesitas soportar dispositivos que no tienen Apple Intelligence;
- necesitas paridad multiplataforma: el mismo modelo en tu servidor y en la app.
Hay un cuarto, no declarado pero evidente: el modelo integrado viaja con el sistema. Ya cambió en 26.4 y volvió a cambiar en 27, y cada vez Apple escribió «revisa tus prompts». Un modelo en tu bundle cambia cuando tú lo decides.
Conseguir el modelo: registro y exportación#
De la exportación se encarga el paquete Swift open source coreai-models, que trae tanto las recetas como las utilidades. Todo empieza en la terminal: instalar el gestor de paquetes uv, clonar el repositorio y entrar en la carpeta coreai-models.
Después, mirar qué hay soportado:
uv run coreai.model.registry --list-models # modelos del registro y sus presetsDe la salida interesa la columna HF_ID: el identificador que se usa al exportar. Que tu primer modelo ronde los 0,6B de parámetros: se descarga rápido y vive cómodo en el dispositivo. Pelearse con la cuantización de un modelo de siete mil millones mientras todavía estás en «¿esto funciona siquiera?» es una variable de más.
Los modelos se especializan para el hardware donde van a correr, así que la plataforma se fija al exportar:
uv run coreai.llm.export HF_ID # exportar para macOS
uv run coreai.llm.export HF_ID --platform iOS # el mismo modelo para iOSLo que sale es una carpeta de recursos: el .aimodel más el tokenizador y lo que el modelo necesite. Esa carpeta entera va a la app.
Mira además el directorio models dentro de coreai-models: cada modelo tiene su README con la receta exacta y sus propios requisitos. Aquí no hay un comando universal de «exporta lo que sea», lo cual es más honesto que una promesa que se rompe con el segundo modelo.
Enchufar el paquete#
CoreAILanguageModel vive en ese mismo coreai-models. Se añade como cualquier dependencia: File > Add Package Dependencies, buscar coreai-models, añadir. En la tabla de productos, junto a CoreAILM aparecerá None — elige ahí tu app, o el paquete se adjunta y el módulo nunca aparece. Es la forma clásica de perder veinte minutos en «por qué no importa».
El código#
Todo el puente son cuatro líneas:
import FoundationModels
import CoreAILanguageModels
// La carpeta de recursos que exportaste y metiste en el bundle.
guard let modelURL = Bundle.main.url(forResource: "The model name",
withExtension: nil) else {
// Recurso no encontrado.
return
}
// Cargamos el modelo y creamos una sesión sobre él.
let model = try await CoreAILanguageModel(resourcesAt: modelURL)
let session = LanguageModelSession(model: model)withExtension: nil no es una errata: se apunta a una carpeta, no a un archivo.
CoreAILanguageModel cumple el protocolo LanguageModel, así que la sesión se crea con exactamente el mismo inicializador que con el modelo integrado. A partir de ahí, el código de tu función no nota ninguna diferencia:
let response = try await session.respond(
to: "Resume los puntos clave de esta transcripción de reunión: \(meetingTranscript)."
)Streaming, herramientas, @Generable, GenerationOptions — todo se traslada sin una sola edición. Que es justo el sentido del ejercicio: tu capa de producto no sabe qué modelo tiene debajo.
La carga es asíncrona, y el usuario lo nota#
El try await del inicializador de CoreAILanguageModel cubre trabajo real: antes de la primera petición el framework compila el modelo y levanta el tokenizador. Llámalo en el momento en que alguien pulsa el botón, y alguien espera.
El patrón que funciona es cargar antes, cuando la petición está a uno o dos segundos: se abrió una pantalla, la persona empezó a escribir, arrancó un flujo. Ese es también el sitio para precalentar la sesión con prewarm(promptPrefix:), de modo que instrucciones y definiciones de herramientas entren en la caché KV antes del primer respond.
Con un modelo grande, la asincronía no basta: querrás compilación anticipada con coreai-build y control explícito de la caché de especializaciones. Eso es territorio del primer artículo, y los modelos de lenguaje tienen allí un detalle propio: expectFrequentReshapes en SpecializationOptions. En un LLM la longitud de secuencia crece un token por paso, y optimizar para cada forma nueva consume más de lo que devuelve.
Los modelos con razonamiento se comportan bien de fábrica#
Los modelos abiertos que emiten cadena de pensamiento son un incordio al integrarlos a mano: hay que separar su texto intermedio de la respuesta, y eso suele acabar en expresiones regulares sobre etiquetas.
Core AI reconoce esa salida por su cuenta y la enruta a la transcripción como segmento de razonamiento. No llega a response.content: la persona ve solo la respuesta. Tú sí puedes leer el razonamiento cuando investigas por qué una respuesta salió rara.
Si el modelo razona o no depende de lo que exportaste, y se comprueba explícitamente:
if model.capabilities.contains(.reasoning) {
// El modelo admite razonamiento.
}Qué medir#
Core AI elige el motor según el dispositivo — GPU, CPU o Neural Engine, en función de cómo se exportó el modelo. Eso no se pilota desde el código de la función, pero el resultado conviene verificarlo.
Se mira en Instruments, en el instrumento Foundation Models: tiempos de carga de assets, recuentos de tokens y duración por petición. El primer número que revisaría es el de tokens de entrada cacheados sobre tokens de entrada totales entre turnos. Si es bajo, el prefijo se recalcula cada vez, y el problema no es el modelo sino cómo está montada la sesión.
Qué pagas#
Sin ilusiones sobre el intercambio. Ganas independencia de Apple Intelligence y control sobre la versión del modelo. A cambio asumes tres cosas que antes hacía el sistema: el peso del modelo en la entrega (o su descarga y actualización), la especialización en el dispositivo con su latencia de primer arranque, y la calidad — un modelo abierto de 0,6B no te debe nada, y eso se comprueba con tus datos y no con tus impresiones.
Así que el orden que mantendría: primero el modelo integrado, con una evaluación honesta de la función sobre él. Core AI cuando choques con la disponibilidad de Apple Intelligence o necesites una capacidad que el modelo del sistema no tiene. La buena noticia es que moverse entre ambos cuesta una línea y no una reescritura.



