Skip to main content

Argus Quarry

PyPI Python License: MIT CI

Provenance-first acquisition of public-domain / CC0 images — the input stage of the Argus suite. The quarry digs up raw material: it downloads images from upstream archives and lands them, with full provenance and licensing, into a folder the rest of the suite already consumes (DATASET_DIR/data/images).

Subjects are grouped into LoRA-training categoriesidentity (people), wardrobe (garments), setting (scenes/environments) and concept (styles/themes) — and everything lands sorted into <category>/<subject>/ subfolders. A category is independent of identity: a subject can be Mark Twain, a red dress, a modern kitchen, or cyberpunk.

It is deliberately lean — acquisition + provenance, nothing more. Quality scoring, near-duplicate detection, faces, embeddings and captioning are owned downstream by argus-curator and argus-lens; quarry never re-implements them.

Want a UI? Quarry is CLI-only by design (see DESIGN.md §9). The suite's web frontend — argus-studio — surfaces the curation and captioning stages that consume quarry's output (e.g. its /curate view scans the <category>/<subject>/ tree quarry publishes).

argus-quarry (NEW)          argus-curator (:8101)        argus-lens (:8100)        argus-studio
─ download  ─┐              ─ scan + score  ─┐           ─ caption ─┐              ─ web UI (:3000)
─ verify    ─┤   images +   ─ near-dup      ─┤  manifest ─ buckets ─┤   dataset    ─ /curate
─ provenance┤   provenance  ─ face-cluster  ─┤           ─ (ident/ ─┤   → LoRA     ─ caption
─ SHA256    ─┴───────────►  ─ select+export ─┴──────────►  wardrobe)─┘
   /data/images (DATASET_DIR) ─────────────────────────────────────────────────►

See DESIGN.md for the full rationale and phased plan.

Why it exists

  • Provenance-first. Every image carries its source URL, landing page, licence and attribution. A record with no accepted licence (PD / CC0) is quarantined, never landed.
  • Idempotent. Exact-dedup by SHA256 (UNIQUE in the DB) and a status lifecycle mean reruns resume partials and never duplicate bytes.
  • Bounded. A per-file resolution/size cap and a total-archive GB budget keep the pool predictable; the full-resolution URL is always retained for later re-fetch.
  • Source-independent. Every downloader yields the same SourceRecord, so the pipeline never learns which archive a file came from.
  • Category-sorted. Subjects carry a category (identity / wardrobe / setting / concept) and land under <category>/<subject>/, so one pool serves every LoRA workflow.

Install

pip install argus-quarry            # library + downloaders
pip install "argus-quarry[cli]"     # + the argus-quarry command
pip install "argus-quarry[phash]"   # + opportunistic perceptual-hash metadata
pip install "argus-quarry[server]"  # + the read-only provenance HTTP API (serve)

For development the suite uses uv (works on PEP 668 "externally managed" system Pythons):

make dev                            # uv venv + editable install (dev + cli extras)
# or, manually:
uv venv && uv pip install -e ".[dev,cli]"

Quickstart

# Inspect the curated subject seeds (all categories, or one)
argus-quarry subjects
argus-quarry subjects --category wardrobe

# Fetch from Wikimedia Commons into the raw pool, then publish a curator-ready,
# CC0/PD-only tree into $DATASET_DIR (symlinks by default). Omit --category to
# harvest every category (identity + wardrobe + setting + concept).
argus-quarry run --source commons --limit 20 --export --licence CC0,PD
argus-quarry run --category concept --limit 20 --export   # just one category

# Or split the two stages
argus-quarry fetch --source commons --limit 20
argus-quarry export --dest ./data --licence CC0,PD   # add --copy to avoid symlinks

# Inspect what you have
argus-quarry stats
argus-quarry list --category setting --licence CC0
argus-quarry verify              # re-check files decode + match recorded SHA256

Installed into a uv venv? Prefix commands with uv run (e.g. uv run argus-quarry stats) or source .venv/bin/activate first.

CLI

Command What it does
run Fetch into the raw pool, then (optionally) publish — the compose entrypoint
fetch Download candidates into the raw pool (no publish)
export Publish a filtered <category>/<subject>/ tree into DATASET_DIR (symlink / --copy)
list List landed photographs with provenance (filter by source / licence / category / subject)
stats Counts by status / category / source / licence + raw-pool size
verify Re-check landed files exist, decode, and match their recorded SHA256
subjects Show the subject seed(s) downloaders harvest around (filter by --category)
serve Start the read-only provenance HTTP API on :8102 (needs the server extra)

run, fetch, export and list all accept --category (identity / wardrobe / setting / concept); with none given they span every category.

Layout produced

Quarry fetches into a raw pool it fully owns ($QUARRY_HOME, a sibling side-car dir), then export publishes a clean tree into DATASET_DIR:

$QUARRY_HOME/                          # side-car state — NEVER scanned by curator
├── images/
│   ├── identity/Albert_Einstein/…      # the raw pool, sorted by <category>/<subject>/
│   ├── wardrobe/Red_dress/…
│   ├── setting/Modern_kitchen/…
│   └── concept/Cyberpunk/…
├── metadata/portraits.sqlite          # provenance DB (subjects + photographs)
├── cache/  logs/

$DATASET_DIR/                          # published, curator-ready view (via export)
├── identity/Albert_Einstein/…          # symlinks (default) or copies into the pool
└── wardrobe/Red_dress/…

Provenance model

A single SQLite database (portraits.sqlite, WAL mode) with two tables:

  • subjectsname · category · wikidata_id · birth_year · death_year · occupation (the identity-only columns stay NULL for wardrobe / setting / concept subjects)
  • photographscategory · title · photographer · year · source · source_url · licence · attribution · width · height · file_size · filename · **sha256 (UNIQUE)** · phash · remote_url · status · downloaded_at

sha256 is the exact-dedup key (idempotent reruns); status (pending → downloading → complete, plus duplicate / quarantined / failed) tracks resumability. phash is recorded opportunistically and is informational only — it never drives dedup here (that's argus-curator's job).

Configuration

Copy .env.example to .env. Key knobs:

Env Default Meaning
QUARRY_HOME ./quarry Raw pool + DB + cache + logs (side-car dir)
QUARRY_MAX_GB 40 Total raw-pool ceiling; 0 = unlimited
COMMONS_USER_AGENT descriptive default Polite UA (Commons/LoC expect one)
DATASET_DIR ./data Published view export writes into

HTTP server

A tiny read-only provenance API (FastAPI) over the raw pool — no mutation endpoints, ever. It powers the argus-studio /gallery view, the same way /curate talks to argus-curator on :8101.

pip install "argus-quarry[server]"          # fastapi + uvicorn
argus-quarry serve --host 0.0.0.0 --port 8102 --cors

The published image ships the server extra and serves by default on :8102:

docker run --rm -p 8102:8102 -v "$PWD/quarry:/data/quarry" \
  -e QUARRY_HOME=/data/quarry ghcr.io/smk762/argus-quarry:latest

The entrypoint is still argus-quarry, so any acquisition subcommand works by overriding the command (docker run ... ghcr.io/smk762/argus-quarry fetch …).

The pool root comes from $QUARRY_HOME (default ./quarry), exactly like every other command — the compose service just sets QUARRY_HOME=/data/quarry.

Endpoint Returns
GET /health {status, service, version, quarry_home}
GET /stats Counts by status / category / source / licence + total_bytes (mirrors stats)
GET /subjects?category= Distinct subjects with landed photo counts: {subjects: [{folder, category, photo_count}]}
GET /photos?category=&subject=&licence=&source=&status=&limit=&offset= Paginated provenance rows: {total, offset, limit, photos: […]}; status defaults to complete (pass empty for all), licence accepts CSV (CC0,PD), limit ≤ 500
GET /photos/{id} One photograph with full provenance (404 if unknown)
GET /thumb?id=&size=384 WEBP thumbnail rendered from the pooled file (size = longest edge, capped at 1024)

Suite integration

Quarry ships a gallery profile in the suite's argus-studio compose.yaml. It's a run-to-completion job: fetch into the pool, publish into DATASET_DIR, then let curator/lens (and the web UI's /curate view) consume the result.

docker compose --profile gallery up --build   # fetch → pool → publish DATASET_DIR
docker compose --profile curator up --build    # then curate the published images

The published tree symlinks back into QUARRY_HOME/images. For those links to resolve inside the curator/lens containers, mount QUARRY_HOME read-only there too, or run export --copy.

Sources

Source Status
Wikimedia Commons Phase 1 (implemented)
Library of Congress, Smithsonian, Rijksmuseum, LAC (Karsh allow-list) Phase 2
Europeana, Flickr Commons (strict per-record rights) Phase 3

New sources register in downloaders/ behind a common Downloader contract, so adding one never touches ingest, storage, or export.

Development

make lint     # ruff
make test     # pytest
make check    # lint + test + build

Related projects

  • argus-studio — the suite's Next.js web UI (captioning + /curate).
  • argus-curator — training-suitability scoring, near-dup dedup, face clustering.
  • argus-lens — intent-aware, multi-model captioning.

Licence

MIT — see LICENSE. Note: the MIT licence covers this software, not the images it downloads. Image licences are recorded per-record and enforced at ingest.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

argus_quarry-0.2.1.tar.gz (48.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

argus_quarry-0.2.1-py3-none-any.whl (39.1 kB view details)

Uploaded Python 3

File details

Details for the file argus_quarry-0.2.1.tar.gz.

File metadata

  • Download URL: argus_quarry-0.2.1.tar.gz
  • Upload date:
  • Size: 48.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for argus_quarry-0.2.1.tar.gz
Algorithm Hash digest
SHA256 e5afe08e346a882a226df06bf4671ca0441d046d336f9575ec1feda2b4bd9f08
MD5 641650eec3b6481eb692ccc5f046e138
BLAKE2b-256 c63a17db3f94cecda9a5677978f17f3c90eab9fa6cc36de2b7945ecaa0ccf50d

See more details on using hashes here.

Provenance

The following attestation bundles were made for argus_quarry-0.2.1.tar.gz:

Publisher: release.yml on smk762/argus-quarry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file argus_quarry-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: argus_quarry-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 39.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for argus_quarry-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9a76a78d26c7dbe2168eda1e5890b2c2070c940e9cc3ee707a4860620db007ef
MD5 cab3e8add4169eeb08cead3b32ed8982
BLAKE2b-256 8c8d006c402262a5b687f9aafdfaa86f5169fbcd22a1f3f1cdfd2359b563fac1

See more details on using hashes here.

Provenance

The following attestation bundles were made for argus_quarry-0.2.1-py3-none-any.whl:

Publisher: release.yml on smk762/argus-quarry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.3

2 files

This release

0.2.1 This release

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page