Vanguardia EPIS is designed for teachers in Peruvian rural schools, where internet access at the point of use — the school itself — can be intermittent or absent. According to BID (2024), 6 in 10 lower-income Peruvian students have no home internet; this is also the demographic whose teachers are the primary users of this system. To ensure the dashboard always shows complete, useful information regardless of connectivity, the system maintains a pre-generated JSON cache of all AI responses. This is not an optional optimisation — Article VIII §6.1 of the project constitution makes the cache mandatory.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Pierrot-01/Hackathon_epis_2026/llms.txt
Use this file to discover all available pages before exploring further.
How the Cache Fits into the Resilience Chain
The offline cache is the second layer in a three-level resilience chain managed byia_client.py:
Cache File Location
fallback.py at import time:
Cache File Structure
The cache is a flat JSON object keyed by student ID. Each entry contains the two AI-generated text fields plus a UTC timestamp recording when the entry was generated.Students classified as ⚪ (
NIVEL_INSUFICIENTE) are not stored in the cache — there are no motives to explain, so no AI response is generated for them. The generar_cache.py script explicitly skips them with a log message.fallback.py — Module Reference
Lazy-Loading Pattern
The cache is loaded from disk only once, on the first call to any function in the module. Subsequent calls reuse the in-memory dict. This avoids repeated disk I/O during a session where the dashboard may request dozens of students.obtener_fallback(id_estudiante)
Looks up a student in the in-memory (lazily loaded) cache. Returns a ready-to-use response dict if the student is found, or None if not.
None — the caller (ia_client.py) then invokes respuesta_error_sin_cache().
guardar_en_cache(id_estudiante, explicacion, recomendacion)
Persists a new entry to both disk and the in-memory dict. Used by generar_cache.py during cache pre-generation, and also called by ia_client.py after every successful live API response so the cache stays up to date.
- Calls
_cargar_cache()to ensure the in-memory dict is initialised - Adds or overwrites the entry with a fresh UTC timestamp
- Creates the
cache/directory if it does not exist (mkdir parents=True) - Writes the entire updated dict to
respuestas_ia.jsonwithensure_ascii=False - Updates
_cachein memory so subsequent reads reflect the new entry immediately
respuesta_error_sin_cache()
The last-resort response. Article VIII §6.2 mandates that no raw error is ever shown to the teacher. This function always returns a polite, actionable message.
generar_cache.py — Pre-Generation Script
generar_cache.py (at the project root) is a standalone async script that populates the entire cache in one pass before the server starts. It operates as follows:
Validate GEMINI_API_KEY
The script aborts immediately with a helpful error and a link to Google AI Studio if the environment variable is not set.
Classify each student
Calls
clasificar_estudiante() for each record. Students classified as ⚪ are skipped with an ⚪ omitido log message.Call Gemini live for each student
For non-⚪ students, calls
generar_explicacion() sequentially (with a 0.5 s delay between calls to avoid rate-limiting). Only responses with origen_ia == "vivo" are written to the cache.Automatic Cache Generation via start.sh
The start.sh startup script checks for the cache file before launching the server. If the cache does not yet exist and a valid API key is available, it runs generar_cache.py automatically — so the first launch is always fully prepared.
In-Memory Session Cache in main.py
Separate from the disk cache in fallback.py, main.py maintains its own in-memory session cache to avoid redundant API calls during a single server session.
GET /api/estudiantes, all students are processed in parallel via asyncio.gather() and the results are stored in _resultados_cache. Subsequent requests return the in-memory results instantly. This cache is cleared when the server restarts.
| Cache | Location | Survives restart | Purpose |
|---|---|---|---|
| Disk cache | cache/respuestas_ia.json | ✅ Yes | Offline fallback, pre-generated AI responses |
| Session cache | _resultados_cache in main.py | ❌ No | Avoid duplicate API calls within one session |