Files
rustytorch/crates/models/rtx-csm/src/hub.rs
T
osobhandClaude Opus 4.7 a5cedfb46a rtx-csm: emotional_speech_guide — CREMA-D vs RAVDESS firdhokk verdict
8-gen bench (4 emotions × 2 corpora) at seed=42 against firdhokk
Whisper-LV3:

  target    RAVDESS              CREMA-D
  happy     happy (0.999) ✓      happy (0.999) ✓
  angry     neutral (0.92)       sad (0.99)
  fearful   happy (0.998)        fearful (0.984) ✓
  sad       angry (0.99)         fearful (0.99)

CREMA-D 2/4 vs RAVDESS 1/4. Larger / more naturalistic corpus
produces more class-pure fearful direction. Neither corpus solves
angry or sad — recipe shifts into 'vague expressivity' rather than
class-specific corners.

Practical: prefer CREMA-D when available; A/B both per emotion if
class precision matters.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-30 00:01:02 -07:00

107 lines
3.8 KiB
Rust

//! HuggingFace Hub asset resolution.
//!
//! Resolves the three weight artifacts CSM needs:
//! - sesame/csm-1b: model.safetensors (CSM dual-Llama weights)
//! - kyutai/mimi: model.safetensors (Mimi codec weights)
//! - meta-llama/Llama-3.2-1B: tokenizer.json (BPE vocab)
//!
//! Llama tokenizer requires HF token acceptance; document via `HF_TOKEN` env var.
use crate::error::Result;
use hf_hub::api::sync::Api;
use std::path::PathBuf;
pub const REPO_CSM_1B: &str = "sesame/csm-1b";
pub const REPO_MIMI: &str = "kyutai/mimi";
pub const REPO_LLAMA_TOKENIZER: &str = "meta-llama/Llama-3.2-1B";
/// Public mirror — tokenizer.json is byte-identical to meta-llama's. Used as
/// fallback when the user hasn't been approved on Meta's gated form yet.
pub const REPO_LLAMA_TOKENIZER_FALLBACK: &str = "unsloth/Llama-3.2-1B";
/// AudioSeal watermark — public, no auth required.
pub const REPO_AUDIOSEAL: &str = "facebook/audioseal";
pub const FILE_AUDIOSEAL_GENERATOR: &str = "generator_base.pth";
pub const FILE_AUDIOSEAL_DETECTOR: &str = "detector_base.pth";
/// WavLM-Base+ Speaker Verification (X-vector head). Public, no auth.
pub const REPO_WAVLM_SV: &str = "microsoft/wavlm-base-plus-sv";
pub const FILE_WAVLM_SV_PT: &str = "pytorch_model.bin";
#[derive(Debug, Clone)]
pub struct CsmAssets {
pub csm_weights: PathBuf,
pub mimi_weights: PathBuf,
pub tokenizer_json: PathBuf,
}
/// Resolve all three CSM-1B assets. Requires HF auth for `sesame/csm-1b` and
/// `meta-llama/Llama-3.2-1B`. Use `resolve_mimi()` alone if you only need the
/// codec (it's public).
pub fn resolve_csm_1b() -> Result<CsmAssets> {
let csm_weights = resolve_csm_weights()?;
let mimi_weights = resolve_mimi()?;
let tokenizer_json = resolve_llama_tokenizer()?;
Ok(CsmAssets {
csm_weights,
mimi_weights,
tokenizer_json,
})
}
/// Download `sesame/csm-1b/model.safetensors`. Requires HF auth + accepted repo terms.
pub fn resolve_csm_weights() -> Result<PathBuf> {
let api = Api::new()?;
Ok(api
.model(REPO_CSM_1B.to_string())
.get("model.safetensors")?)
}
/// Download `kyutai/mimi/model.safetensors`. Public, no auth required.
pub fn resolve_mimi() -> Result<PathBuf> {
let api = Api::new()?;
Ok(api.model(REPO_MIMI.to_string()).get("model.safetensors")?)
}
/// Download `facebook/audioseal/generator_base.pth`. Public, no auth required.
pub fn resolve_audioseal_generator() -> Result<PathBuf> {
let api = Api::new()?;
Ok(api
.model(REPO_AUDIOSEAL.to_string())
.get(FILE_AUDIOSEAL_GENERATOR)?)
}
/// Download `facebook/audioseal/detector_base.pth`. Public, no auth required.
pub fn resolve_audioseal_detector() -> Result<PathBuf> {
let api = Api::new()?;
Ok(api
.model(REPO_AUDIOSEAL.to_string())
.get(FILE_AUDIOSEAL_DETECTOR)?)
}
/// Download `microsoft/wavlm-base-plus-sv/pytorch_model.bin`. Public, no auth.
pub fn resolve_wavlm_sv() -> Result<PathBuf> {
let api = Api::new()?;
Ok(api.model(REPO_WAVLM_SV.to_string()).get(FILE_WAVLM_SV_PT)?)
}
/// Download Llama-3.2-1B `tokenizer.json`.
///
/// Tries the canonical `meta-llama/Llama-3.2-1B` first; on 403 (terms not
/// accepted) falls back to the public `unsloth/Llama-3.2-1B` mirror, which
/// hosts a byte-identical tokenizer.json.
pub fn resolve_llama_tokenizer() -> Result<PathBuf> {
let api = Api::new()?;
match api
.model(REPO_LLAMA_TOKENIZER.to_string())
.get("tokenizer.json")
{
Ok(p) => Ok(p),
Err(e) => {
tracing::warn!(
"{REPO_LLAMA_TOKENIZER} tokenizer fetch failed ({e}); falling back to {REPO_LLAMA_TOKENIZER_FALLBACK}"
);
Ok(api
.model(REPO_LLAMA_TOKENIZER_FALLBACK.to_string())
.get("tokenizer.json")?)
}
}
}