Modern radiocarbon calibration with LLM-powered narrative explanations, Bayesian modelling, and GIS curve selection.
Libby is a full-featured web application for calibrating radiocarbon dates with a modern Svelte 5 frontend, a Python/FastAPI backend, and unique features — including plain-English narrative explanations of calibration results, summed probability distributions, and a lat/lng-based curve selector for IntCal vs SHCal vs mixed curves.
- Single-date calibration — BP age + σ → calibrated PDF chart with 1σ/2σ HPD ranges
- Batch calibration — paste multiple dates at once, view SPD chart and results table
- LLM-powered narratives — plain-English explanation of every calibration result
- Multi-language support — narratives in 12 languages (English, French, German, Spanish, Italian, Portuguese, Japanese, Arabic, Chinese, Dutch, Swedish, Polish)
- Multi-provider LLM support — Nvidia NIM (free tier, 40 req/min), Anthropic Claude
- Bayesian Phase & Sequence modelling — Metropolis-Hastings MCMC with Agreement Index
- GIS curve selector — Leaflet map pin-drop auto-suggests IntCal20/SHCal20/mixed curve
- Project management — group dates by site, context, or research project
- Summed Probability Distribution (SPD) — combined probability across all dates
- Taphonomic warnings — material-aware notes (old-wood effect, collagen preservation, marine reservoir effect, etc.)
- Export: formatted PDF report, CSV, OxCal CQL2 script, publication-ready text, publication-quality figures (PNG/SVG)
- Calibration curves: IntCal20, SHCal20, Marine20 (CC BY 4.0)
- GIS map — OpenStreetMap with zone overlays (journal-safe, no Google Maps)
| Layer | Technology |
|---|---|
| Backend | Python 3.13+ / FastAPI |
| Frontend | Svelte 5 / SvelteKit / Chart.js / Leaflet |
| Calibration engine | iosacal + direct IntCal curve data |
| Bayesian MCMC | Pure numpy/scipy Metropolis-Hastings |
| LLM | Nvidia NIM (OpenAI-compatible) or Anthropic Claude |
| Database | SQLite (aiosqlite) |
| ReportLab | |
| Charts | Chart.js (frontend), matplotlib (PDF reports) |
pip install libby
libbyOpen http://localhost:50001 in your browser.
docker compose up -d
# Open http://localhost:50001Or pull from GitHub Container Registry (once published):
docker pull ghcr.io/mabo-du/libby:latest
docker run -p 50001:50001 ghcr.io/mabo-du/libby:latestTo publish the Docker image yourself:
docker build -t libby .
docker tag libby:latest ghcr.io/mabo-du/libby:latest
docker push ghcr.io/mabo-du/libby:latestgit clone https://github.com/mabo-du/libby.git
cd libby
# Backend + frontend (single server)
uv sync
uv run uvicorn libby.main:app --reload --port 50001
# Open http://localhost:50001
# Frontend dev server (for UI development, requires backend on 50001)
cd frontend
npm install
npm run dev -- --port 50002
# Open http://localhost:50002 (points at backend API on :50001)Libby works without any LLM — a deterministic fallback generates coherent narratives from the numbers alone. For AI-powered narratives, set:
# Nvidia NIM (free — sign up at build.nvidia.com)
echo 'LIBBY_NIM_API_KEY=nvapi-...' > .env
# Or Anthropic Claude
# echo 'LIBBY_LLM_PROVIDER=anthropic' >> .env
# echo 'LIBBY_ANTHROPIC_API_KEY=sk-ant-...' >> .envEnter a BP age and standard deviation, select a curve, click Calibrate. View the probability distribution chart, 1σ/2σ ranges, and plain-English narrative.
Click Batch in the nav, paste dates as CSV-like text, calibrate all at once with Summed Probability Distribution.
On the calibration page, expand Curve selector by site location. Click anywhere on the map to place a pin — Libby suggests the correct curve based on latitude and explains the reasoning.
Create projects to group dates by site. Each project shows:
- All dates with full calibration data
- Summed Probability Distribution chart
- Project summary narrative
- Bayesian modelling (Phase or Sequence)
- PDF report, publication-quality figures, OxCal export, CSV export
With 2+ dates in a project:
- Phase model — estimates start/end boundaries for an activity period
- Sequence model — applies stratigraphic ordering constraints
- Agreement Index (A) per date, following OxCal's convention (A ≥ 60 = acceptable)
Navigate to Import, paste CSV/TSV from your radiocarbon lab. Auto-detects columns, handles "3000±30" embedded sigma format, previews all rows, then batch-calibrates with one click.
libby/
├── src/libby/ # Python backend
│ ├── main.py # FastAPI app factory and routes
│ ├── calibration.py # iosacal integration
│ ├── bayesian.py # MCMC Phase/Sequence models
│ ├── narrative.py # LLM + fallback narrative generation
│ ├── models.py # Pydantic schemas
│ ├── database.py # SQLite (projects, calibrations)
│ ├── gis.py # Curve suggestion by latitude
│ ├── spd.py # Summed Probability Distribution
│ ├── export.py # CSV/text formatters
│ ├── figure.py # Publication-quality figure export
│ ├── oxcal.py # OxCal CQL2 script export
│ ├── report.py # PDF report generation
│ ├── importer.py # Lab report CSV parser
│ └── providers/ # LLM providers (NIM, Anthropic)
├── frontend/src/ # Svelte 5 frontend
│ ├── routes/ # Pages (/, /batch, /import, /projects)
│ └── lib/ # Components (form, chart, map, etc.)
├── tests/ # pytest test suite
├── notebooks/ # Research notebooks
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Docker deployment
└── MANIFEST.in # PyPI package manifest
This tool uses the internationally ratified calibration curves:
- IntCal20 — Northern Hemisphere terrestrial (Reimer et al. 2020)
- SHCal20 — Southern Hemisphere terrestrial (Hogg et al. 2020)
- Marine20 — Global marine (Heaton et al. 2020)
All curves are CC BY 4.0 licensed. Calibration engine: iosacal (GPLv3).
MIT License. See LICENSE for details.
If you use Libby in published research, please cite:
- IntCal20: Reimer et al. 2020, Radiocarbon 62(4)
- SHCal20: Hogg et al. 2020, Radiocarbon 62(4)
- Marine20: Heaton et al. 2020, Radiocarbon 62(4)
