From ddd0506bfe5d308aa63bbfe4afedc571684fe443 Mon Sep 17 00:00:00 2001 From: Refinement Systems Date: Mon, 14 Sep 2026 19:00:39 +0200 Subject: [PATCH] similarity -> distance --- AGENTS.md | 12 ++++---- NOTES.md | 6 ++-- README.md | 16 +++++----- README_DEFERRED.md | 2 +- README_RUNPOD.md | 2 +- pyproject.toml | 4 +-- scripts/bundle.sh | 2 +- scripts/smoke.sh | 16 +++++----- ...lyze_similarity.py => analyze_distance.py} | 22 +++++++------- src/dltb/args.py | 2 +- .../{similarity_loop.py => distance_loop.py} | 30 +++++++++---------- src/dltb/models.py | 4 +-- 12 files changed, 59 insertions(+), 59 deletions(-) rename src/dltb/{analyze_similarity.py => analyze_distance.py} (94%) rename src/dltb/{similarity_loop.py => distance_loop.py} (90%) diff --git a/AGENTS.md b/AGENTS.md index 61e6465..5aebd35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,8 +49,8 @@ scripts/smoke.sh # tiny run of every tool; needs CUD # dltb-klein, both conditionings) scripts/smoke-local.sh # single-frame pass per locally-viable # model (sd-turbo, sdxl-turbo, klein-4b) -uv run dltb-similarity # DreamSim perceptual drift/convergence - # (SMOKE_SIMILARITY=1 adds it to smoke.sh) +uv run dltb-distance # DreamSim perceptual drift/convergence + # (SMOKE_DISTANCE=1 adds it to smoke.sh) uv run python src/dltb/analyze_drift.py # CPU-only drift metrics ``` @@ -65,7 +65,7 @@ There is **no test suite and no linter**. Verification ladder: sd-turbo, after deploying a bundle; `scripts/smoke-local.sh` covers the other locally-viable models. 3. `analyze_drift.py` on produced frames for sanity of results; - `dltb-similarity` for the perceptual counterpart of the same frames (it + `dltb-distance` for the perceptual counterpart of the same frames (it needs torch and downloads DreamSim weights on first use). ## Architecture @@ -82,8 +82,8 @@ in `pyproject.toml`): | `oneshot.py` / `iterate.py` | single pass / free-running self-iteration | | `continuous.py` | video loop: anchored boil test vs stateful blend, reproject, freeze/free/black tails | | `assemble.py` | CPU-only local mp4 assembly from a run's saved frames (split workflow; `dltb-assemble`) | -| `analyze_similarity.py` | DreamSim perceptual drift/convergence over a run's frames (`dltb-similarity`); companion to `analyze_drift.py`, needs torch + first-run weights download | -| `similarity_loop.py` | iterate + measure in one run (`dltb-similarity-loop`): free-running loop with a strength-capable model, then DreamSim on the saved frames -> `similarity_metrics.csv` + `similarity_plot.png`; the pipeline is unloaded and released before DreamSim loads | +| `analyze_distance.py` | DreamSim perceptual drift/convergence over a run's frames (`dltb-distance`); companion to `analyze_drift.py`, needs torch + first-run weights download | +| `distance_loop.py` | iterate + measure in one run (`dltb-distance-loop`): free-running loop with a strength-capable model, then DreamSim on the saved frames -> `distance_metrics.csv` + `distance_plot.png`; the pipeline is unloaded and released before DreamSim loads | | `klein.py` | klein-restricted wrapper; dual-ref conditioning hook; delegates to `continuous.run()` | Key invariants: @@ -95,7 +95,7 @@ Key invariants: error; `--device` overrides) threads an explicit device into `load_pipeline()` and `make_generator()`; `ModelSpec` never carries one. - **One accelerator model at a time**: when a tool phases two models - (`dltb-similarity-loop`: diffusion loop, then DreamSim), `del` the first and + (`dltb-distance-loop`: diffusion loop, then DreamSim), `del` the first and call `models.release_accelerator(device)` before loading the second, so peak VRAM is max(A, B) rather than the sum. - Model differences are encoded in `ModelSpec` (`uses_strength`, `pass_size`, diff --git a/NOTES.md b/NOTES.md index d78820e..ff3cc00 100644 --- a/NOTES.md +++ b/NOTES.md @@ -702,12 +702,12 @@ the single-frame smoke list, out of video runs. `flux-schnell` (~34 GB) and performance move quickly), and keep `uv.lock`'s arm64 wheels in mind when bumping torch. -## DreamSim perceptual metrics: `dltb-similarity` (2026-09-14) +## DreamSim perceptual metrics: `dltb-distance` (2026-09-14) **Why:** `analyze_drift.py` only sees pixels. A loop that has settled into a perceptual fixed point still chatters in pixel space (its `delta_prev` plateaus above the 0.5 threshold), while a loop can be pixel-stable and yet look nothing -like its source. `dltb-similarity` (`src/dltb/analyze_similarity.py`) embeds +like its source. `dltb-distance` (`src/dltb/analyze_distance.py`) embeds frames with DreamSim and reports two distances per frame: - `dreamsim_to_ref` — to the run's source image (`frame_0000_original.png` / @@ -752,7 +752,7 @@ frames, every 5th, ensemble): `analyze_drift` reported CONVERGED (delta_prev - Cache default is `--cache-dir untracked/models` (gitignored, cwd-relative). `untracked/` is **not** packed into pod bundles (tracked files + `untracked/input/` only), so a fresh pod re-downloads ~2.7 GB — that is why the smoke leg is - gated behind `SMOKE_SIMILARITY=1` and runs on the frames step 2 already + gated behind `SMOKE_DISTANCE=1` and runs on the frames step 2 already produced (no extra model pass). - Benign load noise, both on every load: the `torch.nn.utils.weight_norm` FutureWarning and peft's "Already found a `peft_config` attribute in the diff --git a/README.md b/README.md index afb4954..49b794f 100644 --- a/README.md +++ b/README.md @@ -44,17 +44,17 @@ The console scripts share the library code in `src/dltb/` (`models`, `imaging`, copied home, and videos are (re-)assembled locally — no torch, no accelerator (`uv run python src/dltb/assemble.py` also works; needs only numpy/PIL/imageio). -- `dltb-similarity` — perceptual counterpart to `analyze_drift.py`: scores a +- `dltb-distance` — perceptual counterpart to `analyze_drift.py`: scores a run's frames with DreamSim (learned DINOv2/CLIP ensemble, not pixels) and reports the distance to the run's source image (`dreamsim_to_ref`, drift) and to the previous frame (`dreamsim_to_prev`, perceptual fixed-point detection — ~0 while the loop still chatters means the chatter is invisible). Weights are downloaded on first use (see Requirements); runs on CUDA, Apple MPS, or CPU. -- `dltb-similarity-loop` — the free-running loop *and* the perceptual metrics +- `dltb-distance-loop` — the free-running loop *and* the perceptual metrics in one run, restricted to the strength-capable img2img models (`sd-turbo`, `sdxl-turbo`, `flux-schnell`): every pass is saved, then DreamSim scores each frame against the prepared original and its predecessor into - `similarity_metrics.csv`, and both series are charted to `similarity_plot.png` + `distance_metrics.csv`, and both series are charted to `distance_plot.png` (frame number on X, distance on Y). The diffusion pipeline is unloaded before DreamSim loads, so the two models never share accelerator memory. @@ -126,7 +126,7 @@ https://huggingface.co/black-forest-labs/FLUX.2-klein-9B, then set an `HF_TOKEN` environment variable with an access token from https://huggingface.co/settings/tokens (read-only is enough). -`dltb-similarity` and `dltb-similarity-loop` download DreamSim weights (~1.2 GB +`dltb-distance` and `dltb-distance-loop` download DreamSim weights (~1.2 GB checkpoint zip plus backbone checkpoints, ~2.7 GB for the default ensemble) from GitHub releases into `untracked/models` (gitignored) on first use; `--cache-dir` moves it and `--dreamsim-type` picks a cheaper single-backbone variant. `untracked/` is not @@ -158,17 +158,17 @@ uv run dltb-iterate --model flux-schnell --input menu.png --offload # Result analysis: pixel drift (CPU-only) and perceptual drift (DreamSim) uv run python src/dltb/analyze_drift.py untracked/output_sd_turbo/menu_free-running/frames -uv run dltb-similarity untracked/output_sd_turbo/menu_free-running/frames --every 5 --json sim.json +uv run dltb-distance untracked/output_sd_turbo/menu_free-running/frames --every 5 --json sim.json # Self-iteration with the DreamSim drift chart in one run -uv run dltb-similarity-loop --model sd-turbo --input menu.png --strength 0.4 \ +uv run dltb-distance-loop --model sd-turbo --input menu.png --strength 0.4 \ --prompt "a bronze lion sculpture" --iterations 60 ``` Runs land in `untracked/output_/_/` (e.g. `menu_free-running/`, `clip_stateful-a0.3_tailsfreeze-free-black60/`): the untouched input frame, -the saved frames, and the output video(s). `dltb-similarity-loop` uses a fixed -`similarity_s/` tag (no input stem) under the same model tree; since +the saved frames, and the output video(s). `dltb-distance-loop` uses a fixed +`distance_s/` tag (no input stem) under the same model tree; since prompt/steps/seed are not part of that tag, pass `--output-dir` subtrees when varying them — its `run.json` records the settings of each run. diff --git a/README_DEFERRED.md b/README_DEFERRED.md index 73f40d9..ed7e24b 100644 --- a/README_DEFERRED.md +++ b/README_DEFERRED.md @@ -23,7 +23,7 @@ or drop the section. ### Add `torchvision` (flipped the preprocessing backend; resolved 2026-09-14) Parked here as "ship with the next `uv.lock` change, and don't mix runs from -before/after" — then adding `dreamsim` for `dltb-similarity` pulled torchvision +before/after" — then adding `dreamsim` for `dltb-distance` pulled torchvision into `uv.lock` as a side effect, closing the item. The feared reproducibility break did not materialize: NOTES.md ("Runtime log noise" item 3) verified that the torchvision-backed transformers image processors are reachable only from diff --git a/README_RUNPOD.md b/README_RUNPOD.md index 36ebfe1..2dca183 100644 --- a/README_RUNPOD.md +++ b/README_RUNPOD.md @@ -116,7 +116,7 @@ The image itself does **not** count against the container disk (`df The default cache policy keeps every swept model (all five ≈ 87.5 GB) + xet (≤10 GB) + outputs (a full video sweep is a few GB) — plus ~2.7 GB of DreamSim -weights in `untracked/models` when `dltb-similarity` / `SMOKE_SIMILARITY=1` +weights in `untracked/models` when `dltb-distance` / `SMOKE_DISTANCE=1` is exercised (not part of bundles, so every fresh pod re-downloads them) — comfortable on the 150 GB disk, and revisiting an earlier model costs no re-download. With diff --git a/pyproject.toml b/pyproject.toml index 8e902f7..9a232ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,8 +29,8 @@ dltb-iterate = "dltb.iterate:main" dltb-continuous = "dltb.continuous:main" dltb-klein = "dltb.klein:main" dltb-assemble = "dltb.assemble:main" -dltb-similarity = "dltb.analyze_similarity:main" -dltb-similarity-loop = "dltb.similarity_loop:main" +dltb-distance = "dltb.analyze_distance:main" +dltb-distance-loop = "dltb.distance_loop:main" [build-system] requires = ["uv_build>=0.12.7,<0.13.0"] diff --git a/scripts/bundle.sh b/scripts/bundle.sh index 79593d5..551b5f5 100755 --- a/scripts/bundle.sh +++ b/scripts/bundle.sh @@ -54,7 +54,7 @@ fi for f in pyproject.toml uv.lock \ src/dltb/models.py src/dltb/imaging.py src/dltb/output.py src/dltb/args.py \ src/dltb/oneshot.py src/dltb/iterate.py src/dltb/continuous.py src/dltb/klein.py \ - src/dltb/similarity_loop.py; do + src/dltb/distance_loop.py; do [[ -f "${stage}/$f" ]] || { echo "bundle: missing $f" >&2; exit 1; } done diff --git a/scripts/smoke.sh b/scripts/smoke.sh index ce9ee80..89e3e99 100755 --- a/scripts/smoke.sh +++ b/scripts/smoke.sh @@ -30,7 +30,7 @@ # end-to-end check of the klein loop, # including the dual-ref reference-list # code path -# 6. dltb-similarity (optional) SMOKE_SIMILARITY=1: DreamSim over the +# 6. dltb-distance (optional) SMOKE_DISTANCE=1: DreamSim over the # frames step 2 already wrote (no extra # model run), CSV + JSON out -- gated # because the first call downloads ~2.7 GB @@ -58,7 +58,7 @@ # scripts/inputs.sh) # SMOKE_KLEIN=1 also smoke dltb-klein, both conditionings (off by default: # flux2-klein-4b is a ~15 GB download) -# SMOKE_SIMILARITY=1 also smoke dltb-similarity on step 2's frames (off by +# SMOKE_DISTANCE=1 also smoke dltb-distance on step 2's frames (off by # default: DreamSim downloads ~2.7 GB of weights) # KLEIN_MODEL klein model for that leg (default flux2-klein-4b) # SKIP_GPU_CHECK=1 bypass the accelerator preflight @@ -202,18 +202,18 @@ if [[ "${SMOKE_KLEIN:-0}" == "1" ]]; then check "$d/tail_freeze.mp4" fi -# 6. dltb-similarity, optional (SMOKE_SIMILARITY=1): DreamSim over the frames +# 6. dltb-distance, optional (SMOKE_DISTANCE=1): DreamSim over the frames # step 2 already produced -- no extra model run, just the analysis tool. # Default (ensemble) variant on purpose: it is what the tool runs by # default, and the three-backbone path is the one whose weights download # has been flaky. Uses the tool's default cache dir (untracked/models). -if [[ "${SMOKE_SIMILARITY:-0}" == "1" ]]; then +if [[ "${SMOKE_DISTANCE:-0}" == "1" ]]; then log "" - log "smoke: similarity leg (DreamSim weights download on first use)" + log "smoke: distance leg (DreamSim weights download on first use)" d="$OUT/${img_stem}_free-running" - run uv run dltb-similarity "$d/frames" --batch-size 2 --json "$d/similarity.json" - check "$d/similarity_metrics.csv" - check "$d/similarity.json" + run uv run dltb-distance "$d/frames" --batch-size 2 --json "$d/distance.json" + check "$d/distance_metrics.csv" + check "$d/distance.json" fi log "" diff --git a/src/dltb/analyze_similarity.py b/src/dltb/analyze_distance.py similarity index 94% rename from src/dltb/analyze_similarity.py rename to src/dltb/analyze_distance.py index 2b29152..00f01af 100644 --- a/src/dltb/analyze_similarity.py +++ b/src/dltb/analyze_distance.py @@ -10,7 +10,7 @@ # AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -"""analyze_similarity: DreamSim perceptual drift/convergence for a run's frames. +"""analyze_distance: DreamSim perceptual drift/convergence for a run's frames. Companion to analyze_drift.py. analyze_drift measures raw pixel deltas, so its delta_prev stays > 0 for as long as the loop chatters at all -- even when the @@ -38,11 +38,11 @@ but the package only checks for extracted checkpoint files, so switching --dreamsim-type re-downloads the ~1.2 GB zip. Usage: - uv run dltb-similarity untracked/output_sd_turbo/free-running/frames - uv run dltb-similarity untracked/output/.../frames --every 2 --dreamsim-type clip_vitb32 - uv run dltb-similarity untracked/output/.../frames --reference untracked/input/test_512.png --json sim.json + uv run dltb-distance untracked/output_sd_turbo/free-running/frames + uv run dltb-distance untracked/output/.../frames --every 2 --dreamsim-type clip_vitb32 + uv run dltb-distance untracked/output/.../frames --reference untracked/input/test_512.png --json sim.json -Outputs similarity_metrics.csv next to the frames dir and prints a summary. +Outputs distance_metrics.csv next to the frames dir and prints a summary. Unlike run tags, the CSV name does not encode --every / --dreamsim-type / --patch: use --out/--json (or a per-variant directory) when comparing variants, so one @@ -74,8 +74,8 @@ DEFAULT_CACHE_DIR = "untracked/models" def add_dreamsim_args(p: argparse.ArgumentParser) -> None: - """DreamSim variant/cache flags shared by dltb-similarity and - dltb-similarity-loop.""" + """DreamSim variant/cache flags shared by dltb-distance and + dltb-distance-loop.""" p.add_argument("--batch-size", type=int, default=8, help="Frames per model call (lower it if the accelerator runs out " "of memory; 8 x 224x224 costs ~1 GB with the ensemble)") @@ -124,7 +124,7 @@ def parse_args() -> argparse.Namespace: "converged' in the summary (heuristic, see the module " "docstring for calibration)") p.add_argument("--out", type=Path, default=None, - help="CSV path (default: /../similarity_metrics.csv)") + help="CSV path (default: /../distance_metrics.csv)") p.add_argument("--json", dest="json_out", type=Path, default=None, help="Also write metrics plus run metadata as JSON to this path") return p.parse_args() @@ -166,7 +166,7 @@ def load_model(dreamsim_type: str, patch: bool, retries: int, device: str, Checkpoints come from GitHub releases, whose CDN intermittently answers 'HTTP Error 504: Gateway Time-out' mid-download (observed for individual variants while others downloaded fine), so retry with exponential - backoff. Shared by dltb-similarity and dltb-similarity-loop. + backoff. Shared by dltb-distance and dltb-distance-loop. """ import urllib.error import zipfile @@ -197,7 +197,7 @@ def load_model(dreamsim_type: str, patch: bool, retries: int, device: str, def write_metrics_csv(rows: list[tuple[str, float, float]], out_csv: Path) -> None: """Write (frame, dreamsim_to_ref, dreamsim_to_prev) rows as CSV. - Shared with dltb-similarity-loop so both tools emit identical columns + Shared with dltb-distance-loop so both tools emit identical columns (the distance convention: 0.0 = identical, higher = more different). """ out_csv.parent.mkdir(parents=True, exist_ok=True) @@ -266,7 +266,7 @@ def main() -> None: device, cache_dir) rows = compute(frames, reference, model, preprocess, device, args.batch_size) - out_csv = args.out or args.frames_dir.parent / "similarity_metrics.csv" + out_csv = args.out or args.frames_dir.parent / "distance_metrics.csv" write_metrics_csv(rows, out_csv) tail = rows[-10:] diff --git a/src/dltb/args.py b/src/dltb/args.py index 8b5a493..0262350 100644 --- a/src/dltb/args.py +++ b/src/dltb/args.py @@ -28,7 +28,7 @@ def add_model_args(p: argparse.ArgumentParser, models: tuple[str, ...] | None = None) -> None: """--model over the full table (required). - models restricts the choices to a subset (e.g. dltb-similarity-loop + models restricts the choices to a subset (e.g. dltb-distance-loop passes STRENGTH_MODELS because it has no path for a model without --strength); the restriction then shows up in --help and at parse time. """ diff --git a/src/dltb/similarity_loop.py b/src/dltb/distance_loop.py similarity index 90% rename from src/dltb/similarity_loop.py rename to src/dltb/distance_loop.py index b6d797f..c0676c1 100644 --- a/src/dltb/similarity_loop.py +++ b/src/dltb/distance_loop.py @@ -9,7 +9,7 @@ # AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -"""dltb-similarity-loop: free-running self-iteration with a DreamSim chart. +"""dltb-distance-loop: free-running self-iteration with a DreamSim chart. Runs dltb-iterate's loop (P_n = f(P_{n-1}), every pass saved to frames/frame_NNNN.png) and then measures each frame twice with DreamSim: @@ -21,25 +21,25 @@ frames/frame_NNNN.png) and then measures each frame twice with DreamSim: first model-induced change. Distances are DreamSim's 1 - cosine similarity (0.0 = identical, higher = -more different) -- the same metric and CSV columns as dltb-similarity, so +more different) -- the same metric and CSV columns as dltb-distance, so curves from both tools are directly comparable. Frame 0 is the prepared -original itself (to_ref = to_prev = 0.0); dltb-similarity analyzes a frames/ +original itself (to_ref = to_prev = 0.0); dltb-distance analyzes a frames/ directory without it, so there iteration 1's to_prev is 0.0 instead. Artifacts land in the run directory: frame_0000_original.png the model-sized input (the reference frame) frames/frame_NNNN.png every iteration (always all of them) - similarity_metrics.csv frame, dreamsim_to_ref, dreamsim_to_prev - similarity_plot.png both series, frame number on X (matched + distance_metrics.csv frame, dreamsim_to_ref, dreamsim_to_prev + distance_plot.png both series, frame number on X (matched Y scale, lower = more similar) timelapse.mp4 best-effort, as in dltb-iterate run.json settings, since the tag encodes only strength (pass --output-dir subtrees when varying prompt/steps/seed) -Default output: untracked/output_/similarity_s (the shared ---output-dir flag puts runs under /similarity_s +Default output: untracked/output_/distance_s (the shared +--output-dir flag puts runs under /distance_s instead; keep pod runs out of the local tree, per AGENTS.md). Only the three strength-capable img2img models are accepted (sd-turbo, @@ -61,11 +61,11 @@ sum. DreamSim runs on the same --device; its weights (~2.7 GB for the default ensemble) download into --cache-dir on first use. Usage: - uv run dltb-similarity-loop --model sd-turbo --input menu.png \\ + uv run dltb-distance-loop --model sd-turbo --input menu.png \\ --strength 0.4 --prompt "a bronze lion sculpture" --iterations 60 # Cheap DreamSim variant, explicit output subtree for a knob not in the tag - uv run dltb-similarity-loop --model sdxl-turbo --input menu.png \\ + uv run dltb-distance-loop --model sdxl-turbo --input menu.png \\ --strength 0.2 --num-inference-steps 4 --iterations 100 \\ --dreamsim-type clip_vitb32 --output-dir untracked/output_lab/steps4 """ @@ -77,8 +77,8 @@ import json import statistics from pathlib import Path -from .analyze_similarity import (add_dreamsim_args, check_dreamsim_args, - compute, load_model, write_metrics_csv) +from .analyze_distance import (add_dreamsim_args, check_dreamsim_args, + compute, load_model, write_metrics_csv) from .args import (add_geometry_args, add_model_args, add_output_args, add_pass_args, non_empty_path) from .imaging import PassSettings, fit_to_model_size, make_generator, run_pass @@ -146,7 +146,7 @@ def run(args: argparse.Namespace) -> None: check_requirements(spec, args.num_inference_steps, args.strength) check_dreamsim_args(args) - out_dir = run_dir(args.output_dir, args.model, f"similarity_s{args.strength:g}") + out_dir = run_dir(args.output_dir, args.model, f"distance_s{args.strength:g}") frames_dir = out_dir / "frames" frames_dir.mkdir(parents=True, exist_ok=True) device = resolve_device(args.device) @@ -206,7 +206,7 @@ def run(args: argparse.Namespace) -> None: # --- phase 2: DreamSim over the original plus every saved frame -------- cache_dir = Path(args.cache_dir) # dreamsim's own downloader mkdirs a single level (os.mkdir), so nested - # --cache-dir needs this mkdir -p, exactly as in dltb-similarity. + # --cache-dir needs this mkdir -p, exactly as in dltb-distance. cache_dir.mkdir(parents=True, exist_ok=True) label = args.dreamsim_type + ("_patch" if args.patch else "") print(f"loading dreamsim {label} on {device} (weights: {cache_dir}; the " @@ -220,8 +220,8 @@ def run(args: argparse.Namespace) -> None: del model, preprocess release_accelerator(device) - out_csv = out_dir / "similarity_metrics.csv" - out_plot = out_dir / "similarity_plot.png" + out_csv = out_dir / "distance_metrics.csv" + out_plot = out_dir / "distance_plot.png" write_metrics_csv(rows, out_csv) prompt = args.prompt if len(args.prompt) <= 60 else args.prompt[:57] + "..." title = (f"{args.model} strength={args.strength:g} " diff --git a/src/dltb/models.py b/src/dltb/models.py index c5bb712..2e1b100 100644 --- a/src/dltb/models.py +++ b/src/dltb/models.py @@ -116,7 +116,7 @@ MODELS: dict[str, ModelSpec] = { # Tools whose pipeline is called with --strength (classic img2img): keep in # sync with the uses_strength flags above, never by hand-listing model keys at -# call sites (dltb-similarity-loop restricts --model with this). +# call sites (dltb-distance-loop restricts --model with this). STRENGTH_MODELS: tuple[str, ...] = tuple( key for key, spec in MODELS.items() if spec.uses_strength) @@ -211,7 +211,7 @@ def release_accelerator(device: str) -> None: Call AFTER `del `: CPython then frees the tensors, gc collects the reference cycles, and empty_cache() returns the freed blocks to the driver. Without this, a following model load (e.g. DreamSim in - dltb-similarity-loop) starts from a caching allocator that still holds + dltb-distance-loop) starts from a caching allocator that still holds the previous model's allocation, so peak VRAM would approach the sum of both models instead of the max. No-op on CPU (requested explicitly, never auto). -- 2.51.2