Pipeline Overview¶
The pipeline turns public news articles into structured healthcare disruption records. Two independent source pipelines (GDELT and HTML scraper) feed into the same LLM validation and field-extraction layer, then record results to local JSON/CSV and optionally to Supabase.
Main Flow¶
GDELT Pipeline¶
Seed Discovery
src/GDELT/gdelt_seeds.pyscans GDELT GKG files, filtering by sector themes (configured insrc/GDELT/sector_themes.py)Seeds can be collected across multiple threads (
--gdelt-seed-threads)
Scraping
src/shared_utils.get_body_and_title()fetches each candidate URL and extracts the article body and title
Validation and Classification (shared with the HTML pipeline)
src/shared_utils.pycalls a local Ollama endpoint to classify the article as an operational disruption and assign a subsectorOptionally,
src/GDELT/BERT_filter.pycan be used as a pre-screen before LLM validation however this functionality is deprecated
Field Extraction (shared with the HTML pipeline)
Confirmed disruptions are given one of the following subsectors:
cyber_attackdrug_shortagemedical_device_shortagenatural_disasterother: a catch all to capture disruptions that don’t fit the above categories
src/shared_utils.extract_fields()prompts the LLM with a subsector-scoped JSON template to extract subsector-specific info about the disruptionRecords are built as
Vulnerabilityobjects (src/classes/vulnerability.py) with subsector-specific dataclasses (DrugShortageData,MedicalDeviceShortageData,CyberAttackData,NaturalDisasterData,OtherData)
Saving results
The runner writes intermediate stage files under
data/raw/gdelt/{seeds,validated,enriched}/, appends final records todata/output/results.json(orchestrator default) ordata/processed/GDELT.json(runner default), and updatesdata/seen_urls.json
HTML Pipeline¶
Scraping
src/scrapers/scooper.pypaginates through configured HTML news sites (CyberScoop, StateScoop, FedScoop, AHA, HealthIT News), fetching article bodies and datesNew raw rows are appended to
data/raw/scooper_raw.csv
Validation and Classification (shared with the GDELT pipeline)
src/shared_utils.pycalls a local Ollama endpoint to classify the article as an operational disruption and assign a subsectorOptionally,
src/GDELT/BERT_filter.pycan be used as a pre-screen before LLM validation
Field Extraction (shared with the GDELT pipeline)
Confirmed disruptions are given one of the following subsectors:
cyber_attackdrug_shortagemedical_device_shortagenatural_disasterother: a catch all to capture disruptions that don’t fit the above categories
src/shared_utils.extract_fields()prompts the LLM with a subsector-scoped JSON template to extract subsector-specific info about the disruptionRecords are built as
Vulnerabilityobjects (src/classes/vulnerability.py) with subsector-specific dataclasses (DrugShortageData,MedicalDeviceShortageData,CyberAttackData,NaturalDisasterData,OtherData)
Saving Results
HTML results will output in
data/processed/scooper.json
Recommendations¶
Each pipeline was designed to be able to run standalone using its own command line interfaces; however, it is highly recommended to fill out and use the config-template.cfg as it covers the same settings that can be passed as arguments.
Deprecated features¶
This project also contains a deprecated RAG pipeline and frontend to query records. It can be used with the following commands:
python -m src.ingest --file data/processed/GDELT.json
Then run the app:
uvicorn src.RAG.server:app --reload
Outputs¶
Path |
Description |
|---|---|
|
Candidate URLs before LLM validation |
|
Records confirmed as disruptions |
|
Records with filled-in fields |
|
Raw scraped HTML articles |
|
GDELT output (orchestrator default) |
|
HTML scraper output |
|
Validated HTML scraper records |
|
Rejected HTML scraper articles |
|
URL history for GDELT |
|
Cached GKG zip files |
|
Per-module log files |
|
Local vector store for the RAG app |
GDELT Recovery¶
In the case of an unrecoverable pipeline state, the GDELT pipeline saves records in stages all preserved in data/raw/gdelt/seeds/.
To recover from staged GDELT data:
# Stitch from enriched data
python -m src.GDELT.runner --stitch-stage enriched
# Stitch from validated data
python -m src.GDELT.runner --stitch-stage validated
# Stitch from seeds (re-runs scraping + LLM)
python -m src.GDELT.runner --stitch-stage seeds
Current Supporting Modules¶
Module |
Role |
|---|---|
|
Runs GDELT and/or HTML, manages multithreading and progress bars |
|
GDELT end-to-end: seed collection → scrape → validate → extract → output |
|
GKG file discovery, theme matching, subsector detection, URL quality |
|
Sector and subsector theme definitions |
|
Optional pre-screen using BERT model before LLM validation |
|
Old code; filter for healthcare-related articles using Ollama |
|
Filter for healthcare-related articles using Gemma |
|
HTML site scraping and LLM classification for configured news sites |
|
FDA Reports to Congress PDF scraper (drug shortage reports) |
|
Utilities used by both GDELT and HTML pipelines (article fetching, LLM validation/extraction, config loading, signal handling) |
|
|
|
Live progress bars and run summaries |
|
File-backed module loggers |
|
JSON to ChromaDB ingestion with semantic dedup and chunking |
|
FastAPI chat endpoints and web UI |
|
Semantic fingerprint embedding for Supabase dedup |
|
Supabase client, reads, and writes |
|
Generate Supabase-ready SQL from local CSV/JSON files |
Note¶
The
data/gdelt_cache/directory is not auto-cleared unless the--cleanflag is used or set in your config; you can manually delete the contents of the directory to clear disk space or force fresh downloads
CORVID