
Construyendo un Asistente de IA en Dispositivo para tu App Móvil
Patrones de arquitectura para construir un asistente conversacional de IA que se ejecuta completamente en el dispositivo del usuario. Selección de modelo, gestión de conversaciones, patrones de UI y consideraciones de producción.
Un asistente de IA en dispositivo es una interfaz conversacional impulsada por un modelo de lenguaje que se ejecuta localmente en el teléfono del usuario. Sin API en la nube. Sin dependencia de red. Respuestas instantáneas. Privacidad completa.
Esta guía cubre la arquitectura desde la selección del modelo hasta el despliegue en producción.
Descripción general de la arquitectura
El asistente en dispositivo tiene cuatro capas:
- Capa de modelo: llama.cpp carga y ejecuta el modelo GGUF
- Capa de conversación: Gestiona el historial de chat, system prompts y ventanas de contexto
- Capa de interfaz: UI de chat con visualización de tokens en streaming
- Capa de estado: Persiste las conversaciones, gestiona el ciclo de vida del modelo
Selección del modelo para chat
La IA conversacional se beneficia de modelos más grandes. Un modelo 3B con fine-tuning es el punto de partida recomendado:
| Tamaño del modelo | Calidad de chat | Coherencia multi-turno | Recomendado para |
|---|---|---|---|
| 1B | Adecuada | 2-3 turnos | Q&A simple, bots de FAQ |
| 3B | Buena | 5-8 turnos | Asistentes de chat completos |
Fine-tuning es esencial para chat. Un modelo base 3B generará respuestas genéricas. Un modelo 3B con fine-tuning habla con la voz de tu marca, conoce tu producto y maneja tus casos de uso específicos.
Gestión de conversaciones
La plantilla de prompt
Cada familia de modelos tiene una plantilla de chat específica. Para Llama 3.2:
<|begin_of_text|><|start_header_id|>system<|end_header_id|>
Eres el asistente RecipeHelper. Ayuda a los usuarios a encontrar y modificar recetas. Siempre incluye tiempos de preparación y cocción.<|eot_id|><|start_header_id|>user<|end_header_id|>
¿Cena rápida para dos?<|eot_id|><|start_header_id|>assistant<|end_header_id|>
Al hacer fine-tuning, el framework de entrenamiento maneja el formato de la plantilla automáticamente. En el momento de la inferencia, tu app debe formatear la conversación en esta plantilla antes de enviarla a llama.cpp.
Gestión de la ventana de contexto
Los modelos móviles típicamente usan ventanas de contexto de 2048-4096 tokens (configurables, pero ventanas más grandes usan más memoria y ralentizan la inferencia). Una conversación puede exceder esto rápidamente.
Enfoque de ventana deslizante: Mantén el system prompt y los N turnos más recientes. Descarta los turnos más antiguos cuando la ventana se llena:
func buildPrompt(systemPrompt: String, turns: [Turn], maxTokens: Int) -> String {
var prompt = formatSystem(systemPrompt)
var tokenCount = countTokens(prompt)
// Agregar turnos del más nuevo al más antiguo, detenerse cuando la ventana esté llena
var includedTurns: [Turn] = []
for turn in turns.reversed() {
let turnTokens = countTokens(formatTurn(turn))
if tokenCount + turnTokens > maxTokens - 512 { break } // Reservar 512 para la respuesta
includedTurns.insert(turn, at: 0)
tokenCount += turnTokens
}
for turn in includedTurns {
prompt += formatTurn(turn)
}
return prompt
}
Enfoque de resumen: Cuando la conversación excede la ventana, resume los turnos más antiguos en un contexto compacto y agrégalo al inicio del system prompt. Esto preserva la información clave mientras se mantiene dentro del presupuesto de tokens. Sin embargo, esto requiere una llamada de inferencia adicional.
Persistencia de conversaciones
Almacena las conversaciones en almacenamiento local (Core Data en iOS, Room en Android) para que los usuarios puedan retomar donde lo dejaron:
- Guarda cada mensaje (rol, contenido, marca de tiempo)
- Guarda metadatos de la conversación (título, fecha de creación, última actividad)
- Limita las conversaciones almacenadas para prevenir crecimiento ilimitado del almacenamiento
- Permite a los usuarios eliminar conversaciones
UI con streaming
Las interfaces de chat deben mostrar los tokens conforme se generan. Esto crea la percepción de un asistente rápido y responsivo.
iOS (SwiftUI)
struct ChatView: View {
@StateObject var viewModel = ChatViewModel()
var body: some View {
ScrollView {
ForEach(viewModel.messages) { message in
MessageBubble(message: message)
}
}
.onChange(of: viewModel.streamingText) { _ in
// Auto-scroll hacia abajo
}
HStack {
TextField("Mensaje", text: $viewModel.input)
Button("Enviar") { viewModel.send() }
}
}
}
Android (Compose)
@Composable
fun ChatScreen(viewModel: ChatViewModel) {
val messages by viewModel.messages.collectAsState()
val streaming by viewModel.streamingText.collectAsState()
LazyColumn {
items(messages) { message ->
MessageBubble(message)
}
if (streaming.isNotEmpty()) {
item { StreamingBubble(streaming) }
}
}
Row {
TextField(value = input, onValueChange = { input = it })
Button(onClick = { viewModel.send(input) }) { Text("Enviar") }
}
}
Cadencia de visualización de tokens
llama.cpp genera tokens uno a la vez. Mostrar cada token individualmente puede causar parpadeo visual. Almacena en buffer 2-3 tokens antes de actualizar la UI para una apariencia de texto más fluida:
private var tokenBuffer = StringBuilder()
private var bufferCount = 0
fun onToken(token: String) {
tokenBuffer.append(token)
bufferCount++
if (bufferCount >= 3 || token.contains("\n")) {
updateUI(tokenBuffer.toString())
tokenBuffer.clear()
bufferCount = 0
}
}
Gestión del ciclo de vida del modelo
Carga y descarga
La carga del modelo toma 1-3 segundos dependiendo del tamaño del modelo y el dispositivo. La descarga es instantánea. Gestiona el ciclo de vida para equilibrar la capacidad de respuesta con la memoria:
- Cargar en la primera interacción con IA: No cargues al iniciar la app. Carga cuando el usuario abre la función de chat.
- Mantener cargado durante la sesión activa: Mientras el usuario esté en el chat, mantén el modelo en memoria.
- Descargar al navegar fuera: Cuando el usuario abandona la pantalla de chat, descarga el modelo para liberar RAM.
- Manejar advertencias de memoria: Regístrate para las advertencias de memoria del sistema y descarga el modelo si se activan.
Indicador de carga
Muestra un breve estado de carga (1-3 segundos) cuando el modelo se carga por primera vez. Después de eso, las respuestas comienzan a generarse inmediatamente. Los usuarios están acostumbrados a breves estados de carga para nuevas funciones.
Fine-Tuning para tu asistente
La brecha de calidad entre un modelo base y un modelo con fine-tuning es dramática para chat:
| Métrica | Base 3B | Fine-Tuned 3B |
|---|---|---|
| Respuestas dentro del tema | 60-70% | 92-96% |
| Adherencia al formato | 55-65% | 94-98% |
| Precisión de dominio | 50-60% | 88-94% |
| Consistencia de tono | 40-50% | 90-95% |
Datos de entrenamiento para chat
Crea ejemplos de entrenamiento que cubran:
- Preguntas comunes: Las 50-100 preguntas que los usuarios hacen con más frecuencia
- Casos extremos: Preguntas fuera de alcance, con respuestas de redirección elegante
- Patrones multi-turno: Conversaciones que abarcan 3-5 turnos mostrando seguimiento natural
- Ejemplos de estilo: Respuestas con la voz de tu marca y tu formato preferido
500-2,000 conversaciones de entrenamiento producen un asistente de chat de alta calidad. Plataformas como Ertas manejan el pipeline de entrenamiento: sube ejemplos de conversación, haz fine-tuning con LoRA, exporta GGUF.
Consideraciones de producción
Guardarraíles de calidad de respuesta
Los modelos en dispositivo pueden generar respuestas fuera de tema o incorrectas. Implementa guardarraíles ligeros:
- Validación de entrada: Verifica entradas extremadamente largas o contenido que obviamente no es texto
- Monitoreo de salida: Registra los temas de las respuestas (localmente) para identificar problemas de calidad
- Mecanismo de retroalimentación: Permite a los usuarios reportar respuestas malas. Usa esta retroalimentación para mejorar los datos de entrenamiento
Monitoreo de rendimiento
Rastrea métricas en el dispositivo:
- Tiempo hasta el primer token (debe ser menor a 300ms)
- Tokens por segundo (debe mantenerse por encima de 10)
- Tiempo de carga del modelo
- Uso de memoria durante la inferencia
- Tasa de fallos durante interacciones con IA
Actualizaciones del modelo
Distribuye mejoras del modelo a través de tu pipeline normal de entrega de modelos:
- Busca actualizaciones al iniciar la app (cuando hay conexión)
- Descarga en segundo plano
- Intercambia el archivo del modelo al iniciar la siguiente sesión de chat
- Mantén el modelo anterior como respaldo hasta que el nuevo esté validado
El resultado es un asistente de chat que funciona en todas partes, responde al instante, no cuesta nada por conversación y mantiene los datos del usuario completamente privados.
Ship AI that runs on your users' devices.
Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.
Keep reading

On-Device Semantic Search: AI-Powered Search Without a Server
How to build semantic search that runs entirely on the user's phone. Local embeddings, vector similarity, and natural language queries across user content without a server or API.

On-Device Text Classification for Mobile Apps
How to build fast, accurate text classification that runs on the user's phone. Sentiment analysis, content categorization, intent detection, and spam filtering without an API call.

On-Device Content Generation: AI Drafts That Work Offline
How to build AI-powered drafting features that work without internet. Email replies, message suggestions, note expansion, and content templates generated entirely on the user's device.