PubMed retrieval and LLM classification pipeline for CAR literature across five topic groups:
CAR-DCCAR-MacCAR-MonoCAR-TCAR-NK
The project retrieves PubMed records, normalizes metadata, merges cross-topic hits, and then uses an LLM-based classification pipeline to assign:
- a single
primary_topic relevance(relevant/peripheral/irrelevant)primary_mechanismsecondary_mechanismdisease_labeldisease_detailconfidencereason
This repository is designed to support a reproducible CAR literature workflow that can:
- Retrieve all matching PubMed research articles without date restriction.
- Preserve core bibliographic metadata and abstract text.
- Classify each paper by mechanism of action.
- Label each paper by primary disease area.
- Export a final CSV for downstream analysis.
Journal impact factor is intentionally out of scope for the current implementation. Journal names are normalized now so external metrics can be joined later.
Using the current query set and retrieval pipeline, the merged filtered corpus contains:
- 10,772 merged research records after de-duplication
- 896 records matched by more than one topic query
- LLM-based
primary_topicassignment to collapse multi-topic matches into one main topic relevancetagging to identify peripheral and clearly irrelevant false-positive matches
scripts/pubmed.py: retrieval CLI entry pointscripts/pubmed_pipeline/: PubMed retrieval, filtering, merge, and output pipelinescripts/classify.py: classification CLI entry pointscripts/classify_pipeline/: LLM client, prompts, validation, cache, and classification pipelineconfig/queries.json: canonical PubMed topic queriesconfig/README.md: notes about query designdocs/retrieval_flow.md: retrieval architecture notesEXECUTION_PLAN.md: end-to-end project execution planCACHE.md: cache behavior notesoutput/: generated runtime artifacts (ignored by Git).env.example: environment variable template
- Python 3
- Network access to PubMed (
eutils.ncbi.nlm.nih.gov) - Optional LLM API access for semantic classification
This repository intentionally uses the Python standard library only.
Create a local .env from .env.example and fill in your own values:
copy .env.example .envExample .env fields:
NCBI_API_KEY="your_ncbi_api_key"
# Optional proxy settings
HTTP_PROXY=http://127.0.0.1:7897/
HTTPS_PROXY=http://127.0.0.1:7897/
# LLM API for classification subagent
LLM_API_BASE=http://localhost:9310/v1
LLM_API_KEY=your_llm_api_key
LLM_MODEL=your_model_nameImportant:
- Do not commit
.env. - Do not commit
output/. - The retrieval and classification pipelines both support resume through on-disk cache files.
Run the full PubMed retrieval pipeline:
python scripts/pubmed.py --output-dir output/full_v3Run a subset of topics:
python scripts/pubmed.py --topic car_t --topic car_nk --output-dir output/subset_runRun a direct one-off query:
python scripts/pubmed.py --query "chimeric antigen receptor macrophage" --output-dir output/direct_query- PubMed
esearchis used to collect PMIDs. - Large result sets are automatically split by publication year to work around the PubMed
esearch9999-record limit. - PubMed
efetchis used in batches to retrieve article metadata. - Record-level filtering excludes clearly non-research publication types using PubMed metadata.
- Missing or short abstracts are flagged for manual review rather than dropped.
- Records are deduplicated by
pmidand merged across matched topics.
The retrieval phase writes into the selected output directory, for example output/full_v3/:
merged_raw_records.jsonmerged_raw_records.csvmerged_filtered_records.jsonmerged_filtered_records.csvmanual_review_records.jsonmanual_review_records.csvtopic_summary.csvretrieval_quality_summary.csvcache/
The classification phase uses merged_filtered_records.json as input.
Run semantic classification on retrieval output:
python scripts/classify.py --input output/full_v3 --output-dir output/classified_v1Run a small smoke test:
python scripts/classify.py --input output/full_v3 --output-dir output/classify_test --limit 10Run with concurrency:
python scripts/classify.py --input output/full_v3 --output-dir output/classified_v1 --workers 4For each record, the LLM is asked to assign:
primary_topicrelevanceprimary_mechanismsecondary_mechanismdisease_labeldisease_detailconfidencereason
The classification layer includes:
- per-PMID cache files for resume
- LLM network retries
- JSON parse retries when the model returns malformed output
- optional multi-worker concurrency via
--workers - rules-based validation and normalization
- review routing for low-confidence, peripheral, irrelevant, missing-abstract, and inconsistent outputs
- automatic cache invalidation when the classification schema changes
Many records match more than one topic query, especially combinations such as:
car_t+car_nkcar_t+car_maccar_t+car_dc
The retrieval layer intentionally preserves all matched topic memberships in matched_topics. The classification layer then assigns a single primary_topic based on the actual experimental focus of the paper.
Examples:
- a CAR-T paper that discusses tumor-associated macrophages still gets
primary_topic=car_t - a CAR-NK engineering paper that also mentions CAR-T comparisons gets
primary_topic=car_nk - a general review that only briefly mentions CAR platforms may be marked
relevance=peripheral - a keyword false positive can be marked
relevance=irrelevant
The classification phase writes into the selected output directory, for example output/classified_v1/:
classified_records.jsonclassified_records.csvmanual_review_records.csvclassification_summary.jsoncache/classifications/
The final CSV includes both retrieval metadata and semantic labels, including:
primary_topicrelevanceprimary_mechanismsecondary_mechanismdisease_labeldisease_detailconfidencereasonneeds_manual_reviewreview_reasons
car_dccar_maccar_monocar_tcar_nk
relevantperipheralirrelevant
cytotoxic_killingphagocytosisimmune_regulationmicroenvironment_remodelingantigen_presentationfibrosis_modulationdrug_delivery_or_platformmanufacturing_or_engineeringsafety_or_toxicitydiagnostic_or_monitoringother
cancerautoimmune_diseaseorgan_fibrosisinfectious_diseasehematologic_disorder_nonmalignanttransplantationinflammatory_diseaseneurologic_diseaseother
Syntax check:
python -m compileall scriptsRecommended end-to-end smoke sequence:
python scripts/pubmed.py --max-records-per-topic 3 --output-dir output/smoke_retrieval
python scripts/classify.py --input output/smoke_retrieval --output-dir output/smoke_classify --limit 5output/contains generated datasets and caches and is intentionally ignored by Git.- PubMed metadata and abstract redistribution policies may differ from code licensing and should be reviewed before public redistribution of generated output files.
- This repository is intended to open-source the pipeline code and configuration, not the generated dataset artifacts.
The repository currently supports:
- full-history PubMed retrieval with resume support
- merged topic-level corpus generation
- LLM-based semantic classification with cache, retry, review routing, and concurrency support
- single-label
primary_topicassignment for multi-topic records relevanceclassification to isolate peripheral and irrelevant matches- CSV/JSON export for downstream analysis
- add a compact sample dataset or fixture set that does not include large generated outputs
- add optional notebook/reporting layer for downstream analysis
- add a post-processing step that separates
relevantrecords fromperipheral/irrelevantrecords for final release tables