Repository navigation
libelizainference ABI 21: caller-set speed range per Paradee voice slot - #92
Merged
Merged
Conversation
Synthesis on a Paradee voice slot clamps speed to the GGUF's paradee.validated_speed ([0.85, 1.15] for Delibes-8M-esES). A product that chooses to speak outside that envelope had no way to do so short of reconverting the model with a different range, which changes the GGUF hash every consumer pins. Add eliza_inference_paradee_set_voice_speed_range(ctx, voice_id, min, max, &err): a runtime override of the slot's clamp, within the architecture's [0.25, 4] and spanning 1.0; 0, 0 restores the validated range. It belongs to the slot (kept across mmap_evict -> reload and a new load_voice, dropped by unload_voice) and does not load the model. paradee_voice_info adds speed_range next to the unchanged validated_speed. The GGUF, its keys and the converter are untouched. One additive symbol; ABI 20 -> 21 per the header's convention. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lalalune
added a commit
to elizaOS/eliza
that referenced
this pull request
Nov 1, 2026
…inference ABI 21) (#38470) * feat(voice): caller-set speed range for Paradee voice slots (ABI 21) libelizainference clamps a Paradee-family synthesis to the GGUF's paradee.validated_speed (Delibes-8M-esES: 0.85-1.15). elizaOS/llama.cpp#92 adds eliza_inference_paradee_set_voice_speed_range, a runtime override per voice slot that leaves the GGUF and its hash unchanged. Bind it: - move native/llama.cpp to the #92 head (ABI 21); - elizavoice-jni registers nativeParadeeSetVoiceSpeedRange (needs ABI 21) on both VoiceNative classes; - ParadeeVoice.speedRange(min, max) / validatedSpeedRange(), checked in Java against 0.25 <= min <= 1 <= max <= 4 before reaching native; - ffi-bindings.ts: ABI 21, still accepting v20 (the binding does not call the new symbol); ffi-stub/ffi.h re-copied from the pinned header; - stream-contract covers the new call and its refusals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(voice): pin merged llama.cpp speed-range ABI --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Why
libelizainference clamps every Paradee-family synthesis to the GGUF's
paradee.validated_speed(Delibes-8M-esES:[0.85, 1.15], written byconvert_paradee_onnx_to_gguf.py). Grace's owner widened its Spanish speech rate to 0.5x–1.5x (owner decision OCT31-14); Grace already asks for that rate, but the library holds it to 0.85–1.15. Changing the converter's range would change the Delibes GGUF bytes and hash that elizainputs.json,pins.jsonand Grace'svoice.lock.jsonpin, and would misstate what the release validated. This adds a runtime override instead.What
eliza_inference_paradee_set_voice_speed_range(ctx, voice_id, min_speed, max_speed, &err):speedto;0.25 <= min <= 1 <= max <= 4(the architecture's limits, the same bounds the GGUF loader enforces onvalidated_speed);0, 0restores the model's validated range; anything else, or a slot never loaded, isELIZA_ERR_INVALID_ARGand leaves the range unchanged;mmap_evict("tts")→ reload and across a newload_voiceinto the slot, dropped byunload_voice; does not load the model. Slot""is the v17 voice.paradee_voice_infoaddsspeed_range(in force) next to the unchangedvalidated_speed(the model's).tools/paradee/README.mdupdated.pins.jsonand the converter are untouched: no model hash changes.Tests
tests/ffi-paradee-asr.cpp(contract doubles, no weights): argument refusals (below 0.25, above 4, not spanning 1, reversed, NaN, ∞,0, x, unknown slot, null ctx/id), info JSON for both slots, the clamp it sets (0.3/2.0 → 0.5/1.5, values inside pass through), lifetime across evict → reload, setting on an evicted slot without loading it,0, 0reset back to 0.85/1.15, a new load keeping the range, unload dropping it. ABI string "21".tests/ffi-abi.c: ABI "21"; the new symbol refuses before any load (NOT_IMPLEMENTED without Paradee).Run locally (macOS arm64, the
eliza-paradee-stream.ymlconfigure):ctest -R 'eliza-inference-test-(paradee-(asr|stream-output)|abi)$'→ 3/3 passed (paradee-asr: 668 checks, 0 failures). Not run: real-model synthesis at the widened rate, Android cross-build, any listening test. Speech outside 0.85–1.15 was not validated by the Delibes release; a caller that sets a wider range owns that choice.Follow-up
elizaOS/eliza: bind it in the Android voice bridge (
ParadeeVoice.speedRange), accept ABI 21 inffi-bindings.ts, and move the submodule here once this merges.🤖 Generated with Claude Code