Conversation
There was a problem hiding this comment.
Pull request overview
Prepares the 0.0.15 release by updating dependency floors/pins for security advisories, fixing several model inference correctness issues (RawNet2 input normalization, Spectra calibrated thresholds, AST sampling rate), and deduplicating common model-loading/device-selection utilities across the codebase.
Changes:
- Raise/refresh dependency versions (notably
torch>=2.13.0) and bump release metadata (pyproject.toml,README.md,CITATION.cff,CHANGELOG.md). - Fix model inference behavior: RawNet2 now resamples/pads/trims to the expected 16kHz/64600-sample window; AST passes
sampling_rate; Spectra0/SpectraAASIST use calibrated thresholds. - Deduplicate shared utilities (VIT
load_pipeline()caching, sharedget_device()), and update CI/pre-commit pins.
Reviewed changes
Copilot reviewed 20 out of 22 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_models.py | Updates mocks/patch points for shared VIT loader; adds coverage for calibrated Spectra thresholds and RawNet2 resample/length normalization. |
| src/Jabberjay/Utilities/enum_handler.py | Prevents fallthrough after parser.error() by returning explicitly. |
| src/Jabberjay/Utilities/device.py | Introduces shared get_device() helper to centralize device selection + logging. |
| src/Jabberjay/Models/Transformer/VIT/utility.py | Adds shared cached load_pipeline() for VIT and removes redundant canvas draw. |
| src/Jabberjay/Models/Transformer/VIT/MFCC/run.py | Switches to shared load_pipeline() utility. |
| src/Jabberjay/Models/Transformer/VIT/MelSpectrogram/run.py | Switches to shared load_pipeline() utility. |
| src/Jabberjay/Models/Transformer/VIT/ConstantQ/run.py | Switches to shared load_pipeline() utility. |
| src/Jabberjay/Models/Transformer/AST/run.py | Passes sampling_rate=16000 to shared transformers pipeline runner. |
| src/Jabberjay/Models/SpectraAASIST3/run.py | Uses shared get_device() for device selection. |
| src/Jabberjay/Models/SpectraAASIST/run.py | Uses shared get_device() and applies documented calibrated threshold logic. |
| src/Jabberjay/Models/Spectra0/run.py | Uses shared get_device() and applies calibrated threshold logic. |
| src/Jabberjay/Models/RawNet2/run.py | Adds resampling + trim/pad to fixed window and uses shared get_device(). |
| src/Jabberjay/jabberjay.py | Updates RawNet2 handler to pass sr through to RawNet2 predict(). |
| README.md | Bumps cited version to 0.0.15. |
| pyproject.toml | Bumps package version and refreshes dependency constraints and dev tools. |
| CITATION.cff | Updates release version/date metadata. |
| CHANGELOG.md | Adds 0.0.15 release notes and comparison link. |
| .pre-commit-config.yaml | Bumps pre-commit hook revisions. |
| .gitignore | Adds venv/ and .venv/ ignores. |
| .github/workflows/docs.yml | Bumps setup-uv action pin. |
| .github/workflows/ci.yml | Bumps setup-uv action pin across jobs. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 22 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/Jabberjay/Models/RawNet2/run.py:61
- The empty-audio guard happens after the optional resample. If
yis empty andsr != _TARGET_SR,torchaudio.functional.resample()is called first and will likely raise a low-levelRuntimeError, bypassing the intendedValueErrorwith a clear message. Check for zero-length input before resampling so empty input is handled consistently regardless ofsr.
audio = torch.from_numpy(y).float()
if sr != _TARGET_SR:
audio = torchaudio.functional.resample(audio, int(sr), _TARGET_SR)
audio_len = audio.shape[0]
if audio_len == 0:
Bumps the uv group with 1 update in the / directory: [torch](https://github.com/pytorch/pytorch). Updates `torch` from 2.12.1 to 2.13.0 - [Release notes](https://github.com/pytorch/pytorch/releases) - [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md) - [Commits](pytorch/pytorch@v2.12.1...v2.13.0) --- updated-dependencies: - dependency-name: torch dependency-version: 2.13.0 dependency-type: direct:production dependency-group: uv ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the uv group with 1 update in the / directory: [torch](https://github.com/pytorch/pytorch). Updates `torch` from 2.12.1 to 2.13.0 - [Release notes](https://github.com/pytorch/pytorch/releases) - [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md) - [Commits](pytorch/pytorch@v2.12.1...v2.13.0) --- updated-dependencies: - dependency-name: torch dependency-version: 2.13.0 dependency-type: direct:production dependency-group: uv ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matthew Boakes <Matthew.Boakes@Gmail.com>
Closes GHSA-h35f-9h28-mq5c (setuptools MANIFEST.in bypass) and raises the torch floor to >=2.13.0 so a fresh install can never resolve the CVE-2025-3000-vulnerable 2.12.x line. Also refreshes transitive deps (huggingface-hub, transformers, ruff, ty, mkdocs-material, etc.) and bumps stale pre-commit hook pins and the setup-uv GitHub Action from major v7 to v9.
RawNet2's SincConv filters are hardcoded to 16kHz and the model was trained on fixed 64600-sample windows, but predict() fed it raw audio at whatever rate Jabberjay.load() produced (22050Hz by default) with no length normalization. This silently miscalibrated the sinc bandpass and produced wrong scores with no error, unlike every other torch backend (Spectra family) which already resamples and pads/trims correctly.
_load_pipeline() (image-classification, cached_loader) was copy-pasted identically across ConstantQ/, MFCC/, and MelSpectrogram/ run.py. Moved to Transformer/VIT/utility.py as load_pipeline(), matching the pattern already used by Models/Spectra/shared.py, and widened the shared cache from 3x maxsize=4 to a single maxsize=8 covering the full dataset x visualisation matrix.
"cuda" if torch.cuda.is_available() else "cpu" plus a matching debug log line was duplicated independently across RawNet2, Spectra0, SpectraAASIST, and SpectraAASIST3. Consolidated into Utilities/device.get_device().
parser.error() always raises SystemExit in normal argparse usage, but EnumAction.__call__() fell through to setattr() with an unassigned value on invalid input, relying entirely on that contract. Add an explicit return so the failure mode is a clean control-flow guarantee rather than an implicit assumption about argparse internals.
HuBERT, Wav2Vec2, and WavLM all pass sampling_rate=16000 to run_pipeline(); AST was the one outlier omitting it despite the underlying AST feature extractor expecting the same 16kHz input.
plt.savefig() redraws the canvas internally, so the explicit fig.canvas.draw() beforehand was wasted work on every VIT inference call.
predict() derived the Bonafide/Spoof verdict via softmax+argmax, which is equivalent to thresholding the bonafide logit at 0. But lab260's own classify() method (and model cards) document a different, EER-tuned decision boundary: -1.0625009 for Spectra0, -1.140625 for SpectraAASIST. Argmax silently used the wrong boundary for borderline samples. SpectraAASIST3 is intentionally left unchanged: its classify() default (-1.0625009) is undocumented on its model card and identical to Spectra0's value in both Jabberjay's and lab260's own upstream model.py — almost certainly a stale copy-paste rather than a real calibration, so there's no trustworthy threshold to adopt for that model yet.
Bumps version and adds the CHANGELOG entry covering this session's work: two CVE closures (torch/CVE-2025-3000, setuptools/GHSA-h35f), the RawNet2 resampling fix, the Spectra0/AASIST calibrated-threshold fix, and the AST/EnumAction/VIT/device cleanups. Also gitignores venv/ and .venv/ — an untracked local venv/ directory was getting swept into `uv build`'s sdist (via hatchling's default git-based file selection, which only skips gitignored paths) and crashing the pack step on an absolute symlink. Harmless in CI's clean checkout, but broke local `uv build`.
astral-sh/setup-uv@v9 doesn't resolve — only the exact v9.0.0 release tag exists upstream, the floating major alias hasn't been published yet. Broke CI immediately after pushing the v7->v9 bump.
Co-authored-by: MattyB95 <5563995+MattyB95@users.noreply.github.com>
Copilot's assert->raise and zero-length-audio fixes weren't black-formatted, which was failing CI's format-check job. Also adds a test for the empty-audio ValueError path and marks the _CONFIG-is-None branch pragma: no cover — that invariant is guaranteed by _load_model() and unreachable in practice, same as the EnumAction fallthrough guard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
torch.jit.scriptmemory corruption) by raising the floor to>=2.13.0, and GHSA-h35f-9h28-mq5c (setuptools MANIFEST.in NFC/NFD bypass) by locking to 84.0.0sampling_rate, matching HuBERT/Wav2Vec2/WavLM;EnumActionno longer falls through afterparser.error()See
CHANGELOG.md[0.0.15] for full details.Test plan
uv run pytest)uv run ruff check .,uv run black --check .,uv run ty check src/)uv buildproduces a clean sdist/wheeldevelop(lint, full test matrix, TestPyPI pre-release publish)