ZONOS3-Mini / requests_schema.py
fffiloni's picture
Deploy ZONOS3 Mini ZeroGPU integration v0.1.0
6d1acb0 verified
Raw History Blame Contribute Delete
3.09 kB
"""Validate public inputs before reserving GPU time; no model imports."""
from dataclasses import dataclass
import json
import math
import secrets
from config import LANGUAGES, MAX_CHARS, MAX_SEED
class InputError(ValueError):
pass
@dataclass(frozen=True)
class SpeechRequest:
text: str
voice: str
language: str
source: str
seed: int
normalize: bool
temperature: float
top_p: float
top_k: int
repetition_penalty: float
rate: float | None
def number(value, label, low, high, *, integer=False):
if isinstance(value, bool):
raise InputError(f"{label} must be a number.")
try:
result = float(value)
except (TypeError, ValueError):
raise InputError(f"{label} must be a number.") from None
if not math.isfinite(result) or not low <= result <= high:
raise InputError(f"{label} must be between {low} and {high}.")
if integer and result != int(result):
raise InputError(f"{label} must be a whole number.")
return int(result) if integer else result
def validate(text, picker, source, seed, randomize, normalize, temperature, top_p, top_k,
repetition_penalty, rate, voice_names, clip_present, consent):
if not isinstance(text, str) or not text.strip():
raise InputError("Write something to say first.")
text = text.strip()
if len(text) > MAX_CHARS:
raise InputError(f"Use at most {MAX_CHARS} characters for one take.")
try:
data = json.loads(picker) if isinstance(picker, str) else picker
voice, language = data["voice"], data["language"]
except (ValueError, TypeError, KeyError):
raise InputError("Choose a voice and a text language.") from None
if not isinstance(language, str) or language not in LANGUAGES:
raise InputError("This text language is not supported by this runtime.")
if not isinstance(source, str) or source not in {"Preset", "Voice clip"}:
raise InputError("Choose Preset or Voice clip.")
if source == "Preset" and (not isinstance(voice, str) or voice not in voice_names):
raise InputError("Choose one of the available preset voices.")
if source == "Voice clip" and not clip_present:
raise InputError("Upload or record a reference voice first.")
if source == "Voice clip" and consent is not True:
raise InputError("Confirm that you have permission to use the reference voice.")
if not isinstance(randomize, bool) or not isinstance(normalize, bool):
raise InputError("Seed and normalization switches must be true or false.")
selected_seed = secrets.randbelow(MAX_SEED + 1) if randomize else number(seed, "Seed", 0, MAX_SEED, integer=True)
rate = number(rate, "Speaking rate", 0, 30)
return SpeechRequest(
text, voice, language, source, selected_seed, normalize,
number(temperature, "Temperature", .1, 1.5),
number(top_p, "Top-p", .1, 1), number(top_k, "Top-k", 1, 400, integer=True),
number(repetition_penalty, "Repetition penalty", 1, 4), rate if rate else None,
)