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.

src/bot/constants/keywords.ts is the single source of truth for all intent detection in Salud IA Bot. Rather than scattering trigger strings across handler methods, every keyword list, region array, bypass marker, and greeting pattern is exported from this module and imported by bot.update.ts. This makes it straightforward to extend coverage or tune specificity without touching handler logic.

Exported Constants

YOPAL_KEYWORDS

An exhaustive array of phrases that identify queries about health services in Yopal, Casanare. The list combines generic proximity queries (cerca de mi, hospital cercano en yopal) with the exact names of local providers registered in the dataset (e.g., capresoca, clinica casanare, esesalud, coosalud). When any term matches, the message is routed to YopalHealthService.
export const YOPAL_KEYWORDS = [
    'yopal',
    'qué información tienes de yopal',
    'laboratorios clínicos en yopal',
    'servicios de urgencias en yopal',
    'hospitales en yopal',
    'cerca de mi estoy en yopal',
    'prestadores de salud en yopal',
    // ... provider names: capresoca, coomeva en yopal, clinica casanare,
    // esesalud, coosalud, cardio andes, vital alliance, …
];

RISK_ANALYSIS_KEYWORDS

Keywords that signal a disease-level risk or mental health query — not a predictive/forecast query (those are caught earlier by inline normPred checks in onText). Current terms cover major communicable diseases and mental health conditions:
export const RISK_ANALYSIS_KEYWORDS = [
    'tuberculosis', 'dengue', 'zika', 'malaria', 'sarampion',
    'rubeola', 'fiebre amarilla', 'hepatitis', 'polio', 'tos ferina',
    'ansiedad', 'depresion', 'estres', 'trastorno mental',
];

ENVIRONMENTAL_KEYWORDS

Triggers for environmental and vector-borne disease queries, including air-quality-adjacent conditions. Note the intentional overlap with RISK_ANALYSIS_KEYWORDS (e.g., dengue, zika) — routing priority order in onText determines which handler wins:
export const ENVIRONMENTAL_KEYWORDS = [
    'dengue', 'zika', 'chikun', 'malaria', 'tuberculosis', 'contaminacion',
    'chagas', 'ofidico', 'animales', 'eta', 'alimentos', 'intoxicacion',
    'desnutricion', 'respiratoria',
];

CYCLE_KEYWORDS

An array of objects that map colloquial life-cycle terms to canonical age-group identifiers. Used by vaccination and public health services to filter datasets by demographic segment:
export const CYCLE_KEYWORDS = [
    { keys: ['adolescente', 'adolescentes'], cycle: 'adolescentes' },
    { keys: ['jovenes', 'joven'],            cycle: 'jovenes'      },
    { keys: ['mayores', 'mayor'],            cycle: 'mayores'      },
    { keys: ['ninos', 'nino', 'nena'],       cycle: 'niños'        },
    { keys: ['adultos', 'adulto'],           cycle: 'adultos'      },
];

GRAPHIC_KEYWORDS

Phrases that trigger ChartQueryService to generate a chart image instead of a text response. Covers both accented and unaccented spellings to handle the full range of mobile keyboard input:
export const GRAPHIC_KEYWORDS = [
    'graficos', 'gráficos', 'graficar', 'gráficar', 'visualizar', 'visualiza',
    'dibujar', 'dibuja', 'mostrar gráfico', 'mostrar graficos', 'mostrar gráfico de',
    'mostrar graficos de', 'puedes graficar', 'puedes mostrar un gráfico de',
    'puedes mostrar un graficos de',
];

DEPARTMENTS

The full array of the 32 Colombian departments used by the region-detection helper (detectRegion). Values match the official names with diacritics:
export const DEPARTMENTS = [
    'Amazonas', 'Antioquia', 'Arauca', 'Atlántico', 'Bolívar', 'Boyacá',
    'Caldas', 'Caquetá', 'Casanare', 'Cauca', 'Cesar', 'Chocó', 'Córdoba',
    'Cundinamarca', 'Guainía', 'Guaviare', 'Huila', 'La Guajira', 'Magdalena',
    'Meta', 'Nariño', 'Norte de Santander', 'Putumayo', 'Quindío', 'Risaralda',
    'San Andrés', 'Santander', 'Sucre', 'Tolima', 'Valle del Cauca',
    'Vaupés', 'Vichada',
];

CAPITALS

The 31 departmental capital cities (plus Bogotá). Checked alongside DEPARTMENTS for region detection so that users can refer to a city instead of its department:
export const CAPITALS = [
    'Leticia', 'Medellín', 'Arauca', 'Barranquilla', 'Cartagena', 'Tunja',
    'Manizales', 'Florencia', 'Yopal', 'Popayán', 'Valledupar', 'Quibdó',
    'Montería', 'Bogotá', 'Inírida', 'San José del Guaviare', 'Neiva',
    'Riohacha', 'Santa Marta', 'Villavicencio', 'Pasto', 'Cúcuta', 'Mocoa',
    'Armenia', 'Pereira', 'Bucaramanga', 'Sincelejo', 'Ibagué', 'Cali',
    'Mitú', 'Puerto Carreño',
];

MAJOR_VALLE_TOWNS

Supplementary municipalities in the Valle del Cauca department. These fall outside the capital (Cali) but are served by the CaliHealthService dataset and need their own entries for accurate region detection:
export const MAJOR_VALLE_TOWNS = [
    'Buga', 'Tuluá', 'Palmira', 'Jamundí', 'Cartago', 'Buenaventura',
    'Yumbo', 'Candelaria', 'Florida', 'El Cerrito', 'Sevilla', 'Zarzal',
    'Caicedonia', 'Guacarí', 'Roldanillo',
];

OTHER_REGION_NAMES

Additional region aliases and EPS (health insurer) names that should trigger region-aware routing even when the user does not mention a full department or capital name:
export const OTHER_REGION_NAMES = [
    'valle', 'capresoca', 'coomeva', 'medimas', 'sanitas', 'nueva eps',
    'coosalud', 'horo', 'orinoquia', 'atioquia',
];

BYPASS_MARKERS

A set of string markers that services embed at the start of structured responses. When BotUpdate retrieves a summary from StatsService and finds any of these markers in the result, it sends the response directly to the user without forwarding it to the LLM for rephrasing. This prevents the AI from paraphrasing or degrading structured data outputs:
export const BYPASS_MARKERS = [
    '--- ANÁLISIS',
    '--- RANKING',
    '--- DISTRIBUCIÓN',
    '--- ANÁLISIS GLOBAL',
    '--- SALUD MENTAL',
    '--- PERFIL DE RIESGO',
    '--- COMPARATIVA SIVIGILA',
];

GREETING_REGEX

A single compiled regular expression that detects greeting messages and /start commands. Matched messages are handled by handleGreeting(), which returns a personalised welcome with the user’s first name and a summary of bot capabilities:
export const GREETING_REGEX =
  /^(hola|buenos dias|buenas tardes|buenas noches|saludos|hi|hello|\/start|que sabes hacer|que puedes hacer)/i;

Intent Routing Priority in onText()

BotUpdate.onText() applies the following priority chain. Each handler returns true if it consumed the message (causing an early return) or false to fall through to the next priority level.
PriorityTriggerHandler / Service
0Service capability queries (qué info tienes de…)handleServiceCapabilitiesQuery()
1Structural data queries (counts, lists)handleStructuralDataQuery()
2Mental health diagnoses / risk profilesMentalHealthQuestionsService.handleMentalHealthQuery()
2.5Public health queries (SIVIGILA)handleSaludPublicaQuestions()
3.5Predictive alerts, forecasts, early warningshandleNewPredictiveServices() via PredictiveQuestionsService
4Chart / graphic generationhandleChartQuery() via ChartQueryService
5Greetings / /starthandleGreeting()
6Cali-specific provider querieshandleServiceCali() via CaliHealthService
6.5Antioquia provider querieshandleAntioquiaQuery() via AntioquiaHealthService
7General provider search (region detected)handleProviderSearch()
8Yopal-specific provider querieshandleYopalQuery() via YopalHealthService
9ML-based disease predictionhandlePrediction()
10Air quality querieshandleAirQualityQuery() via AirQualityQuestionsService
11General statistics + bypass checkStatsService.getSummary() + BYPASS_MARKERS
12Sexual health Q&AhandleSexualHealthQuery() via SexualHealthService
13ML risk classificationhandleMLClassification()
14Public health events by namehandleSaludPublica() via SaludPublicaService
15General LLM fallbackhandleGeneralQuery() via GenkitService

Bypass Marker Flow

The bypass system prevents double-processing of structured responses. When StatsService.getSummary() returns data (priority 11), the result is checked against BYPASS_MARKERS before any LLM call is made:
// PRIORIDAD 11: Estadísticas generales
const contextData = await this.statsService.getSummary(messageText);
if (contextData && BYPASS_MARKERS.some(marker => contextData.includes(marker))) {
    await this.sendLongMessage(ctx, contextData);
    return;
}
If the structured data block starts with a bypass marker (e.g., --- ANÁLISIS or --- RANKING), BotUpdate sends it directly and returns — the LLM never sees it. If there is no bypass marker, the context data is appended to the LLM prompt at priority 15 to enrich the general response.
To add a new intent, add the trigger keywords to the appropriate array in keywords.ts and add a corresponding routing branch in BotUpdate.onText(). Keep keyword lists ordered from most-specific to least-specific to avoid false matches — for example, 'clinica casanare' should appear before a generic 'casanare' entry.

Build docs developers (and LLMs) love