rtx-csm: Phase 13.7 — --lora support in tts_server
Closes the gap where converse_server (Phase 12.4) supported LoRA but the simpler HTTP-only tts_server didn't. Same flag set (--lora / --lora-rank / --lora-alpha / --extended-lora) and same apply_lora_adapter shared helper. Combines with --quantized-gguf (Phase 12.6) for Q8 + voice clone over plain HTTP. Verified end-to-end on Metal: tts_server --quantized-gguf … --lora … boots, injects LoRA into the quantized backbone (q=16 k=16 v=16 o=16 + MLP w1/w2/w3 = 224 tensors), listens. Single HTTP POST /v1/tts returned 200 OK with a 146KB 24kHz mono WAV. Lib suite 110/110. tts_server is now the simplest production deploy for a personalized voice: HTTP-only, no STT/LLM overhead, LoRA + Q8 + AudioSeal/SilentCipher + WavLM-SV all available behind one binary. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
@@ -92,6 +92,28 @@ struct Cli {
|
|||||||
/// /v1/speaker_embed and /v1/speaker_compare are enabled.
|
/// /v1/speaker_embed and /v1/speaker_compare are enabled.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
wavlm_sv: Option<PathBuf>,
|
wavlm_sv: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// LoRA voice adapter (safetensors, output of `lora_train` or
|
||||||
|
/// `lora_train_emotional`). Loaded into the backbone (FP or quantized
|
||||||
|
/// — combines with --quantized-gguf per Phase 12.6) before serving so
|
||||||
|
/// every TTS request uses the trained voice.
|
||||||
|
#[arg(long)]
|
||||||
|
lora: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// LoRA rank override. When omitted, auto-detected from the adapter's
|
||||||
|
/// embedded metadata (Phase 12.5); falls back to 8 for older adapters.
|
||||||
|
#[arg(long)]
|
||||||
|
lora_rank: Option<usize>,
|
||||||
|
|
||||||
|
/// LoRA alpha override. Auto-detected from metadata when omitted.
|
||||||
|
#[arg(long)]
|
||||||
|
lora_alpha: Option<f32>,
|
||||||
|
|
||||||
|
/// Force extended LoRA coverage (q+k+v+output_proj + MLP). Auto-
|
||||||
|
/// detected from metadata when omitted; setting it on a classic q+v
|
||||||
|
/// adapter just allocates extra unused B=0 slots.
|
||||||
|
#[arg(long, default_value_t = false)]
|
||||||
|
extended_lora: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_message(s: &str) -> Result<u16> {
|
fn parse_message(s: &str) -> Result<u16> {
|
||||||
@@ -484,6 +506,19 @@ async fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
tracing::info!("CSM-1B loaded");
|
tracing::info!("CSM-1B loaded");
|
||||||
|
|
||||||
|
// Optional LoRA adapter (Phase 12.4 + 12.5 self-describing metadata).
|
||||||
|
if let Some(lora_path) = cli.lora.as_ref() {
|
||||||
|
let extended_override = if cli.extended_lora { Some(true) } else { None };
|
||||||
|
rtx_csm::training::apply_lora_adapter(
|
||||||
|
&mut generator,
|
||||||
|
lora_path,
|
||||||
|
cli.lora_rank,
|
||||||
|
cli.lora_alpha,
|
||||||
|
extended_override,
|
||||||
|
&device,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Optional AudioSeal — install inline + keep a detector instance.
|
// Optional AudioSeal — install inline + keep a detector instance.
|
||||||
let audioseal_message = parse_message(&cli.audioseal_message)?;
|
let audioseal_message = parse_message(&cli.audioseal_message)?;
|
||||||
let audioseal_detector = if let (Some(g), Some(d)) = (
|
let audioseal_detector = if let (Some(g), Some(d)) = (
|
||||||
|
|||||||
Reference in New Issue
Block a user