PubMiner is a literature mining workspace for PubMed and PMC.
It combines:
- a
Next.jsfrontend for search, article review, task monitoring, and result preview - a
FastAPIbackend for PubMed retrieval, PMC full-text download, LLM extraction, and CSV export
The current workflow is:
- Search PubMed or paste PMIDs
- Load the first page of article metadata while the full PMID set is saved as a backend search session
- Review article metadata, charts, and automatic current-page OA PDF checks
- Select loaded articles or target the full matched search session
- Run chunked extraction tasks with persistent task tracking
- Preview and download CSV outputs for completed or partial runs
- Framework:
Next.js 16,React 19,TypeScript - Styling:
Tailwind CSS,shadcn/ui - State:
Zustand - Charts:
ECharts
Main frontend areas:
src/components/pubminer/search-section.tsxSearch input and query buildersrc/components/pubminer/search-results-section.tsxSearch result list, filters, charts, pagination, article selectionsrc/components/pubminer/extraction-setup-section.tsxLLM extraction options and custom fieldssrc/components/pubminer/tasks-section.tsxTask queue and task detail diagnosticssrc/components/pubminer/results-section.tsxResult preview, column controls, article mapping, and CSV download
- Framework:
FastAPI - Data source:
NCBI Entrezfor PubMed and citation links - Full text:
PMC BioC API - LLM extraction:
Zhipu GLM - Export:
pandasCSV export
Main backend areas:
PubMiner/api_server.pyAPI entry point and task orchestrationPubMiner/pubminer/fetcher/PubMed search and metadata parsingPubMiner/pubminer/downloader/PMC full-text download, OA PDF resolution, parsing, fallback logic, and cachePubMiner/pubminer/extractor/LLM extraction client and schema generationPubMiner/pubminer/exporter/CSV column mapping, ordering, and export logic
- PubMed query builder
- direct PMID list import
- session-backed incremental loading for search results
- first-page metadata loading for large queries
- current-page automatic OA PDF checking
- manual current-page OA refresh and batch OA PDF download
- metadata review before extraction
- article filtering and selection
- PubMed-style result statistics, including year distribution
- search and extraction are separated into distinct steps
- extraction can target either selected loaded articles or the full matched backend search session
- built-in extraction schema for common literature fields
- custom extraction field support
- optional citation fetching
- PMC full-text retrieval with structured section parsing
- fallback full-text assembly when section parsing is weak
- article-level extraction status tracking
- extraction cache keyed by PMID, schema, model, and text hash
- chunk-based processing for large runs
- persistent SQLite-backed task queue and task detail panel
- full-text download report
- fallback usage report
- cache hit reporting
- citation status reporting
- article mapping from search result to final output row
- chunk progress reporting and retry actions for failed chunks or failed articles
- preview extracted CSV data in the UI
- switch between
Metadata,LLM, andFullpreview modes - grouped visible-column controls
- result preview and CSV download for both
completedandpartialtasks - multiple CSV download modes:
- metadata only
- LLM fields only
- full table
The backend uses the following retrieval flow:
Entrez.esearchFind PMIDs from a PubMed query and persist them as a backend search session- paged
Entrez.efetchFetch PubMed XML metadata only for the currently loaded slice - optional
Entrez.elinkFetch citation and reference links when enabled PMC BioC APIDownload full text for records with a PMCID- OA PDF resolver Resolve legal OA PDF candidates with PMC-first logic plus optional DOI fallbacks
- section parser + fallback Build usable extraction text from PMC content
ZhipuExtractorExtract structured fields with a schema-driven promptCSVExporterMerge metadata and LLM results into ordered CSV output
This project has already been improved beyond the initial scaffold. Notable changes include:
- search preview and LLM extraction split into separate UX stages
- search sessions added so large query sets no longer require full metadata hydration before first render
- dynamic custom extraction fields wired end-to-end
- result preview in the frontend
- article-level mapping between search results and extraction outputs
- PMC full-text caching in
download/pmc_cache - citation fetching enabled only when requested
- citation fetching parallelized with the main extraction flow
- enhanced section parsing with fallback logic
- PubMed metadata retry and split-batch fallback for incomplete reads
- OA PDF resolution narrowed to current-page automatic checks for large result sets
- extraction scope can now use the full matched backend search session
- task and search-session state persisted locally in SQLite
- CSV export modes and stable output naming
- richer bibliographic metadata surfaced before extraction
.
├─ src/ Frontend application
│ ├─ app/
│ ├─ components/
│ │ ├─ pubminer/
│ │ └─ ui/
│ └─ lib/
├─ PubMiner/ Python backend
│ ├─ api_server.py
│ ├─ config/
│ └─ pubminer/
├─ docs/ Notes and example inputs
├─ download/ Downloaded and cached PMC/OA PDF content
├─ output/ Exported CSV files and checkpoints
├─ db/ Local data and support files
└─ README.md
Use the root directories with the following intent:
- Source code
src/for the Next.js frontendPubMiner/for the FastAPI backend and Python packageprisma/for database schema and Prisma metadatapublic/for frontend static assets
- Documentation and examples
docs/for example inputs, notes, and future project docs- Runtime artifacts
download/for PMC BioC cache and OA PDF cacheoutput/for exported CSV files and checkpointsdb/for local SQLite files, including persisted task and search-session state
- Local machine only
.venv/,.env,.tmp/, and local log files are environment-specific and should not be treated as source files
When adding new files, prefer:
docs/for sample inputs, notes, or operational docssrc/orPubMiner/for code that is part of the productdownload/,output/, ordb/only for generated runtime data
Install dependencies from the project root:
pnpm installStart the frontend:
pnpm devBy default the frontend runs on:
Create and activate a Python environment, then install backend dependencies.
Example:
cd PubMiner
pip install -r requirements.txtStart the API server:
python api_server.pyBy default the backend runs on:
If you start the backend this way, set NEXT_PUBLIC_API_URL=http://localhost:8000 in /.env before starting the Next.js frontend.
From the project root you can also use:
.\start_backend.ps1This script always uses .venv\Scripts\python.exe, starts api_server.py from the correct backend directory, and warns if port 8000 is already occupied.
Recommended convention:
- use .env.example as the template
- copy it to /.env on your machine
- keep real secrets only in
.env - do not commit
.env
Current lookup behavior:
- the backend supports both root and backend-local env files for backward compatibility
- the effective priority is now:
- root
.env PubMiner/.env- root
.env.local PubMiner/.env.local
- root
Practical guidance:
- prefer putting
NCBI_EMAIL,NCBI_API_KEY,ZHIPU_API_KEY,UNPAYWALL_EMAIL, andNEXT_PUBLIC_API_URLin the root /.env - if both
.envand.env.localexist,.envshould now win - the repository only ships the root /.env.example template now
The backend package now also supports direct CLI usage.
Run commands from PubMiner:
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main --helpAvailable subcommands:
searchSearch PubMed, persist a local search session, and preview the first loaded pageoa-checkResolve legal OA PDF availability for PMIDs, a PMID file, or a saved search sessionoa-downloadDownload legal OA PDFs with the same PMC-first strategy used by the web appextractRun extraction from PMIDs or a saved search session using the same persisted task/chunk flow as the web apptasksInspect persisted extraction tasks or saved search sessions in local SQLitepipelineRun the older all-in-one CLI pipeline for backward compatibility
Common examples:
# Create a saved search session
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main search -q "aging[tiab]" --max-results 20 --load-size 5
# Check OA PDF availability for a few PMIDs
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main oa-check --pmids 31452104 41876404 --limit 2
# Download OA PDFs and write a manifest
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main oa-download --session-id <search_session_id> --limit 10 --manifest-out ..\\output\\oa_manifest.json --zip-output ..\\output\\oa_pdfs.zip
# Run extraction against a saved search session
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main extract --session-id <search_session_id>
# Inspect local tasks and sessions
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main tasks --view tasks --limit 10
D:\Study\Project\PubMiner2\.venv\Scripts\python.exe -m pubminer.cli.main tasks --view sessions --limit 10Notes:
- CLI and web extraction now share the same persisted task format in db/pubminer_tasks.db
extractcreates the sametask_id,article_report,chunk_report, andresult_filerecords that the task panel reads in the web appoa-checkandoa-downloadcan use--query,--file,--session-id, or inline--pmids
Backend configuration lives in:
PubMiner/config/default.yaml
Important sections:
ncbizhipusearchdownloadextractionoutputcheckpointoa_pdfdatabase
Example PMIDs for quick manual testing live in:
docs/examples/test_pmids.txt
OA PDF benchmark for the fixed 10-article sample:
.\.venv\Scripts\python.exe .\scripts\benchmark_oa_pdf.pyOptional variants:
.\.venv\Scripts\python.exe .\scripts\benchmark_oa_pdf.py --method pmc
.\.venv\Scripts\python.exe .\scripts\benchmark_oa_pdf.py --method europepmc-ptpmcrender
.\.venv\Scripts\python.exe .\scripts\benchmark_oa_pdf.py --method europepmc-pdf-render
.\.venv\Scripts\python.exe .\scripts\benchmark_oa_pdf.py --concurrency 5 --timeout 60The current PubMiner/config/default.yaml still contains plain-text API keys.
That is not a safe long-term setup.
Recommended next step:
- move NCBI and Zhipu keys to environment variables
- load them in the backend at startup
- remove secrets from tracked config files
Current export behavior:
- citation-related columns are omitted when citation fetching is disabled
- bibliographic metadata is ordered before LLM extraction fields
- output file names follow a stable pattern such as:
pubminer_extract_20260313_153000_10articles.csv
pubminer_extract_20260313_153000_10articles_citations.csv
pubminer_extract_20260313_153000_10articles_2custom.csv
- very large searches still require manual
Load next ...pagination after the first page - automatic OA PDF checks are intentionally limited to the current visible page for responsiveness
- some PMC articles still require fallback full-text assembly
- repository-wide lint and type-check noise still exists in unrelated legacy or example areas
- the current full-project TypeScript check is still blocked by the existing
src/lib/db.tsPrisma issue - secret management still needs cleanup
If you continue productizing this project, the most natural next steps are:
- move secrets to environment variables
- add optional background jobs for all-session OA PDF resolution
- virtualize or further aggregate very large loaded result lists in the frontend
- improve result table filtering and search
- add automated backend and frontend regression tests