Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
237 lines
13 KiB
Markdown
237 lines
13 KiB
Markdown
# Phonon-2: minimal variant validation
|
|
|
|
Revision responding to [maintainer feedback](https://github.com/0xShug0/audio.cpp/pull/863#issuecomment-6100453087).
|
|
The existing Parakeet family/loader/backend math remains in use. Model-local
|
|
hotwords, rolling streaming and `word_timestamp_mode` remain. The F32 precision
|
|
API, CPU weight-expansion policy and runtime BN/input-scale overrides are removed.
|
|
Vulkan optimizations are reviewed independently. No backend or GGML files change.
|
|
|
|
## Controlled mathematics
|
|
|
|
All 699 F32 inference tensors match independently decoded original records after
|
|
the documented conversion transforms, and match the GGUF exactly. The 1/32
|
|
projection transform cancels the normal loader's scale fold. BN gamma compensation
|
|
preserves the reference formula in two channels affected by its variance floor.
|
|
No runtime arithmetic customization is required.
|
|
|
|
CPU F32 encoder relative L2 error on the 3 s speech fixture is
|
|
`1.04e-06` (limit `1e-4`); maximum absolute error is
|
|
`3.5e-07`. Text and actual token-duration word timestamps
|
|
match the independently pinned reference exactly. No randomness was introduced;
|
|
all backend/storage requests repeat their own outputs exactly.
|
|
|
|
## Ordinary requests
|
|
|
|
Twenty inputs: speech, silence, short/longer video excerpts and music as arithmetic
|
|
stress coverage. Counts below use the published dense F32 reference. Exact word
|
|
timing uses its 1 ms JSON print tolerance; whole 80 ms shifts are recorded as
|
|
differences. Word edits use case/punctuation-normalized Levenshtein distance over
|
|
450 reference words. They are not a human-labelled WER benchmark.
|
|
|
|
| Storage | Backend | Exact text | Exact timing | Reference word edits | Exact repeat |
|
|
|---|---|---:|---:|---:|---:|
|
|
| f32 | cpu | 20/20 | 20/20 | 0/450 | 20/20 |
|
|
| f32 | cuda | 20/20 | 19/20 | 0/450 | 20/20 |
|
|
| f32 | vulkan | 20/20 | 20/20 | 0/450 | 20/20 |
|
|
| bf16 | cpu | 20/20 | 19/20 | 0/450 | 20/20 |
|
|
| bf16 | cuda | 19/20 | 18/20 | 2/450 | 20/20 |
|
|
| bf16 | vulkan | 20/20 | 19/20 | 0/450 | 20/20 |
|
|
| q8_0 | cpu | 19/20 | 17/20 | 1/450 | 20/20 |
|
|
| q8_0 | cuda | 18/20 | 17/20 | 3/450 | 20/20 |
|
|
| q8_0 | vulkan | 19/20 | 17/20 | 1/450 | 20/20 |
|
|
|
|
F32 text matches on every input/backend. Reduced-precision differences and CUDA
|
|
duration/timing differences are explicitly retained in the evidence; this is not
|
|
a claim of universal precision equivalence or no corpus-level quality change.
|
|
All nine combinations complete and pass their upload endpoint text check.
|
|
|
|
## Features and regressions
|
|
|
|
- Original hotword policy: 9 lists, 329 transition/bonus vectors exactly match.
|
|
- Original decoder/hotword/live final text: 54/54; final stream segments: 18/18.
|
|
Original offline timings match in 27/36 cases and provisional sequences in
|
|
5/18.
|
|
These diagnostic differences are included rather than hidden by forcing GPU precision.
|
|
- CPU/CUDA/Vulkan actual CLI and legacy server: uploaded streaming, unaligned
|
|
live PCM, per-request isolation and repeated requests pass.
|
|
- CPU/CUDA/Vulkan lifecycle: 13/2049/whole-input chunking, invalid order/retry,
|
|
repeat finalize/post-final rejection, nonfinite input and callback failure
|
|
recovery, idle/reuse and multiple phrases pass. Six named-term F32 cases match
|
|
original final text. Committed deltas equal final text; timestamps stay in range.
|
|
- Stock Parakeet Q8 offline/buffered streaming: six before/after text/timing checks
|
|
pass. Bad strength/JSON recovery and biased silence pass.
|
|
- CPU CTest: 54/54; combined-build targeted CTest: 4/4; converter/timestamp Python:
|
|
14/14. Windows source encoding and embedded catalog are enabled; no assertions
|
|
or unrelated framework tests were weakened.
|
|
|
|
Dedicated HTTP hotword fields were removed after those measurements. Hotwords
|
|
use generic `options` on JSON and batch multipart requests; single-file uploads
|
|
and live PCM use the existing `prompt` interface. A subsequent CUDA check covered
|
|
18 requests across standard and parallel servers, including upload, upload
|
|
streaming and live PCM: prompt bias took effect, removing it restored the
|
|
baseline, and committed deltas concatenated to the final text.
|
|
After separating variant selection from timestamp formatting, eight further
|
|
CUDA live requests using a newly packaged F32 GGUF matched the previous final
|
|
text and unprompted snapshot sequences exactly. Both server modes preserved
|
|
prompt bias and repeated-request isolation, with `session.wall_ms` emitted for
|
|
each request. These checks do not establish new performance results.
|
|
|
|
## Functional timing and memory
|
|
|
|
Windows Ryzen 7950X3D (8 threads), RTX 3090, MSVC 14.43, CUDA 12.4, Vulkan SDK
|
|
1.4.350. Median of five warm HTTP requests for an 11.9925 s clip, excluding loading.
|
|
CPU peak is process RSS; GPU peak is device-wide NVML sampled every 20 ms, after
|
|
subtracting the desktop baseline, over the complete 20-input sequence. Both
|
|
include weights/work buffers. Samples may miss short peaks or include unrelated
|
|
driver/desktop allocations; do not interpret this as cache alone or a controlled
|
|
before/after speedup experiment. Some CPU functional runs overlap the reference
|
|
process; the separate optimization report uses alternating timing trials.
|
|
|
|
| Storage | Backend | Warm request (ms) | Peak RSS (GiB) | Additional peak VRAM (GiB) |
|
|
|---|---|---:|---:|---:|
|
|
| f32 | cpu | 549.3 | 4.63 | n/a |
|
|
| f32 | cuda | 42.5 | 2.95 | 3.24 |
|
|
| f32 | vulkan | 68.4 | 2.88 | 3.38 |
|
|
| bf16 | cpu | 518.0 | 3.51 | n/a |
|
|
| bf16 | cuda | 45.0 | 2.15 | 2.62 |
|
|
| bf16 | vulkan | 62.1 | 2.11 | 2.72 |
|
|
| q8_0 | cpu | 530.4 | 3.46 | n/a |
|
|
| q8_0 | cuda | 41.5 | 2.19 | 2.37 |
|
|
| q8_0 | vulkan | 67.5 | 2.12 | 3.90 |
|
|
|
|
## Reproduce
|
|
|
|
Use the [Phonon-2 section in the Parakeet guide](../models/parakeet_tdt.md#phonon-2-parakeet-tdt-variant).
|
|
Actual build commands use Ninja Release, `AUDIOCPP_MODEL_SET=custom`,
|
|
`ENGINE_BUILD_TESTS=ON`, `AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER=OFF` and
|
|
`AUDIOCPP_BUILD_SERVER_FRONTENDS=OFF`. The combined build enables CUDA/Vulkan,
|
|
`CMAKE_CUDA_ARCHITECTURES=86`, `AUDIOCPP_MODELS=parakeet_tdt` and
|
|
`ENGINE_BUILD_MODEL_TESTS=ON`; the common CPU suite disables GPU/model tests,
|
|
sets `AUDIOCPP_DEPLOYMENT_BUILD=ON` and links
|
|
`parakeet_tdt;sortformer_diar_v2;supertonic`. MSVC uses `/EHsc /utf-8`.
|
|
Build CLI/server, `phonon_features_probe`, `phonon_hotwords_test`,
|
|
`parakeet_variant_config_test`, `partial_text_render_test`, the common CTest
|
|
targets, and the combined-build `tdt_decoder_duration_loop_test`/`parakeet_parity_dump`.
|
|
|
|
In an MSVC 14.43 developer environment with CUDA/Vulkan SDKs on PATH,
|
|
the combined runtime build used:
|
|
|
|
```bash
|
|
cmake -S . -B ../build-gpu -G Ninja -DCMAKE_BUILD_TYPE=Release \
|
|
'-DCMAKE_CXX_FLAGS=/DWIN32 /D_WINDOWS /EHsc /utf-8' \
|
|
-DAUDIOCPP_MODEL_SET=custom -DAUDIOCPP_MODELS=parakeet_tdt \
|
|
-DENGINE_BUILD_TESTS=ON -DENGINE_BUILD_MODEL_TESTS=ON -DENGINE_BUILD_WARMBENCH=ON \
|
|
-DAUDIOCPP_BUILD_NATIVE_MODEL_MANAGER=OFF -DAUDIOCPP_BUILD_SERVER_FRONTENDS=OFF \
|
|
-DAUDIOCPP_DEPLOYMENT_BUILD=ON -DGGML_CCACHE=OFF \
|
|
-DENGINE_ENABLE_CUDA=ON -DENGINE_ENABLE_VULKAN=ON -DCMAKE_CUDA_ARCHITECTURES=86
|
|
cmake --build ../build-gpu -j 6 --target audiocpp_cli audiocpp_server audiocpp_gguf \
|
|
phonon_features_probe phonon_hotwords_test parakeet_variant_config_test \
|
|
partial_text_render_test tdt_decoder_duration_loop_test parakeet_parity_dump
|
|
ctest --test-dir ../build-gpu --output-on-failure \
|
|
-R 'phonon_hotwords_test|parakeet_variant_config_test|tdt_decoder_duration_loop_test|partial_text_render_test'
|
|
```
|
|
|
|
```bash
|
|
ctest --test-dir build-cpu --output-on-failure
|
|
python tests/parakeet_tdt/test_phonon2_conversion.py
|
|
python tests/parakeet_tdt/test_phonon2_timestamps.py
|
|
python tests/parakeet_tdt/validate_phonon2_hotwords.py \
|
|
--probe build/bin/phonon_features_probe \
|
|
--original-hotwords ORIGINAL_WHEEL/fermion/_speech/hotwords.py \
|
|
--source-config models/Phonon-2-source/extracted/config.json
|
|
```
|
|
|
|
`validate_phonon2.py` audits weights and numerical bounds; exact text/timing is
|
|
diagnostic unless `--require-exact-reference` is supplied for the controlled CPU
|
|
F32 run. The [portable JSON](../../tests/parakeet_tdt/phonon2_validation.json) includes source/model hashes,
|
|
all matrix summaries and differing fixture IDs. Raw commands/configs/outputs are
|
|
under `outputs/phonon2-review-20261010/`; earlier pre-compensation evidence is
|
|
preserved in its `pre-bn-compensation/` directory. No user audio is uploaded.
|
|
RTX 5090, Metal/HIP/MUSA runtime coverage is absent; removing the failing API path
|
|
does not constitute a verified RTX 5090 fix. Original WebSocket protocol and
|
|
packed kernels remain outside this PR.
|
|
|
|
## Mixed GGUF storage follow-up
|
|
|
|
Opt-in `mixed-f16` preserves all 699 staged tensor values exactly (327 F16,
|
|
372 F32 tensors). `mixed-q8` keeps sensitive feed-forward/pointwise weights in
|
|
exact F16 and non-F16-representable, normalization and compensated projection
|
|
values in F32, with ordinary rounded Q8_0 for the remaining matrices (120 Q8_0,
|
|
144 F16, 435 F32 tensors). It is not lossless whole-model storage. Both use
|
|
the normal Parakeet runtime; existing `orig`, `bf16`, `q8_0` defaults and shared
|
|
backends are unchanged. Mixed-FP16 is not a new BF16 package.
|
|
|
|
The 21-input follow-up adds the maintainer's 28 s WAV to the existing ten original
|
|
and ten holdout clips. Reference is the published dense Python FP32 route.
|
|
Timing counts below require every word in a clip to match within 1 ms.
|
|
Native FP32 GPU results also have reference differences; this does not claim
|
|
that either mixed package improves every timestamp or surpasses FP32 accuracy.
|
|
|
|
| Package | GB (decimal) | Exact transcript | Exact word-timing clip | Exact repeat |
|
|
|---|---:|---:|---:|---:|
|
|
| FP32 | 2.510 | 63/63 | 61/63 | 63/63 |
|
|
| Old BF16 | 1.264 | 62/63 | 56/63 | 63/63 |
|
|
| Old Q8 | 0.944 | 59/63 | 51/63 | 63/63 |
|
|
| Mixed-FP16 | 1.302 | 63/63 | 59/63 | 63/63 |
|
|
| Mixed-Q8 | 1.184 | 63/63 | 60/63 | 63/63 |
|
|
|
|
Mixed-FP16 is 48.1% smaller than FP32. Mixed-Q8 is 52.8% smaller than FP32,
|
|
25.5% larger than old Q8 and 9.1% smaller than mixed-FP16. All mixed-Q8 final
|
|
tensor payloads/types match the tested candidate; all 63 final request pairs
|
|
repeat exactly. Converter/timestamp Python: **16/16**; targeted CTest: **4/4**.
|
|
SHA256 mixed-FP16: `3ca25f950f46ab66f5b09ad806610ad0ff826c0d0cf0360fc87d4d704eb104c7`;
|
|
mixed-Q8: `238f4d03628ae7d594fe6345535cadba4f8576331ff5d7572c838add583ca25d`. These are file/storage comparisons, not VRAM
|
|
measurements. Existing optional F32 weight-loading session settings reproduce
|
|
the corresponding native FP32 package for mixed-FP16, using its working memory.
|
|
|
|
Recorded loaded-model request times for the same 28 s input, in seconds:
|
|
|
|
| Backend | FP32 | Old BF16 | Old Q8 | Mixed-FP16 | Mixed-Q8 |
|
|
|---|---:|---:|---:|---:|---:|
|
|
| CPU | 2.831 | 2.823 | 2.416 | 3.002 | 2.506 |
|
|
| CUDA | 0.120 | 0.109 | 0.111 | 0.116 | 0.104 |
|
|
| VULKAN | 0.211 | 0.187 | 0.191 | 0.199 | 0.185 |
|
|
|
|
These are single HTTP request measurements from separate validation passes,
|
|
excluding model loading, on Ryzen 7950X3D / RTX 3090 with 4 threads. They are
|
|
not alternating controlled speed trials and establish no general speedup.
|
|
Earlier timing tables use a different clip/thread setting; do not combine them.
|
|
|
|
Selected word-end offsets from Python FP32 on the maintainer WAV (milliseconds):
|
|
|
|
| Backend | Word | Native FP32 | Old BF16 | Old Q8 | Mixed-FP16 | Mixed-Q8 |
|
|
|---|---|---:|---:|---:|---:|---:|
|
|
| CPU | solar | 0 | 0 | +160 | 0 | 0 |
|
|
| CPU | sunrise. | 0 | +320 | 0 | 0 | 0 |
|
|
| CPU | spare | 0 | +80 | 0 | +80 | 0 |
|
|
| CUDA | solar | 0 | 0 | +160 | 0 | 0 |
|
|
| CUDA | sunrise. | 0 | +320 | 0 | 0 | 0 |
|
|
| CUDA | spare | 0 | +80 | 0 | +80 | +80 |
|
|
| VULKAN | solar | 0 | 0 | 0 | 0 | 0 |
|
|
| VULKAN | sunrise. | +320 | +320 | +320 | +320 | +320 |
|
|
| VULKAN | spare | +80 | +80 | +80 | +80 | +80 |
|
|
|
|
Reference ends: solar 3.84 s, sunrise. 14.56 s, spare 18.80 s. Other words on
|
|
this input match for these configurations. On `movie_offset_240_12s`, mixed-Q8
|
|
CPU introduces `to` start +80/end +240 ms and `improve` start/end +80 ms, where
|
|
old Q8 matches. Mixed-FP16 has other CPU/CUDA timing differences as recorded in
|
|
the portable JSON. Corpus WER and RTX 5090/Metal/HIP/MUSA remain untested.
|
|
|
|
## Duration diagnostics
|
|
|
|
One encoder frame is 80 ms (160-sample hop, 8x subsampling, 16 kHz). Scores near
|
|
ties can change blank/token choice or duration while preserving final text.
|
|
On the maintainer WAV, Python's period beats blank by 0.003579 score units;
|
|
duration 1 beats 2 by 0.001392. The Vulkan +320 ms `sunrise.` shift combines
|
|
later punctuation emission with a longer duration; it is not a clock error.
|
|
|
|
The same Python encoder output replayed through native FP32 decoders gives
|
|
identical IDs/frames/durations for all 166 retained tokens on CPU/CUDA/Vulkan.
|
|
FP32 encoder relative L2 on 350 valid rows is 8.77e-7 / 5.39e-4 / 5.03e-3;
|
|
the unused 351st capacity row is excluded. Encoder and decoder rounding can
|
|
reinforce or cancel differences. The original Fermion CPU wrapper also marks
|
|
2801 feature frames valid versus the dense route's 2800. A mask-only crossover
|
|
removes its word-time differences on this WAV, not a claim about every input.
|
|
No timestamp offsets, fitted duration choices or mandatory backend precision
|
|
controls were introduced. Raw captures remain in the follow-up artifact folders
|
|
listed in the existing portable JSON; user audio is not uploaded.
|