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 ships a family of analytics services that operate on structured local datasets — SIVIGILA epidemiological records, CIE-10 mental health diagnosis registries, sexual health Q&A pairs, PAI vaccination coverage, and environmental air quality readings. Each service exposes typed methods that produce formatted strings ready for Telegram rendering, bypassing the LLM entirely for deterministic fact retrieval.

HealthStatsService

HealthStatsService aggregates the SIVIGILA dataset loaded by HealthDataService and produces formatted analytical summaries. It also exposes a simple linear regression predictor for next-period case count estimation.
MethodReturnsExample query
getDiseaseComparison(diseaseName)Promise<string>"Compara casos urbanos y rurales de dengue"
getHealthEventAgeAnalysis(diseaseName)Promise<string>"Distribución por edad de varicela"
getTopDiseasesRanking()Promise<string>"Ranking de enfermedades con más casos"
getGlobalGenderAnalysis()Promise<string>"¿En general hay más casos en mujeres u hombres?"
getHealthKnowledgeSummary()Promise<string>"¿Qué datos de salud pública tienes?"
predictNextValue(historicalData)numberInternal - used by prediction pipeline

predictNextValue(historicalData: number[]): number

Implements simple linear regression over an array of historical case counts. Returns the projected value for period n (the next step after the last observed point).
predictNextValue(historicalData: number[]): number {
  const n = historicalData.length;
  if (n < 2) return historicalData[0] || 0;

  let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
  for (let i = 0; i < n; i++) {
    sumX += i;
    sumY += historicalData[i];
    sumXY += i * historicalData[i];
    sumX2 += i * i;
  }

  const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
  const intercept = (sumY - slope * sumX) / n;
  const prediction = slope * n + intercept;
  return Math.max(0, Math.round(prediction));
}
The prediction is floor-clamped at zero — negative case projections are treated as zero.

getDiseaseComparison(diseaseName: string)

Fetches SIVIGILA stats for the named event and returns an urban/rural analysis block:
--- ANÁLISIS ESTADÍSTICO: DENGUE ---
Total de Casos: 45321
📍 Zona Urbana: 38900 casos (85.8%)
🏡 Zona Rural: 6421 casos (14.2%)
📈 Relación Urbano/Rural: 6.1 veces más casos en zonas urbanas.
Conclusión: La incidencia es predominantemente urbana.

getHealthEventAgeAnalysis(diseaseName: string)

Identifies the most affected age group and the top-two “critical range” that together concentrate the largest share of cases:
--- DISTRIBUCIÓN ETARIA: DENGUE ---
Total Casos: 45321
👥 Grupo más afectado: Adulto Joven (62.3%)
⚠️ Rango Crítico: Adulto Joven y Adulto Mayor concentran el 74.1% de los casos.
Conclusión: Se recomienda priorizar campañas de prevención en el grupo de Adulto Joven.

MentalHealthService

MentalHealthService loads data/Salud_Mental.xml on instantiation and exposes CIE-10 diagnosis data with full age-bracket breakdowns. The XML schema maps each row to a MentalHealthEvent interface.

MentalHealthEvent interface

export interface MentalHealthEvent {
  diagnostico_ingreso: string;  // Diagnosis label
  codigo_dx_ingreso: string;    // CIE-10 code
  menor_a_1: number;
  de_1_a_4: number;
  de_5_a_9: number;
  de_10_a_14: number;
  de_15_a_19: number;
  de_20_a_49: number;
  de_50_a_64: number;
  _65_y_mas: number;
  total: number;
  a_o_diagn_stico: string;      // Diagnostic year
}
MethodReturnsDescription
getStatsForDiagnosis(query)Promise<MentalHealthEvent | null>Exact then partial match on diagnosis name or CIE-10 code
getAllDiagnoses()Promise<string[]>Array of all diagnosis label strings
searchDiagnoses(query)Promise<MentalHealthEvent[]>Partial-match search by diagnosis label or CIE-10 code
getTopDiagnoses(limit)Promise<MentalHealthEvent[]>Top N diagnoses by total case count (default: 5)
getTopByLifeCycle(cycle, limit)Promise<MentalHealthEventWithTotal[]>Top diagnoses for a life-cycle group (niños, adolescentes, jovenes, adultos, mayores)
getAgeDistribution()Promise<Record<string, number>>Aggregate case counts for all age brackets across all diagnoses
getRiskProfileByDiagnosis(diagName)Promise<{diagnostico, total, distribucion} | null>Life-cycle risk profile for a specific diagnosis
getComparisonBetweenDiagnoses(d1, d2)Promise<{d1, d2} | null>Side-by-side comparison of two diagnoses
getStatsForDiagnosis prioritizes exact CIE-10 code or name match, then calls findDiagnosisInText() for scored token matching, and finally falls back to substring inclusion — avoiding ambiguous results for similar diagnoses.

Example query

"¿Cuántos casos de depresión hay?" calls getStatsForDiagnosis("depresión") and returns the row with diagnostico_ingreso matching depression, including the full age breakdown for graphing with ChartService.

SexualHealthService

SexualHealthService loads data/Salud_sexual_-_preguntas.xml, a curated Q&A corpus on sexual and reproductive health. It does not use the LLM — answers are retrieved directly from the XML.

SexualHealthQA interface

export interface SexualHealthQA {
  id: number;
  id_sub_tema: number;
  pregunta: string;
  respuesta: string;
  palabras_claves: string[];
}

Intencion enum

Intent classification used before search to apply topic-specific routing:
export enum Intencion {
  BUSCAR_INFORMACION    = 'buscar_info',
  BUSCAR_SERVICIO       = 'buscar_servicio',
  PREVENCION            = 'prevencion',
  TRATAMIENTO           = 'tratamiento',
  DERECHOS              = 'derechos',
  EMERGENCIA            = 'emergencia',
  RIESGO_ITS            = 'riesgo_its',
  EMBARAZO_ADOLESCENTE  = 'embarazo_adolescente',
}

Topic coverage

IntentExample keywordsSample response topic
EMERGENCIAviolacion, abuso, agresion, acidoEmergency protocol, referral routes
RIESGO_ITSvih, condon, its, sexo sin proteccionPost-exposure prophylaxis within 72h
EMBARAZO_ADOLESCENTEembarazada, adolescente, gestanteSSAAJ advisory services
BUSCAR_SERVICIOdonde, acudir, ips, pastillasHealth service lookup
BUSCAR_INFORMACION(default fallback)General sexual health information

classifyIntent(query: string): Intencion

Applies keyword inclusion tests in priority order (EMERGENCIA first, then RIESGO_ITS, EMBARAZO_ADOLESCENTE, BUSCAR_SERVICIO, then BUSCAR_INFORMACION as the default) to classify the incoming query before invoking searchByKeyword.

searchByKeyword(query: string): Promise<SexualHealthQA[]>

Applies normalized 6-character stem matching across pregunta, respuesta, and palabras_claves fields. A Q&A pair matches if >= 70% of the query’s stemmed tokens are found in the combined text. Pre-defined bypass responses for high-priority keywords (vih, condon, pastillas, vasectomia, embarazada, pomeroy) return a fixed, validated answer without running the general search — guaranteeing accuracy for the most sensitive topics.

VaccinationService

VaccinationService reads the PAI (Programa Ampliado de Inmunización) vaccination coverage dataset from SQLite via TypeORM. It is injected into MlPredictionService, AdvancedPredictionService, and EarlyWarningService to enrich risk scores with real coverage figures.
MethodReturnsDescription
getCoverageByDepartment(departamento)Promise<VaccinationCoverage[]>Returns all vaccine coverage records matching the department name
getAllDepartament()Promise<string[]>Distinct sorted list of all departments in the dataset

VaccinationCoverage interface

interface VaccinationCoverage {
  coddepto: string;
  departamento: string;
  a_o: string;
  biol_gico: string;                  // Vaccine name
  cobertura_de_vacunaci_n: string;    // Coverage value (decimal 0–1 or raw dose count)
}
getCoverageByDepartment searches both the departamento and indicator1 columns with a LIKE query, accommodating variant department name spellings stored in the XML source.
Coverage values may be stored as decimals (0–1) or as dose counts depending on the vaccine type. MlPredictionService normalizes these with a rawVal <= 1 ? rawVal * 100 : rawVal check before comparing against thresholds.

AirQualityService

AirQualityService queries the Colombian open data portal (datos.gov.co) Socrata API for real-time air quality measurements. Air quality indicators are used by the prediction pipeline as environmental risk factors.
MethodReturnsDescription
getAirQualityByMunicipio(municipio)Promise<any>Fetches up to 10 records matching municipality or department name
getAllMunicipios()Promise<string[]>Distinct sorted list of monitored municipalities
getAllDepartamentos()Promise<string[]>Distinct sorted list of monitored departments

API endpoint

GET https://www.datos.gov.co/resource/kekd-7v7h.json
  ?$where=nombre_del_municipio like '%MEDELLÍN%'
  &$limit=10
The $where clause uses Socrata SoQL LIKE against both nombre_del_municipio and nombre_del_departamento, so either a city name or a department name resolves to the correct records.
Air quality data is used in AdvancedPredictionService.obtenerFactoresInfluencia() to add an environmental context sentence to forecast recommendations when monitored variables are available for the queried location.

Build docs developers (and LLMs) love