open-standards/.github/workflows/wai-neural-e2e.yml
Transaction Science fdce7d9172 wai: decouple the neural decoders from the C codec chain
The neural feature pulled `codecs`, dragging the AV1/JXL/opus/FLAC C chain
(meson/ninja/nasm + dev libs) into any neural build — including the neural-e2e
CI job, which failed building libdav1d-sys. But the Rust neural decoders need
only `ort`; nothing in src/neural uses crate::codecs. The two couplings were
incidental: the neural C FFI (ffi_neural) wraps the codec FFI's shared
buffer/error types, and zstd-safe needed its `std` feature (which codecs' zstd
was enabling transitively).

Fix both: gate ffi_neural on all(neural, codecs) — the Rust decoders stay
available with just `neural`, only the C FFI wrapper needs the codec FFI — and
give zstd-safe `features=["std"]` directly. neural now drops `codecs`.

So the neural-e2e job builds `--no-default-features --features neural`: no
system codec deps, just ort. All 6 reference decoders (elic/mlicpp/glc/dcvc/
snac) reproduce their references end-to-end without the C chain. Both
codecs+neural and neural-alone build clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 04:09:46 -04:00

56 lines
2.7 KiB
YAML

name: WAI neural decoders end-to-end
# The float neural decoders (elic / mlicpp / glc / dcvc / snac) cannot make
# WAI's cross-architecture byte-equality promise — their ONNX synthesis is
# float, so the low bits differ by hardware (this is exactly why the
# integer-exact int_synth path exists, and why only it is in the byte-equality
# matrix). What they CAN be is *correct end-to-end* on a real machine: entropy
# decode → ONNX synthesis → image assembly, reproducing a reference within ORT
# float rounding (±4). This job proves that, with no committed model blobs:
# the committed tool builds minimal synthetic CompressAI-compatible models +
# bitstreams, and the Rust decoders reproduce each reference. It runs only when
# the neural decode code or the generator changes — not on every cargo class.
on:
push:
branches: [main]
paths:
- 'wai/wai-rs/src/neural/**'
- 'wai/wai-rs/tests/neural_native_decode.rs'
- 'wai/tools/wai_validate_synthetic.py'
- '.github/workflows/wai-neural-e2e.yml'
pull_request:
paths:
- 'wai/wai-rs/src/neural/**'
- 'wai/wai-rs/tests/neural_native_decode.rs'
- 'wai/tools/wai_validate_synthetic.py'
- '.github/workflows/wai-neural-e2e.yml'
jobs:
neural-e2e:
name: synthetic fixtures → Rust decode → reference (±4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: ML stack (CPU torch + torchvision + compressai + onnxruntime)
run: |
python -m pip install --upgrade pip
# torch AND torchvision from the CPU index so their compiled ops match
# (compressai imports torchvision; a mismatched build fails at
# `torchvision::nms does not exist`).
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
# `onnx` (the exporter) is separate from `onnxruntime` (the decoder).
pip install compressai onnx onnxruntime numpy pillow
- name: Build the synthetic fixtures (elic / mlicpp / snac / dcvc / glc)
working-directory: wai
run: python tools/wai_validate_synthetic.py --size 256
- name: Rust 1.96.0
run: rustup toolchain install 1.96.0 --profile minimal && rustup default 1.96.0
- name: Each Rust decoder reproduces its reference end-to-end
working-directory: wai/wai-rs
# --no-default-features: the neural decoders need only `ort`, NOT the C
# codec chain (AV1/JXL/opus), so the job needs no system codec deps.
run: cargo test --no-default-features --features neural --test neural_native_decode -- _matches_reference --nocapture