Parallel Ingestion¶
Run PubMed, PMC, and bioRxiv ingestion in parallel for bulk KG building. Each source gets its own subprocess with independent Neo4j connections and LLM instances. Neo4j handles concurrent writes safely via its transaction model.
Quick Start¶
# Dry run — show what would be launched without running
uv run python parallel_ingest.py \
-q data/queries_bulk.txt \
--biorxiv-queries-file data/queries_biorxiv.txt \
-d olink1 -s bedrock --dry-run
# Full parallel run (overnight)
uv run python parallel_ingest.py \
-q data/queries_bulk.txt \
--biorxiv-queries-file data/queries_biorxiv.txt \
-d olink1 -s bedrock \
--skip-node-labeling \
--pubmed-max 500 --pmc-max 200 --biorxiv-max 100
How It Works¶
parallel_ingest.py
├── Parses queries file (one MeSH query per line)
├── Builds ingest_main.py commands for each enabled source
├── Launches all sources as async subprocesses
├── Tails each log in real-time (5s interval)
├── Waits for all to complete
└── Prints summary: ✅/❌ per source + wall-clock time
Logs are written to logs/parallel_YYYYMMDD_HHMMSS/{source}.log.
All Options¶
| Flag | Default | Description |
|---|---|---|
--queries-file / -q |
required | Queries file (used for PubMed and PMC) |
--biorxiv-queries-file |
same as -q |
Separate queries for bioRxiv (simple keywords) |
--database / -d |
olink3 |
Neo4j database name |
--service / -s |
local |
LLM service (local, bedrock, sagemaker-llama3) |
--pubmed-max |
500 | Max results per query for PubMed |
--pmc-max |
200 | Max results per query for PMC |
--biorxiv-max |
100 | Max results per query for bioRxiv |
--skip-pubmed |
off | Skip PubMed source |
--skip-pmc |
off | Skip PMC source |
--skip-biorxiv |
off | Skip bioRxiv source |
--skip-node-labeling |
off | Skip post-ingestion labeling (saves hours) |
--enable-consolidation |
off | Run relationship consolidation during ingestion |
--force / -f |
off | Force re-ingestion of already-processed PMIDs |
--chunk-size |
2000 | Chunk size for full-text sources (words) |
--chunk-overlap |
200 | Chunk overlap (words) |
--pubmed-mass-scraper |
off | Use mass scraper for PubMed (millions of abstracts) |
--batch-size |
500 | Mass scraper batch size |
--max-concurrent-batches |
3 | Mass scraper concurrency |
--dry-run |
off | Show commands without running |
Query Files¶
data/queries_bulk.txt (74 lines, ~31 active queries)¶
MeSH-style queries for PubMed and PMC. One per line, supports # comments:
# Cardiovascular
"cardiovascular disease"[MeSH] AND "protein biomarker"
"heart failure"[MeSH] AND "proteomics"
# Oncology
"breast cancer"[MeSH] AND "serum biomarker"
data/queries_biorxiv.txt (37 lines)¶
Simple keyword terms — bioRxiv API does substring matching on title/abstract:
Performance Tips¶
- Use
bedrockorsagemaker-llama3for bulk runs —local(Ollama) is too slow for hundreds of articles. - Always
--skip-node-labelingduring bulk ingestion — saves hours. Run labeling separately on a schedule (see Operations). - PubMed is fastest (abstracts only). PMC and bioRxiv are slower due to full-text chunking.
- Overnight runs through AWS SSM: use
caffeinate -s bash scripts/tunnel_keepalive.shto prevent tunnel drops. - Monitor progress: tail the per-source logs in
logs/parallel_*/.
Post-Ingestion Steps¶
After parallel ingestion completes, run these sequentially:
# 1. Entity consolidation
uv run python -m pipeline.processors.entity_resolver \
--database olink1 --operation full
# 2. Relationship consolidation
uv run python ingest_main.py --consolidate-relationships --database olink1
# 3. Node labeling (if skipped during ingestion)
uv run python ingest_main.py --label-nodes -d olink1
# 4. Vector embeddings
uv run python ingest_main.py --add-graph-embeddings --database olink1 --service bedrock
Typical Timings¶
| Source | Queries | Max/query | ~Duration | ~Articles |
|---|---|---|---|---|
| PubMed | 31 | 500 | 2-4 hours | ~5,000 |
| PMC | 31 | 200 | 4-8 hours | ~2,000 |
| bioRxiv | 15 | 100 | 2-3 hours | ~500 |
| Total (parallel) | — | — | 4-8 hours | ~7,500 |
Wall-clock time equals the slowest source (they run simultaneously).
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
| All sources fail immediately | Neo4j not running | Start Neo4j: docker compose --profile db up -d |
| bioRxiv returns 0 results | Keywords too long | Use 2-3 word terms in bioRxiv queries file |
| Process killed overnight | SSH/SSM tunnel dropped | Use caffeinate -s + tunnel_keepalive.sh |
| Neo4j OOM | Too many concurrent writes | Reduce --pubmed-max or skip one source |
Related Pages¶
- Ingestion Pipeline — pipeline stages and architecture
- Incremental Updates — weekly maintenance (not bulk)
- Operations — node labeling schedules, cache warming