Radiocarbon calibration tool with LLM-powered narrative explanations, Bayesian modelling, and GIS curve selection
Project description
Libby
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.
Features
- 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
- Calibration curves: IntCal20, SHCal20, Marine20 (CC BY 4.0)
- GIS map — OpenStreetMap with zone overlays (journal-safe, no Google Maps)
Tech Stack
| 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) |
Quick Start
# Clone
git clone https://github.com/mabo-du/libby.git
cd libby
# Backend
uv sync
uv run uvicorn libby.main:app --reload --port 50001
# Frontend (separate terminal)
cd frontend
npm install
npm run dev -- --port 50002
Open http://localhost:50002 in your browser.
LLM Narratives (Optional)
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-...' >> .env
Usage
Single Calibration
Enter a BP age and standard deviation, select a curve, click Calibrate. View the probability distribution chart, 1σ/2σ ranges, and plain-English narrative.
Batch Calibration
Click Batch in the nav, paste dates as CSV-like text, calibrate all at once with Summed Probability Distribution.
GIS Curve Selector
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.
Projects
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, OxCal export, CSV export
Bayesian Modelling
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)
Lab Report Import
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.
Project Structure
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
│ ├── 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
Calibration Curves
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).
Licence
MIT License. See LICENSE for details.
Citation
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)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file libby-0.1.0.tar.gz.
File metadata
- Download URL: libby-0.1.0.tar.gz
- Upload date:
- Size: 498.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df06678eef0acbd96e35aeb1a6179a7b3f89f5e62546166409380e9ba9ab87d1
|
|
| MD5 |
58c4186e14ada0df2a81f2509a205daf
|
|
| BLAKE2b-256 |
40f1b329dc22a75e864592986dad5b1040452999d8e60259e33375c3282bf129
|
File details
Details for the file libby-0.1.0-py3-none-any.whl.
File metadata
- Download URL: libby-0.1.0-py3-none-any.whl
- Upload date:
- Size: 508.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ac2dd74fa6012e38fa15309fbd6d39827861cd3ffd8b76cc3bf2ab43c1d4d0d
|
|
| MD5 |
283652707c21024c21d3b7ddbcca5f25
|
|
| BLAKE2b-256 |
24d3473d01c9c6921e6bbcdb34534542706a6fa8f84d51ce91af3bd04b0f275c
|