voice_audio_multi/tests/kitten_tts2/README.md
Fabio c36510c21e
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
Initial import: audio.cpp with Orange Pi documentation
2026-11-04 19:05:22 +01:00

269 lines
13 KiB
Markdown

# Kitten TTS 2 validation
Powered by Stellon Labs.
Run commands from the audio.cpp repository root. Replace
`/absolute/path/kitten-tts-2` with the local upstream model directory and
`/absolute/path/KittenTTS` with the upstream source checkout. They need not be
siblings of audio.cpp. Point GGUF arguments at the downloaded package or your
own converted file.
Commands below use POSIX-shell `\` line continuations. In PowerShell, join
the lines or replace those continuations with backticks. Environment-variable
setup is shown separately for both shells.
Build per the [model guide](../../docs/models/kitten_tts2.md), adding
`-DENGINE_BUILD_TESTS=ON`. Build `kitten_tts2_session_probe`,
`kitten_tts2_components_probe`, and `model_spec_system_test`.
The [validation record](validation.md)
includes the Windows configure/build commands and results for the current port.
On Visual Studio, use `bin/Release/` and append `.exe` below.
[Chatterbox S3 encoder correctness PR #778](https://github.com/0xShug0/audio.cpp/pull/778)
and the Kitten model PR #776 are included in the upstream base for this follow-up.
No additional correctness patch is needed on that base. The validation record
also retains the earlier pre-merge results and their prerequisite.
```sh
python tools/check_loader_catalog_sync.py
build-kitten2/bin/model_spec_system_test
```
## Validation assets
### Execution plans
For an isolated NEON A/B, build with `ENGINE_ENABLE_NEON=ON` and compare plans
`{"vocoder":{"impl":"ggml"}}` and
`{"vocoder":{"impl":"neon","backend":"cpu"}}` using the same executable,
requests, threads, and weights. Leave all other execution-plan fields omitted.
Compare `kitten_tts2.vocoder_ms`, total RTF, audio lengths and sample errors,
then ASR the output. `neon_vocoder_test` independently checks the HiFT network,
production upsample geometry, Snake epsilon, shape changes, and thread counts.
The session probe accepts `metal` as well as `cpu` and `cuda`. Use `-` to skip
the optional upstream reference directory. Its final optional argument is the
`kitten_tts2.exec_plan` JSON. For example:
```sh
build-kitten2/bin/kitten_tts2_session_probe <model.gguf> <output-directory> 8 native - cpu \
'{"vocoder":{"impl":"neon","backend":"cpu"}}'
```
Run the same probe without the JSON argument as the default-path control. For
Metal, pass `metal` with the same NEON vocoder plan.
The probe checks invalid execution plans, seeded repeats, voice switching,
long-form chunks, and unknown-voice rejection.
### Updated BF16, Q8 and hybrid Q4
Build `kitten_tts2_session_probe` with `-DENGINE_BUILD_MODEL_TESTS=ON` in both
CPU-only and CUDA builds. The probe checks all three stored precision combinations. Pass
`default` as its weight-type argument to exercise the package's
default precision policy, followed by the matching upstream asset directory
and `cpu` or `cuda`. Run the existing multilingual server checks with the
exporter's complete `voices-default.json` and the updated reference assets.
Also run with `native`, the default advertised by the current external model
contract. For each GGUF, it should match the same seeded run with the option
omitted. Run from the repository root and check the contract trace points to
`model_specs/kitten_tts2.json` so this exercises external-contract precedence,
not only the embedded GGUF fallback.
`python tools/model_manager_v2.py info kitten_tts2 --json` should select
`kitten_tts2_q8_v2`. The rebuilt WebUI should offer **GGUF Q8**,
**GGUF Q4** and **GGUF BF16**, with Q8 as the default
package. Selecting any of them must leave `kitten_tts2.weight_type` unset unless
the user explicitly supplied an override. Regenerate the frontend bundle before
building the server after changing these catalog entries:
```sh
npm --prefix webui/native ci
npm --prefix webui/native run build
cmake --build build-kitten2 --target audiocpp_server
```
Replace `build-kitten2` with the configured server build directory. CMake embeds
the generated `webui/native/dist/index.html` already on disk and does not invoke
the frontend build.
Offline checks require NumPy, PyTorch and safetensors:
```sh
python -m unittest discover -s tests/kitten_tts2 -p 'test_*.py'
python tests/kitten_tts2/check_updated_weights.py \
--model /path/to/updated-kitten-tts-2 --output updated-weights.json
python tests/kitten_tts2/check_hybrid_gguf.py \
--model /path/to/updated-kitten-tts-2 --gguf /path/to/kitten-tts2-q4-multilingual.gguf \
--output hybrid-tensors.json
```
The source check requires all 196 body matrices to match the full BF16 values
before and after standard Q8_0/Q4_0 packing. The hybrid package check verifies
every LM tensor's stored values, a Q8_0 embedding, and embedding relative L2
below 0.5% against full BF16, both overall and on speech-token rows. Other dense
LM tensors must remain exact. This does not imply identical generated audio
across quantizations or backends.
### Default decoder
The published GGUF is sufficient for native preset inference and, with a user
reference clip/transcript, cloning. The developer tests below additionally use:
- **Session cloning checks:** the upstream `voices/voices.json` index and its
Bruno/Bella reference WAVs. Without the optional reference-model argument,
the session probe runs only the preset and invalid-voice checks.
- **Component parity:** `speaker/model.safetensors`, the LM speaker-projection
weights, `native/s3gen_meanflow.safetensors`, `cpp/default/voices.json`, and
the upstream **`cpp/default/decoder.pt`** TorchScript export. That export is
a Python comparison reference only; the native decoder does not load it.
- **Multilingual checks:** the original voice index, referenced WAV/NPZ files,
and a separate complete prepared voice JSON saved during conversion as shown
below.
Follow the model guide for the additional S3 checkpoint. The validated upstream
snapshot/revisions are recorded in [validation.md](validation.md); component
graph extraction relies on the matching default `decoder.pt` export.
Python component comparisons use NumPy, SoundFile, PyTorch, and safetensors.
These are validation-only dependencies.
## Session regression
```sh
build-kitten2/bin/kitten_tts2_session_probe \
models/kitten-tts2-v2/kitten-tts2-q8-v2-multilingual.gguf build-kitten2/native-session \
8 native /absolute/path/kitten-tts-2 cpu > build-kitten2/session.log 2>&1
```
One session checks exact seeded repeats, voice switching, three-chunk synthesis,
unknown voice rejection, cloning from Bruno/Bella WAVs, cloned-voice cached
repeats, reference changes, and missing-transcript/short-clip rejection.
The optional reference model directory supplies WAVs/transcripts; inference
weights come from the first argument. A final `cpu` or `cuda` argument selects
the backend (default: `cpu`). Output WAVs are float32, mono, 24 kHz.
Reported RTF and the framework's `session.wall_ms` cover the entire `run()` call,
including reference conditioning and first-clone lazy encoder loading. Initial
model/session construction is outside this timer.
The production model has no custom tensor-dump environment variable or hooks.
Normal framework timing/profiling remains available. `check_parity.py` is retained
only for comparing archived prompt/logit traces from the original port; it cannot
capture fresh traces from this runtime. Those historical comparisons additionally
require Transformers and the full upstream LM weights/tokenizer/configuration.
## Native components
For controlled **CUDA parity**, disable TF32 before launching the component
probe. Setting it only for the later Python comparison cannot change captured
tensors. This is a test setting; ordinary synthesis uses the default backend
precision policy.
```sh
export NVIDIA_TF32_OVERRIDE=0
```
```powershell
$env:NVIDIA_TF32_OVERRIDE = "0"
```
```sh
build-kitten2/bin/kitten_tts2_components_probe \
/absolute/path/kitten-tts-2/native/s3gen_meanflow.safetensors \
/absolute/path/kitten-tts-2/cpp/default/voices.json \
tests/kitten_tts2/component_codes.json \
build-kitten2/native-components cpu /absolute/path/kitten-tts-2
python tests/kitten_tts2/check_native_components.py \
--model /absolute/path/kitten-tts-2 --upstream /absolute/path/KittenTTS \
--speaker-output build-kitten2/native-components \
--decoder-output build-kitten2/native-components \
--codes tests/kitten_tts2/component_codes.json
```
The optional reference-model directory makes the test-only probe exercise
the public speaker API with Bruno's reference WAV. It writes the resampled
input with the framework WAV writer and embedding/projection vectors as JSON.
The script checks XVectorSincNet using that exact input, then the BF16 speaker
projection independently. The fixed 72-token fixture was captured from a seeded
Bruno request during the original port; both decoder implementations receive
the same fixture plus the usual three lookahead tokens.
The script compares encoder hidden states and two-step
meanflow mel with the published decoder's Gaussian draws fixed to zero.
Finally, it supplies identical mel and zero random draws to HiFT and checks
pitch and waveform. The graph extraction rejects incompatible exports.
Replace `cpu` with `cuda` in the component probe command to check NVIDIA execution. Use the
same numerical comparison limits on CPU and CUDA, with TF32 disabled for the
controlled CUDA run as described above.
The encoder comparison fails with the original relative-shift padding order.
The shift fix alone passes its tolerance; using the upstream LayerNorm epsilon
further reduces the error (see the ablation in [PR #778](https://github.com/0xShug0/audio.cpp/pull/778)).
Max-error limits are 0.00005 for speaker identity, 0.0001 for encoder hidden
states, 0.005 for mel, 0.032 for BF16 projection, and 0.01 for pitch/waveform.
## Server and dependencies
Run ordinary synthesis/server checks without the parity override, in a fresh
shell or after `unset NVIDIA_TF32_OVERRIDE` (POSIX) /
`Remove-Item Env:NVIDIA_TF32_OVERRIDE -ErrorAction SilentlyContinue` (PowerShell).
Register the GGUF as `kitten_tts2`, task `tts`, mode `offline`.
POST to `/v1/audio/speech` with a preset `voice` or reference audio:
```json
{
"model": "kitten-tts2",
"input": "Hello from native voice cloning.",
"voice_ref": {"type": "path", "path": "/absolute/path/reference.wav"},
"reference_text": "The words spoken in that recording.",
"seed": 1234
}
```
Inspect executable imports (`dumpbin /dependents` on Windows) to verify no
Torch/Python/ONNX DLL. Inspect the GGUF for its three tensor namespaces,
license/NOTICE sidecars, and absence of TorchScript resources.
CPU and NVIDIA CUDA are tested backends. Student decoders, streaming, exhaustive
testing of every English voice, and automatic transcript generation are outside
the implemented/validated scope.
Numerical checks do not measure intelligibility or speaker similarity;
listen to generated samples as well.
## Multilingual presets
Build `audiocpp_kitten_tts2_prepare_voices` alongside the converter. If you already
saved the complete prepared index during packaging, pass its path to `--voices`
below. Otherwise, create a local GGUF and retain its index with:
```sh
python tools/community_models/prepare_kitten_tts2_gguf.py \
--model /absolute/path/kitten-tts-2 \
--converter build-kitten2/bin/audiocpp_gguf --type q8_0 \
--output build-kitten2/kitten-tts2-q8-v2-multilingual.gguf \
--voices-output build-kitten2/kitten-tts2-multilingual-voices.json
```
Use the updated upstream assets, including both `lm/model.safetensors` and
`lm/model-ternary.safetensors`. The helper completes the voice index from WAV/NPZ
assets, refreshes preset speaker projections with the updated full LM, and
rejects a package missing any registered preset. The following test uses that
local GGUF; substitute the downloaded GGUF path to validate the
published package with the same complete index.
```sh
python tests/kitten_tts2/check_multilingual.py \
--server build-kitten2/bin/audiocpp_server \
--model build-kitten2/kitten-tts2-q8-v2-multilingual.gguf \
--reference-model /absolute/path/kitten-tts-2 \
--voices build-kitten2/kitten-tts2-multilingual-voices.json \
--output build-kitten2/multilingual-validation --backend cpu
```
Use `--backend cuda` and the CUDA server to repeat on NVIDIA. This starts and
stops a temporary localhost server. NumPy and SoundFile are used only by the test.
It checks all nine language presets plus Bruno, 48 registered voices, exact
prepared reference tokens/transcripts against upstream assets, finite non-silent
24 kHz output, Chinese chunking, and German/Chinese cloning. WAVs and a JSON
report remain in the output directory. Without runtime dump hooks this test
does not inspect internal BPE IDs, logits, or generated token counts. These are
execution checks, not an ASR or native-speaker pronunciation assessment.