INTERNET y ACCESS_NETWORK_STATE (tools:node="remove"), allowBackup=false y data_extraction_rules.xml impiden copias en la nube. tools/check_offline.js lo audita en CI.src/core/) es TypeScript puro con pruebas Jest. Los servicios (src/services/) son adaptadores finos sobre librerías nativas.LlamaService mantiene un único LlamaContext; cambiar de modelo libera el anterior.┌──────────────────────────── UI (React Native) ────────────────────────────┐
│ Inicio · Chat · Materias · Herramientas · Gestor de modelos · Documentos │
└───────────────┬───────────────────────────────────────────────────────────┘
│ hooks (useLlmStatus, useStreamingTool, useFocusData)
┌───────────────▼──────────────── Servicios ────────────────────────────────┐
│ ChatService → prompt.ts + RagService + LlamaService + WatermelonDB │
│ StudyService → study.ts + LlamaService │
│ ModelManager → gguf.ts + DeviceStats (Kotlin) + ModelPack (Kotlin) │
│ RagService → chunking.ts + EmbeddingService (ONNX) + VectorStore │
│ DocumentProcessor→ docx.ts / PDF→imagen→OcrService / TXT │
│ OcrService → ML Kit + ocrLayout.ts + recorte (image-editor) │
│ CurriculumImporter → curriculumPack.ts + unzip + VectorStore │
│ BackupService → zip + saveDocuments (diálogo del sistema) │
└───────────────┬───────────────────────────────────────────────────────────┘
┌───────────────▼──────────────── Nativo ───────────────────────────────────┐
│ llama.rn (llama.cpp, C++) · onnxruntime-react-native · op-sqlite+sqlite-vec│
│ WatermelonDB (SQLite, JSI) · ML Kit Text Recognition v2 (bundled) │
│ DeviceStatsModule.kt · ModelPackModule.kt │
└────────────────────────────────────────────────────────────────────────────┘
| Tema | Decisión | Motivo |
|---|---|---|
| Inferencia | llama.rn (llama.cpp) con use_mmap, sin mlock, n_gpu_layers=0 por defecto |
Estándar en móviles; mmap permite modelos cercanos a la RAM libre; la GPU móvil es inconsistente entre gamas |
| Plantilla de chat | Se envían messages y llama.rn aplica la plantilla Jinja embebida en el GGUF |
Soporta Llama 3.2 y Qwen 2.5 sin código específico |
| Contexto | 2048 tokens por defecto; 1024 con memoria baja; 512 reservados a la respuesta, ≤600 al RAG | Equilibrio entre calidad y velocidad en gama media |
| Truncamiento | Se conserva sistema + RAG + mensaje actual; el historial se agrega del más reciente al más antiguo hasta llenar el presupuesto; nunca inicia con una respuesta huérfana | core/prompt.ts |
| Embeddings | all-MiniLM-L6-v2 INT8 (≈23 MB) en ONNX Runtime; tokenizador WordPiece propio | Sin dependencias nativas extra; 384 dimensiones = índice pequeño |
| Base vectorial | op-sqlite con sqlite-vec (vec0, distancia coseno); fallback a fuerza bruta en JS |
WatermelonDB no permite cargar extensiones; se usa una segunda BD SQLite solo para vectores |
| Filtro por materia | KNN con sobre-muestreo (k×6) y filtro posterior; los documentos del usuario siempre participan | Compatible con cualquier versión de sqlite-vec |
| Renderizar páginas a imagen y aplicar OCR (máx. 80 páginas) | Una sola ruta para PDFs digitales y escaneados, sin motor PDF en JS | |
| DOCX | Descomprimir y leer word/document.xml |
Formato abierto; sin librerías pesadas |
| OCR | ML Kit v2 empaquetado (com.google.mlkit:text-recognition) |
No depende de Google Play Services para descargar el modelo |
| Recorte inteligente | Rectángulo que envuelve los bloques detectados (+4 % de margen); segundo pase si el primero halló poco texto | Mejora legibilidad de la vista previa y el OCR de texto pequeño |
| Base de datos | WatermelonDB (SQLite + JSI) | Offline-first, perezosa, rápida con historiales largos |
| Flashcards | SM-2 simplificado; falladas se repiten en la misma sesión | Probado y fácil de explicar |
| Distribución | AAB con asset pack model_pack (fast-follow) + APK por ABI para sideload |
Cumple “split de Model Pack y App base” y permite instalar sin tienda |
ChatScreen → ChatService.sendMessage guarda el mensaje del usuario.RagService.retrieve genera el embedding de la pregunta (+ texto OCR) y busca top-4 en sqlite-vec.buildConversation arma [system+RAG, …historial recortado…, user] dentro del presupuesto.LlamaService.chat consulta currentTuning() (RAM/temperatura), genera en streaming y aplica pausa térmica.EmbeddingService acepta cualquier modelo BERT con vocabulario WordPiece y salida last_hidden_state (o ya agrupada). Para cambiarlo:
python tools/export_embedding_model.py --model sentence-transformers/distiluse-base-multilingual-cased-v2
Ajusta RAG.embeddingDim y EMBEDDING_MODEL_ID, y usa el mismo modelo en tools/build_curriculum_pack.py. Los modelos con tokenizador SentencePiece (p. ej. XLM-R) requerirían un tokenizador adicional.
ImagePicker.clean, removeIfExists); la carpeta tmp/ se vacía en cada arranque.check_offline.js falla si se agregan.op-sqlite admite SQLCipher ("op-sqlite": { "sqlcipher": true }) si se requiere cifrar la base vectorial con una clave del Android Keystore..zip mediante el diálogo del sistema; restauración con validación del formato.