简体中文 · Design · Gallery tools · Safe apply / undo
A fully local, zero-training, pure-vision image-library curation pipeline and an offline review studio. Turn a large image collection into explainable review queues without uploading images or training a custom model.
Quality, identity-similarity and safety proposals use decoded pixels—not filenames, prompts, EXIF, or embedded generation metadata. Paths select dataset roles and locate files; hashes identify content, break ties and select deterministic audit samples. Names remain available for human search, but never become model features.
An approved but not-yet-implemented context-assisted grouping layer (ADR-0005) is the sole narrow exception: only explicitly selected folder/session membership may act as a measured, consent-bound weak prior in its own versioned proposal layer, never as a model input or score, and visual contradiction always wins. The delivered pipeline described here is the pure-vision one above; manual folder organization remains available regardless, and no contextual grouping ships today.
Human decisions stay in charge. Model proposals are not deletion commands, identity verification, or a safety certificate.
Project source: AGPL-3.0-only. The inference stack is not unrestricted for commercial use: pyiqa uses PolyForm Noncommercial, and model weights have separate terms. Read third-party licenses before use.

Read-only images → strict RGB decode → content-addressed manifest + thumbnails
↓
SigLIP references + safety signal + five quality means (incl. HPSv3)
↓
Eligibility gates → corpus-relative ranking → queue construction + abstention
↓
scores.csv + families.json → offline review studio
↓
Human decision journal (JSON/CSV; separate from model proposals)
five-means-v1 profile requires aesthetic v2.5,
TOPIQ-IAA, TOPIQ-NR, Q-ReAlign and HPSv3 means, plus HPS sigma as uncertainty
evidence. Means contribute equally after population z-normalization; zero
variance is guarded. An explicit four-means-v1 profile supports legacy runs
without HPS; absence never selects it automatically. Missing required quality
evidence makes cohort consensus/thresholds unavailable and widens abstention
to review, not a surviving-scorer average. Per-signal reasons are exported in
flags; safety/identity assessment routes retain precedence. These are
within-corpus scores, not universal quality units.The full inference path targets Python 3.12, Windows and an NVIDIA CUDA GPU. CUDA 12.8 wheels were used with an RTX 5060 Ti 16 GB. Linux CPU-only CI verifies the gallery generator, not the GPU pipeline. There is no advertised CPU inference fallback. Keep the checkout writable: output and cache paths must remain inside it.
From a new checkout, in PowerShell:
$env:PYTHONUTF8='1'
$env:UV_CACHE_DIR="$PWD\.uv-cache"
uv venv --python 3.12 .venv
uv pip install --python .venv\Scripts\python.exe torch==2.11.0 torchvision --index-url https://download.pytorch.org/whl/cu128
uv pip install --python .venv\Scripts\python.exe transformers==4.57.6 pyiqa==0.1.15.post2 aesthetic-predictor-v2-5 ImageHash Pillow numpy PyYAML 'pydantic>=2' accelerate
uv pip install --python .venv\Scripts\python.exe --no-deps -e .
Copy-Item config.example.yaml config.yaml
Edit config.yaml before running. Replace all /path/to/... placeholders with
your local input, reference, posted-image and subject-root paths. This file is
gitignored. Keep outputs under out/; the example uses out/library.
The input/reference folder names are arbitrary. Own references must be nonempty.
Optional other-subject references currently use the legacy discovery glob
*参考图集* under sibling subject directories; without them, confusion margins are
empty. This convention selects a dataset role, not an image score.
Q-ReAlign uses a separate environment because its newer Transformers requirement must not change the aesthetic scorer's main environment:
uv venv --python 3.12 .venv-qrealign
uv pip install --python .venv-qrealign\Scripts\python.exe torch==2.11.0 torchvision --index-url https://download.pytorch.org/whl/cu128
uv pip install --python .venv-qrealign\Scripts\python.exe pyiqa==0.1.16 transformers==5.17.0 'pydantic>=2' ImageHash
uv pip install --python .venv-qrealign\Scripts\python.exe --no-deps -e .
The first scoring pass downloads upstream weights over the network; images are
not uploaded. Models include SigLIP, aesthetic v2.5, TOPIQ-IAA/NR,
Falconsai/nsfw_image_detection and q-future/Q-ReAlign-Mini-0.8B. Q-ReAlign is
pinned to revision fe1f45a7574c9e9d908875af9f7e90cb946aa19f.
Hugging Face revisions are recorded on first resolution and weights/preprocessing
fingerprints key prediction caches. Shared weights live under
out/library/cache/{huggingface,torch}; per-run predictions stay in that run's cache.
.venv\Scripts\python.exe -m artcurator.cli run-all --config config.yaml --out out/smoke --limit 12
.venv\Scripts\python.exe -m artcurator.cli run-all --config config.yaml --out out/library
.venv\Scripts\python.exe -m artcurator.cli previews --out out/library
.venv\Scripts\python.exe tools/build_gallery.py --out out/library
Once every required model/revision is cached, use HF_HUB_OFFLINE=1 and
TRANSFORMERS_OFFLINE=1 for disconnected inference. A missing cache is an error,
not a reason to send images to a service. The generated studio needs no network.
| Command | Purpose |
|---|---|
scan | Inventory/decode/hash PNG, JPG, JPEG and WebP; manifest and thumbnails |
score | Pixel-only embeddings, reference signals, quality/safety scores and gaming audit |
cluster | Relative consensus, duplicate families, flags and proposed tiers |
report | Export frozen-column scores.csv, summary and provenance |
run-all | Run scan → score → cluster → report (not previews or gallery) |
previews | Read saved manifest; produce metadata-stripped, ≤1024px JPEG review assets |
Common options: --input, --out, --config, --limit. Scan/run-all inspect the
whole inventory before choosing SHA-sorted limited rows; other stages use the saved
manifest. score --pass accepts siglip, aes_v25, topiq_iaa, topiq_nr,
qrealign, hpsv3, nsfw_prob. HPS sigma is uncertainty evidence, not a sixth scorer.
Resume the same scoring command after interruption; do not rerun scan, which starts a fresh manifest. Then rerun cluster and report:
.venv\Scripts\python.exe -m artcurator.cli score --out out/library --pass qrealign
.venv\Scripts\python.exe -m artcurator.cli cluster --out out/library
.venv\Scripts\python.exe -m artcurator.cli report --out out/library
Outputs include SQLite manifest, float16 embeddings, CSV scores, families, previews, thumbnails, logs and caches. All are private local outputs, not repository assets.
The primary workspace has a big preview, score inspector, six-action belt and
neighbor filmstrip. UI labels are currently Chinese. Human decisions are stored
in browser localStorage under a corpus fingerprint, separately from proposed_tier.
The action journal exports JSON/CSV; export regularly because browser storage is
not a backup. It does not directly execute filesystem moves.
| Key | Action |
|---|---|
← / →, J / K | Navigate |
1–6 | Select, approve queue, archive, confirm safety route, question identity, skip |
U | Undo current image's manual action |
Space / F / ? | Fit/100% zoom, fullscreen, shortcut help |
The secondary virtualized table keeps all metrics, sorting, filtering, family
details and a metric legend. A short-key columnar payload is gzip/base64 embedded;
native DecompressionStream("gzip") decodes it. No framework, CDN or cloud API.
Use current Chrome/Edge; unsupported browsers show a blocking compatibility message.

Try the committed 60-row synthetic fixture, with no model downloads or images:
python tools/build_demo.py
python -m http.server 8765 --bind 127.0.0.1 --directory tests/fixtures/gallery
Open http://127.0.0.1:8765/gallery.html. Serve only the fixture directory, not the
repository/corpus. Real galleries may also open directly as local files; browser
policy can block original-file links when served over HTTP.
artcurator.apply creates a plan only.
Explicit execution requires the stored plan, unchanged CSV digest and a confirmation token.See apply/undo contracts and recovery limits. Never run competing apply operations on the same corpus from different output directories.
These are historical measurements, not new benchmarks for every platform. The scan comparison was one sequential pair with OS-cache confounders; private receipts and corpus paths are intentionally excluded. See methodology and limits.
sha16 is only a display/index hint. Legacy CSVs have
unavailable full identity until derived from source bytes; legacy short-key caches
and embedding alignment files are not silently reused.out/library.See CONTRIBUTING.md for the lightweight test command. Source code
is licensed under GNU AGPL v3 (SPDX AGPL-3.0-only), without warranty.
Copyright © 2026 XucroYuri. Dependencies, weights and any images you process retain
their own rights; see THIRD_PARTY_LICENSES.md.
简体中文 · Design · Gallery tools · Safe apply / undo
A fully local, zero-training, pure-vision image-library curation pipeline and an offline review studio. Turn a large image collection into explainable review queues without uploading images or training a custom model.
Quality, identity-similarity and safety proposals use decoded pixels—not filenames, prompts, EXIF, or embedded generation metadata. Paths select dataset roles and locate files; hashes identify content, break ties and select deterministic audit samples. Names remain available for human search, but never become model features.
An approved but not-yet-implemented context-assisted grouping layer (ADR-0005) is the sole narrow exception: only explicitly selected folder/session membership may act as a measured, consent-bound weak prior in its own versioned proposal layer, never as a model input or score, and visual contradiction always wins. The delivered pipeline described here is the pure-vision one above; manual folder organization remains available regardless, and no contextual grouping ships today.
Human decisions stay in charge. Model proposals are not deletion commands, identity verification, or a safety certificate.
Project source: AGPL-3.0-only. The inference stack is not unrestricted for commercial use: pyiqa uses PolyForm Noncommercial, and model weights have separate terms. Read third-party licenses before use.

Read-only images → strict RGB decode → content-addressed manifest + thumbnails
↓
SigLIP references + safety signal + five quality means (incl. HPSv3)
↓
Eligibility gates → corpus-relative ranking → queue construction + abstention
↓
scores.csv + families.json → offline review studio
↓
Human decision journal (JSON/CSV; separate from model proposals)
five-means-v1 profile requires aesthetic v2.5,
TOPIQ-IAA, TOPIQ-NR, Q-ReAlign and HPSv3 means, plus HPS sigma as uncertainty
evidence. Means contribute equally after population z-normalization; zero
variance is guarded. An explicit four-means-v1 profile supports legacy runs
without HPS; absence never selects it automatically. Missing required quality
evidence makes cohort consensus/thresholds unavailable and widens abstention
to review, not a surviving-scorer average. Per-signal reasons are exported in
flags; safety/identity assessment routes retain precedence. These are
within-corpus scores, not universal quality units.The full inference path targets Python 3.12, Windows and an NVIDIA CUDA GPU. CUDA 12.8 wheels were used with an RTX 5060 Ti 16 GB. Linux CPU-only CI verifies the gallery generator, not the GPU pipeline. There is no advertised CPU inference fallback. Keep the checkout writable: output and cache paths must remain inside it.
From a new checkout, in PowerShell:
$env:PYTHONUTF8='1'
$env:UV_CACHE_DIR="$PWD\.uv-cache"
uv venv --python 3.12 .venv
uv pip install --python .venv\Scripts\python.exe torch==2.11.0 torchvision --index-url https://download.pytorch.org/whl/cu128
uv pip install --python .venv\Scripts\python.exe transformers==4.57.6 pyiqa==0.1.15.post2 aesthetic-predictor-v2-5 ImageHash Pillow numpy PyYAML 'pydantic>=2' accelerate
uv pip install --python .venv\Scripts\python.exe --no-deps -e .
Copy-Item config.example.yaml config.yaml
Edit config.yaml before running. Replace all /path/to/... placeholders with
your local input, reference, posted-image and subject-root paths. This file is
gitignored. Keep outputs under out/; the example uses out/library.
The input/reference folder names are arbitrary. Own references must be nonempty.
Optional other-subject references currently use the legacy discovery glob
*参考图集* under sibling subject directories; without them, confusion margins are
empty. This convention selects a dataset role, not an image score.
Q-ReAlign uses a separate environment because its newer Transformers requirement must not change the aesthetic scorer's main environment:
uv venv --python 3.12 .venv-qrealign
uv pip install --python .venv-qrealign\Scripts\python.exe torch==2.11.0 torchvision --index-url https://download.pytorch.org/whl/cu128
uv pip install --python .venv-qrealign\Scripts\python.exe pyiqa==0.1.16 transformers==5.17.0 'pydantic>=2' ImageHash
uv pip install --python .venv-qrealign\Scripts\python.exe --no-deps -e .
The first scoring pass downloads upstream weights over the network; images are
not uploaded. Models include SigLIP, aesthetic v2.5, TOPIQ-IAA/NR,
Falconsai/nsfw_image_detection and q-future/Q-ReAlign-Mini-0.8B. Q-ReAlign is
pinned to revision fe1f45a7574c9e9d908875af9f7e90cb946aa19f.
Hugging Face revisions are recorded on first resolution and weights/preprocessing
fingerprints key prediction caches. Shared weights live under
out/library/cache/{huggingface,torch}; per-run predictions stay in that run's cache.
.venv\Scripts\python.exe -m artcurator.cli run-all --config config.yaml --out out/smoke --limit 12
.venv\Scripts\python.exe -m artcurator.cli run-all --config config.yaml --out out/library
.venv\Scripts\python.exe -m artcurator.cli previews --out out/library
.venv\Scripts\python.exe tools/build_gallery.py --out out/library
Once every required model/revision is cached, use HF_HUB_OFFLINE=1 and
TRANSFORMERS_OFFLINE=1 for disconnected inference. A missing cache is an error,
not a reason to send images to a service. The generated studio needs no network.
| Command | Purpose |
|---|---|
scan | Inventory/decode/hash PNG, JPG, JPEG and WebP; manifest and thumbnails |
score | Pixel-only embeddings, reference signals, quality/safety scores and gaming audit |
cluster | Relative consensus, duplicate families, flags and proposed tiers |
report | Export frozen-column scores.csv, summary and provenance |
run-all | Run scan → score → cluster → report (not previews or gallery) |
previews | Read saved manifest; produce metadata-stripped, ≤1024px JPEG review assets |
Common options: --input, --out, --config, --limit. Scan/run-all inspect the
whole inventory before choosing SHA-sorted limited rows; other stages use the saved
manifest. score --pass accepts siglip, aes_v25, topiq_iaa, topiq_nr,
qrealign, hpsv3, nsfw_prob. HPS sigma is uncertainty evidence, not a sixth scorer.
Resume the same scoring command after interruption; do not rerun scan, which starts a fresh manifest. Then rerun cluster and report:
.venv\Scripts\python.exe -m artcurator.cli score --out out/library --pass qrealign
.venv\Scripts\python.exe -m artcurator.cli cluster --out out/library
.venv\Scripts\python.exe -m artcurator.cli report --out out/library
Outputs include SQLite manifest, float16 embeddings, CSV scores, families, previews, thumbnails, logs and caches. All are private local outputs, not repository assets.
The primary workspace has a big preview, score inspector, six-action belt and
neighbor filmstrip. UI labels are currently Chinese. Human decisions are stored
in browser localStorage under a corpus fingerprint, separately from proposed_tier.
The action journal exports JSON/CSV; export regularly because browser storage is
not a backup. It does not directly execute filesystem moves.
| Key | Action |
|---|---|
← / →, J / K | Navigate |
1–6 | Select, approve queue, archive, confirm safety route, question identity, skip |
U | Undo current image's manual action |
Space / F / ? | Fit/100% zoom, fullscreen, shortcut help |
The secondary virtualized table keeps all metrics, sorting, filtering, family
details and a metric legend. A short-key columnar payload is gzip/base64 embedded;
native DecompressionStream("gzip") decodes it. No framework, CDN or cloud API.
Use current Chrome/Edge; unsupported browsers show a blocking compatibility message.

Try the committed 60-row synthetic fixture, with no model downloads or images:
python tools/build_demo.py
python -m http.server 8765 --bind 127.0.0.1 --directory tests/fixtures/gallery
Open http://127.0.0.1:8765/gallery.html. Serve only the fixture directory, not the
repository/corpus. Real galleries may also open directly as local files; browser
policy can block original-file links when served over HTTP.
artcurator.apply creates a plan only.
Explicit execution requires the stored plan, unchanged CSV digest and a confirmation token.See apply/undo contracts and recovery limits. Never run competing apply operations on the same corpus from different output directories.
These are historical measurements, not new benchmarks for every platform. The scan comparison was one sequential pair with OS-cache confounders; private receipts and corpus paths are intentionally excluded. See methodology and limits.
sha16 is only a display/index hint. Legacy CSVs have
unavailable full identity until derived from source bytes; legacy short-key caches
and embedding alignment files are not silently reused.out/library.See CONTRIBUTING.md for the lightweight test command. Source code
is licensed under GNU AGPL v3 (SPDX AGPL-3.0-only), without warranty.
Copyright © 2026 XucroYuri. Dependencies, weights and any images you process retain
their own rights; see THIRD_PARTY_LICENSES.md.