Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/RubenDarioGuerreroNeira/Ecosistema-IA-Colombia/llms.txt

Use this file to discover all available pages before exploring further.

Salud IA Bot includes a regional provider directory covering four areas of Colombia: Antioquia, Boyaca, Cali, and Yopal. Queries are fully handled in natural language — users do not need to know provider names, addresses, or complexity levels in advance.
Yopal proximity search works with any Telegram-compatible client that supports the location sharing button. Make sure location permissions are enabled in your Telegram app.

Covered regions

RegionData sourceBackendNotable feature
AntioquiaXML seeded into SQLite via TypeORMAntioquiaHealthServiceText search across hospitals, clinics, municipalities
BoyacaXML seeded into SQLite via TypeORMBoyacaHealthServiceText search including Tunja and other municipalities
CaliSERVICIOS_OFERTADOS_RED_DE_SALUD_DEL_CENTRO_ESE_POR_SEDE_CALI.xml (in-memory)CaliHealthService8-step NLP routing, zero-hallucination fast path
YopalCentros_de_salud_Yopal._.xml (in-memory)YopalHealthServiceGPS proximity search with Haversine formula

Cali — zero-hallucination direct routing

The Cali module implements a special fast path through CaliHealthService.processCaliQuery(text). NLP detects the user’s intent and routes the query to the right data method without calling the LLM. Because the response comes entirely from the in-memory XML dataset, the hallucination rate for Cali provider queries is 0%. The routing pipeline follows eight ordered detection steps:
1

Knowledge query

Patterns like "que sabes de cali" or "servicios de salud en cali" are matched by isKnowledgeQuery(text) and return a formatted menu of available question categories via getAvailableQuestions().
2

Urgency / emergency detection

Any query containing urgencia, emergencia, 24 horas, or atencion inmediata triggers getEmergencyServices(), which filters providers whose grupo or servicio field includes urgency-related keywords.
3

Categories and groups

Queries containing categorias de servicios, grupo, categorias, or disponible return the full category list from getGruposDisponibles() with service counts per category.
4

Statistics and summary

Patterns like estadistica, cuantos, resumen, or total return getKnowledgeSummary() — total sedes, total services, top sedes by service count, and top service groups.
5

Specific sede lookup

The query is matched against the list of all unique sede names from getUniqueSedes(). If a sede name is found inside the normalized query string, formatSedeDetails(sedeName) returns address, phone, and up to 10 services for that sede.
6

Hospital / clinic filter

Terms like hospital or clinica filter providers where sede, grupo, or servicio fields contain these words.
7

Specific service search

A hardcoded list of services — odontologia, fisioterapia, laboratorio, radiologia, rayos x, psicologia, medicina general, consulta externa, pediatria, ginecologia, medicina interna, cirugia, dermatologia, nutricion, optometria, oftalmologia, ecografia, mamografia, vacunacion, farmacia — triggers searchByService(servicioMatch).
8

General fallback

Any remaining query runs searchProviders(text) across all indexed fields (ciudad, sede, servicio, grupo, direccion) using tokenized matching with stop-word filtering.

BYPASS_MARKERS and zero-hallucination guarantee

BYPASS_MARKERS (defined in constants/keywords.ts) is a list of sentinel strings — '--- ANÁLISIS', '--- RANKING', '--- DISTRIBUCIÓN', '--- ANÁLISIS GLOBAL', '--- SALUD MENTAL', '--- PERFIL DE RIESGO', '--- COMPARATIVA SIVIGILA' — that BotUpdate uses to detect pre-formatted responses from analytics services. When a response string contains one of these markers, the bot sends it directly to the user and skips the LLM call entirely.

Example Cali queries

"¿Dónde atienden urgencias en Cali?"
-> Returns up to 5 unique urgency/emergency providers with address and phone

"Sedes de alta complejidad en Cali"
-> Filters providers by complejidad field matching 'alta'

"Servicio de odontología en Cali"
-> Returns sedes offering odontologia with address and phone

"Sede Alfonso López Cali"
-> Returns full service portfolio for that specific sede

Yopal is the only region with live geolocation support. The flow is coordinated between BotUpdate and YopalHealthService:
1

Intent detection

The bot detects proximity phrases such as "centros de salud cerca de mí", "prestadores cercanos", or "cerca de mi ubicación" using isNearbyLocationQuery(text).
2

Location keyboard

requestLocationForNearbyProviders(ctx) sends a Telegram reply keyboard with request_location: true, displaying a “Compartir Ubicación” button to the user.
3

Location event handler

When the user taps the button, Telegram sends a location update. The @On('location') onLocation(ctx) handler in BotUpdate receives the GPS coordinates.
4

Haversine proximity query

YopalHealthService.findNearby(lat, lon, radiusKm) computes the distance from the user’s coordinates to every provider with valid geocoordinates using the Haversine formula (Earth radius = 6371 km). Default search radius is 5 km.
5

Sorted results

Providers are filtered to those within the radius, sorted by ascending distance, and returned as a formatted list with name, address, phone, and distance in km.
YopalHealthService also includes coordinate normalization logic (normalizeCoordinates) that handles common data quality issues in the open dataset — such as coordinates stored as integers without decimal points — by detecting string length and inserting the decimal separator at the correct position. Valid coordinates for Yopal/Casanare are validated against geographic bounds (lat 4 to 6, lon -70 to -74).

Additional Yopal search capabilities

Beyond proximity, Yopal supports:
  • Category classification: classifyProvider(entityName) assigns each provider to categories like EPS, HOSPITAL/CLINICA, ODONTOLOGIA, LABORATORIO, RADIOLOGIA/DIAGNOSTICO, OPTICA/OFTALMOLOGIA, TRANSPORTE/AMBULANCIA, and FARMACIA/OXIGENO based on keywords in the entity name.
  • 24-hour and emergency providers: getProvidersBySchedule('24h') and getEmergencyProviders() filter by keywords like 24 HORAS, URGENCIA, VITAL, and EMERGENCIA in the entity name.
  • Condition-based suggestion: suggestProvidersForCondition(condition) maps conditions like diabetes, embarazo, and fractura to relevant provider categories.
  • Fuzzy search: jaroWinkler(s1, s2) similarity scoring handles typos and partial name matches with a threshold of 0.7 to 0.8.

Antioquia and Boyaca use TypeORM repositories backed by a SQLite database. Provider data is seeded from XML at startup. Queries are resolved through text-based search across hospital and clinic records. Users can ask by city, municipality, or service type:
"Hospitales en Tunja"
-> Filters providers in Boyaca matching 'tunja' in municipality/city fields

"Clínicas en Medellín"
-> Filters providers in Antioquia matching 'medellin' in location fields

Region detection logic

BotUpdate determines which regional service to call by checking static lists before resorting to pattern matching:
  • Static lists: DEPARTMENTS (all Colombian departments), CAPITALS (department capitals), and MAJOR_VALLE_TOWNS (key municipalities in Valle del Cauca including Cali) are checked first.
  • NLP regex fallback: Patterns like "en [region]" and "de [region]" are extracted from the query text to identify the target region when it is not found in the static lists.
  • Keyword override: Explicit mentions of "Cali", "Yopal", "Antioquia", or "Boyaca" in the query always route to the corresponding service regardless of other content.

Build docs developers (and LLMs) love