Skip to content

QVAC-24107 test[tts-ggml]: extend model-load consolidation pattern to supertonic + addon - #4036

Merged
GustavoA1604 merged 4 commits into
mainfrom
feat/QVAC-24107-consolidate-model-loads
Aug 25, 2026
Merged

QVAC-24107 test[tts-ggml]: extend model-load consolidation pattern to supertonic + addon#4036
GustavoA1604 merged 4 commits into
mainfrom
feat/QVAC-24107-consolidate-model-loads

Conversation

@Alok-Ranjan23

@Alok-Ranjan23 Alok-Ranjan23 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Extend the model-load consolidation pattern from PR #4013's CosyVoice3 pilot to two more integration test files. Two model.load() calls removed per CPU-heavy leg.

Closes QVAC-24107.

Prerequisite investigation (Phase 1a — done)

QVAC-24107 flagged speech-cpp reload() semantics as a prerequisite for deeper consolidation (Version B: 20–25 min/leg saving). Investigation result: reload() calls unload() + load() internally on every engine — the GGUF file is re-parsed each time. No parse-skip.

Per-engine table (from reading packages/tts-ggml/addon/src/model-interface/**/*.cpp):

Engine reload() exists? Skips GGUF parse?
Chatterbox Yes NO — unload+load
Supertonic Yes NO — unload+load
Parler Yes NO — unload+load
CosyVoice3 Yes NO — unload+load
Audio8 Yes NO — unload+load

Consequence: Version B (extended folds via reload transitions on chatterbox-speed, output-sample-rate, parler emotion/description) is disproved — a "1 load + 3 reloads" restructure would cost the same as 4 loads. Only Version A's deterministic folds ship here.

If someone wants the deeper win in future work, the path is speech-cpp-side: add a "swap sampling params without re-parsing GGUF" API, or a shared engine pool across process invocations. Out-of-scope for this test-side ticket.

Measured CI wall-time impact

Same-day comparison against the main baseline used in PR #4013 (workflow_dispatch run 32729043118) plus the merged PR #4013 CI (run 32774343662):

Leg Runner main #4013 (merged) This PR (#4036) Δ vs main
macos-26 darwin-arm64 (Metal) self-hosted 27m38s 25m08s 25m08s −2m30s
windows-2025 x64 (Vulkan) self-hosted 30m05s 27m47s 28m14s −1m51s
ubuntu-24.04 x64 (Vulkan) self-hosted 35m05s 29m54s 29m39s −5m26s
ubuntu-22.04 x64 (Vulkan) self-hosted 33m13s 29m59s 30m07s −3m06s
ubuntu-26.04 linux-x64 (CPU) github-hosted 43m09s 61m12s ⚠️ 37m34s −5m35s
ubuntu-24.04-arm linux-arm64 (CPU) github-hosted 51m10s 47m53s 45m56s −5m14s
macos-15-large darwin-x64 (CPU) github-hosted 72m21s 68m39s 66m24s −5m57s
Total 292m41s 290m32s 263m02s −29m39s

Read:

  • All 7 legs faster than main today. Consistent direction across every runner class — no flaky-runner outlier this time.
  • Slowest-leg wall-clock: 72m21s → 66m24s (−5m57s, ~8% cut). This is the compounded effect of QVAC-23853 test[tts-ggml]: simplify multilingual + lifecycle integration tests #4013's MTL/quant trim + the cosyvoice3 pilot + the two new folds in this PR.
  • CPU-heavy legs consistently −5 min each vs main — better than the ~1–2 min this PR alone predicted; the ubuntu-26.04 +18m spike on the pilot run was confirmed to be flaky-runner variance (this run landed cleanly at 37m34s, below main's 43m09s baseline).
  • Does NOT get any leg under 20 min. Matches the parent ticket's honest expectation. Structural changes (speech-cpp engine pool / GGUF-swap API) are the only path to a bigger win, and Phase 1a proved they're needed.

Changes

packages/tts-ggml/test/integration/supertonic.test.js (5 tests → 4)

  • Folded "aborting the run via signal rejects the response" into "basic synthesis returns ~44.1 kHz audio + stats". Both tests loaded Supertonic with identical construction (F1/en/CPU). Abort call runs AFTER the successful synth and MUST be last (the native cancel-teardown path — mid-flight cancel wedging macOS process exit — is intentionally NOT covered here; an already-aborted signal short-circuits before addon.runJob).
  • Coverage retained: exact same abort assertion runs against the same construction.

packages/tts-ggml/test/integration/addon.test.js (5 tests → 4)

  • Folded "streaming input + streaming PCM output (runStreaming + onUpdate)" into "English synthesis + optional WER verification". Both tests loaded Chatterbox with loadChatterboxTTS({modelDir, language:'en'}) — identical construction. Streaming block runs BEFORE the WER test's mid-body model.unload() (must not move).
  • Coverage retained: all 5 original streaming assertions (passed, sampleCount > 0, reportedSampleRate === 24000, streamChunkCount === phrases.length, per-chunk sentenceChunks match) run against the shared loaded model.

Investigations audited and NOT consolidated

Rationale mirrors PR #4013's "Investigations that did not ship":

  • Parler variant matrix (variant × quant — 5 entries) — each entry proves a distinct GGUF loads and synthesizes. Matrix is the point.
  • Parler emotion/description/seed variations — all use voice: Laura with per-test unique assertions; the "all-defaults" test omits voice AS its assertion. No safe fold.
  • LavaSR enhancer/denoiser combos (cosyvoice3-lavasr.test.js) — enhancer path, streamChunkTokens, outputSampleRate, denoiser presence are all load-time. Every load exercises a distinct native code path.
  • Chatterbox KV-cache GPU sweep — matrix on variant × kvCacheType × GPU is the coverage story.
  • Chatterbox speedspeed is validated at ChatterboxModel::validateConfig load time; the 4 loads are the test.
  • CosyVoice3 clone triplet — baked/zero-shot/cross-lingual each need different referenceAudio/promptText (load-time files).
  • Audio8 CPU vs Vulkan — different useGPU, includeEncoder, useModelDir — the whole point of the pair.
  • Chatterbox MTL sweep — already the target of PR QVAC-23853 test[tts-ggml]: simplify multilingual + lifecycle integration tests #4013's trim.

What did NOT change

  • No .github/workflows/** edits.
  • No package.json / CHANGELOG.md / README.md edits — test-only change.
  • No unit tests, benchmark tests, or non-touched integration tests changed.
  • No t.skip / .only / commented-out tests introduced. Zero test files deleted.

Test plan

  • CI runs on push with the run-desktop-addon-tests label: the seven-leg run-integration-tests matrix exercised the touched files. Same-day main baseline comparison above.
  • Local static checks: prettier --check and node --check on both files.
  • Coverage audit: every original assertion from the two folded tests still runs on the shared loaded model in its target test.

…h test

The standalone "aborting the run via signal rejects the response" test loaded
Supertonic with default construction (F1/en/CPU) and issued one already-aborted
run() to prove the AbortSignal plumbing rejects synchronously. The basic-synth
test uses the same construction and completes its own synth first — so the
abort call can piggyback on that loaded model without a second load.

The abort must be the LAST engine call on the shared instance (the header
comment on the original test warned native cancel-teardown wedges macOS
process exit; the already-aborted signal path short-circuits before
addon.runJob, so this is safe as long as no further synths follow it).

Coverage retained: exact same abort assertion runs against the same
construction. Only the extra model.load() is gone.

Follow-up to PR #4013's cosyvoice3 pilot pattern.
…h-WER test

The standalone "streaming input + streaming PCM output (runStreaming + onUpdate)"
test loaded Chatterbox with loadChatterboxTTS({modelDir, language:'en'}) and
called runChatterboxStreaming on 3 phrases. The English-WER test loads the
identical construction and iterates English sentences via runChatterboxTTS —
same instance can serve both.

The streaming block is inserted BEFORE the WER test's model.unload() (line
after the sentence-loop, before whisper is loaded). Its 3-phrase run adds
~15-20s per leg; the target test's timeout is 30 min so ample headroom.

Coverage retained: all original streaming assertions (passed, sampleCount > 0,
reportedSampleRate === 24000, streamChunkCount === phrases.length,
sentenceChunks match) run against the shared loaded model.

Follow-up to PR #4013's cosyvoice3 pilot pattern. 5 → 4 tests, one
model.load() removed per CPU-heavy leg.
@Alok-Ranjan23
Alok-Ranjan23 requested review from a team as code owners August 25, 2026 07:03
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review Status

Current Status: ✅ APPROVED
Approvals so far: Team Lead: 1, Member: 1

@Alok-Ranjan23 Alok-Ranjan23 added the run-desktop-addon-tests CI: run desktop integration tests (requires verified) label Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

License compliance — clean

No new dependency license findings in this PR.

Warn-only (shadow) mode — this check does not block merges yet.

Updated automatically by the canonical license compliance workflow.

NOTICE presence (advisory)

Missing NOTICE (advisory, does not block):

  • ./.github/actions/release-merge-guard
  • ./docs/website
  • ./packages/ggml-coload-smoke
  • ./packages/fabric/test/integration
  • ./packages/inference-addon-cpp/mobile
  • ./packages/sdk/e2e
  • ./packages/llm-llamacpp/benchmarks/performance
  • ./packages/llm-llamacpp/benchmarks/server
  • ./packages/vla-ggml/sim/server
  • ./packages/embed-llamacpp/benchmarks/performance
  • ./packages/embed-llamacpp/benchmarks/server
  • ./packages/asr-ggml/benchmarks/server

@GustavoA1604
GustavoA1604 merged commit a0d39f3 into main Aug 25, 2026
49 checks passed
@GustavoA1604
GustavoA1604 deleted the feat/QVAC-24107-consolidate-model-loads branch August 25, 2026 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-desktop-addon-tests CI: run desktop integration tests (requires verified)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants