===============================================
N I N E N I N E S I X πΌ
===============================================
/\_/\
( -.- )ββββ
> ^ < β
===============================================
This is a complete, production-ready workflow for finetuning LFM2-based text-to-speech models (like KaniTTS) with NeMo NanoCodec on your own speakers and languages.
IMPORTANT: This pipeline requires a dataset tokenized with NeMo NanoCodec.
If you don't have a tokenized dataset yet, prepare it using our dataset processing pipeline: NanoCodec Dataset Pipeline
The dataset pipeline will:
# Clone the repository
git clone https://github.com/your-org/KaniTTS-Finetune-pipeline
cd KaniTTS-Finetune-pipeline
# Run setup (this will take 10-15 minutes, perfect time for a coffee break! β)
make setup
The setup script will:
make login
This will authenticate you with:
Edit the configuration files (detailed explanation below):
config/dataset_config.yaml - Your training datasetsconfig/experiments.yaml - Hyperparameters for your experimentsmake train
Training can take several hours depending on your dataset size and GPU.
make eval
This will generate audio samples for all your trained models and upload them to HuggingFace Hub for comparison.
This pipeline uses YAML configuration files.
config/dataset_config.yaml)This file tells the pipeline where to find your training data and how to process it.
max_duration_sec: 12 # Maximum audio duration in seconds
hf_datasets:
- reponame: "your-username/your-dataset-repo"
name: null # Subset name (use null if no subsets)
split: "train"
text_col_name: text # Column containing transcriptions
nano_layer_1: nano_layer_1 # codec layer 1
nano_layer_2: nano_layer_2 # codec layer 2
nano_layer_3: nano_layer_3 # codec layer 3
nano_layer_4: nano_layer_4 # codec layer 4
encoded_len: encoded_len # Audio length in frames
speaker_id: "alice" # OPTIONAL: speaker identifier May be `null` if you want to tune no support speaker_id model
max_len: 10000 # OPTIONAL: limit number of samples
Required Fields:
reponame: Your HuggingFace dataset repository (must be tokenized with NanoCodec)text_col_name: Column name containing text transcriptionsnano_layer_1/2/3/4: Column names for the 4 codec layersencoded_len: Column with audio length in codec framesOptional Fields:
speaker_id (HIGHLY RECOMMENDED for multi-speaker datasets):
"alice: Hello world")speaker_id: "alice"max_len:
categorical_filter:
categorical_filter:
column_name: "speaker"
value: "speaker_001"
column_name == valueWhen you run training, the dataset processor:
max_duration_sec)max_len is setThe processing uses multiprocessing for speed, automatically detecting your CPU count.
max_duration_sec: 12
hf_datasets:
- reponame: "my-username/alice-voice-nano"
name: null
split: "train"
text_col_name: text
nano_layer_1: nano_layer_1
nano_layer_2: nano_layer_2
nano_layer_3: nano_layer_3
nano_layer_4: nano_layer_4
encoded_len: encoded_len
speaker_id: "alice"
max_duration_sec: 12
hf_datasets:
# Alice's voice
- reponame: "my-username/alice-voice-nano"
name: null
split: "train"
text_col_name: text
nano_layer_1: nano_layer_1
nano_layer_2: nano_layer_2
nano_layer_3: nano_layer_3
nano_layer_4: nano_layer_4
encoded_len: encoded_len
speaker_id: "alice"
max_len: 5000
# Bob's voice
- reponame: "my-username/bob-voice-nano"
name: null
split: "train"
text_col_name: text
nano_layer_1: nano_layer_1
nano_layer_2: nano_layer_2
nano_layer_3: nano_layer_3
nano_layer_4: nano_layer_4
encoded_len: encoded_len
speaker_id: "bob"
max_len: 5000
Key Point: Notice each dataset has a different
speaker_id. This is crucial for the model to learn to distinguish between speakers!
config/experiments.yaml)This file defines your training experiments. You can run multiple experiments with different hyperparameters in a single training run.
base_model: "nineninesix/kani-tts-450m-0.2-pt"
project_name: "my-tts-experiments"
experiments:
- base:
model_id: "alice-tts-v1-lora16"
run_name: "alice-experiment-001"
desc: "Standard LoRA rank 16"
lora_args:
r: 16
lora_alpha: 16
lora_dropout: 0.1
target_modules: [q_proj, v_proj, w1, w2, w3]
bias: "none"
task_type: CAUSAL_LM
use_rslora: true
trainer_args:
num_train_epochs: 2
per_device_train_batch_size: 1
gradient_accumulation_steps: 4
learning_rate: 5e-5
lr_scheduler_type: cosine
warmup_ratio: 0.1
LoRA (Low-Rank Adaptation) is a technique that lets you finetune large models efficiently:
This pipeline is designed specifically for LFM2-based models like KaniTTS.
r (rank): Controls the size of adapter matrices
lora_alpha (scaling factor): Usually set equal to r
rlora_dropout: Regularization to prevent overfitting
target_modules: Which parts of the model to finetune
Available modules and what they do:
q_proj, k_proj, v_proj: Attention query/key/value (core attention mechanism)out_proj: Attention output projectionw1, w2, w3: Feed-forward network layers (most of the model's capacity)in_proj: Input projection (less commonly used)Common patterns:
# Minimal (fastest, good for testing)
target_modules: [q_proj, v_proj]
# Balanced (recommended for most cases)
target_modules: [q_proj, v_proj, w1, w2, w3]
# Comprehensive (best quality, slower)
target_modules: [q_proj, k_proj, v_proj, out_proj, w1, w2, w3]
# Full (everything, highest quality)
target_modules: [q_proj, k_proj, v_proj, out_proj, w1, w2, w3, in_proj]
use_rslora: Improved LoRA variant
true (better training stability)num_train_epochs: How many times to go through the dataset
per_device_train_batch_size: Samples per GPU
gradient_accumulation_steps: Accumulate gradients before update
batch_size Γ accumulation_stepslearning_rate: How fast the model learns
lr_scheduler_type: Learning rate schedule
cosine (gradually decreases LR)linear, constantwarmup_ratio: Fraction of training for warmup
weight_decay: Regularization
optim: Optimizer
adamw_torch (standard choice)bf16: Use bfloat16 precision
true (faster, less memory, supported by modern GPUs like Blackwell)You can run many experiments in one go:
experiments:
# Experiment 1: Conservative
- base:
model_id: "alice-conservative"
run_name: "exp-conservative"
lora_args:
r: 8
target_modules: [q_proj, v_proj]
trainer_args:
learning_rate: 2e-5
num_train_epochs: 1
# Experiment 2: Balanced
- base:
model_id: "alice-balanced"
run_name: "exp-balanced"
lora_args:
r: 16
target_modules: [q_proj, v_proj, w1, w2, w3]
trainer_args:
learning_rate: 5e-5
num_train_epochs: 2
# Experiment 3: Aggressive
- base:
model_id: "alice-aggressive"
run_name: "exp-aggressive"
lora_args:
r: 32
target_modules: [q_proj, k_proj, v_proj, out_proj, w1, w2, w3]
trainer_args:
learning_rate: 5e-5
num_train_epochs: 3
The pipeline will:
./checkpoints/<model_id>You can then evaluate all of them and pick the best one. This is perfect for hyperparameter optimization with tools like Optuna.
The default base model is:
base_model: "nineninesix/kani-tts-400m-0.3-pt"
This model is pretrained on multiple languages:
Coming soon: More advanced versions with support for additional languages including French, Portuguese, and more.
config/eval_config.yaml & config/eval_set.yaml)paths:
audio_output_dir: "./audio_samples"
checkpoints_dir: "./checkpoints"
huggingface:
upload_dataset: true
repo_name: "your-username/tts-evaluation-results"
private: true
processing:
num_proc: 4
audio_output_dir: Where to save generated audio filescheckpoints_dir: Where your trained models are savedupload_dataset: Whether to upload results to HuggingFace Hubrepo_name: Your HuggingFace dataset repo for evaluation resultsprivate: Keep evaluation dataset privateThis file contains the prompts for evaluation:
eval_set:
- prompt_1: "alice: Hello, this is a test of the text to speech system."
- prompt_2: "alice: The quick brown fox jumps over the lazy dog."
- prompt_3: "alice: Machine learning is transforming the world of artificial intelligence."
When to include speaker ID:
alice:) if you trained with speaker_id in dataset configWhen you run make eval, the pipeline:
eval_set.yaml./checkpoints/experiment_id: Model identifiertrain_configuration: Complete hyperparameter config (!)sentence_id: Prompt identifiersentence: The text promptaudio: The generated audio fileOn HuggingFace Hub, you can:
This makes it easy to pick the best model or iterate on your experiments.
Defines the token space and codec settings. You usually don't need to modify this.
Controls inference behavior:
max_new_tokens: Maximum audio lengthtemperature: Sampling randomness (0.6 = balanced)top_p: Nucleus sampling thresholdrepetition_penalty: Discourage repetitionThis pipeline uses NeMo NanoCodec which compresses audio into discrete tokens:
The model learns to predict these codec tokens from text, then the codec reconstructs them into audio.
The model's vocabulary is extended beyond text:
Training sequences look like:
[start_of_human] <text_tokens> [end_of_text] [end_of_human]
[start_of_ai] [start_of_speech] <audio_tokens> [end_of_speech] [end_of_ai]
Dataset preprocessing uses multiprocessing:
n_shards_per_dataset parameterThis makes preprocessing fast even for large datasets!
The notebook is available in the notebooks/ directory, so you can run experiments without a local GPU.
# Validate configuration files
make test-config
# Clean cache files
make clean
# Upload a trained model to HuggingFace
make upload-model
# Show all available commands
make help
per_device_train_batch_size to 1gradient_accumulation_steps to maintain effective batch sizer: 8 instead of r: 16)max_duration_sec in dataset configdataset_config.yaml match your datasetmake test-config to validate config filesbase_model path is correct in experiments.yamlmake login)Need help or want to share your results?
Join our Discord to:
This pipeline is built on top of open-source projects:
This project is under Apache 2. See LICENSE file for details.
8 commits
2 commits
Jupyter Notebook
43.5%
Python
36.2%
Shell
12.6%
Makefile
7.7%
===============================================
N I N E N I N E S I X πΌ
===============================================
/\_/\
( -.- )ββββ
> ^ < β
===============================================
This is a complete, production-ready workflow for finetuning LFM2-based text-to-speech models (like KaniTTS) with NeMo NanoCodec on your own speakers and languages.
IMPORTANT: This pipeline requires a dataset tokenized with NeMo NanoCodec.
If you don't have a tokenized dataset yet, prepare it using our dataset processing pipeline: NanoCodec Dataset Pipeline
The dataset pipeline will:
# Clone the repository
git clone https://github.com/your-org/KaniTTS-Finetune-pipeline
cd KaniTTS-Finetune-pipeline
# Run setup (this will take 10-15 minutes, perfect time for a coffee break! β)
make setup
The setup script will:
make login
This will authenticate you with:
Edit the configuration files (detailed explanation below):
config/dataset_config.yaml - Your training datasetsconfig/experiments.yaml - Hyperparameters for your experimentsmake train
Training can take several hours depending on your dataset size and GPU.
make eval
This will generate audio samples for all your trained models and upload them to HuggingFace Hub for comparison.
This pipeline uses YAML configuration files.
config/dataset_config.yaml)This file tells the pipeline where to find your training data and how to process it.
max_duration_sec: 12 # Maximum audio duration in seconds
hf_datasets:
- reponame: "your-username/your-dataset-repo"
name: null # Subset name (use null if no subsets)
split: "train"
text_col_name: text # Column containing transcriptions
nano_layer_1: nano_layer_1 # codec layer 1
nano_layer_2: nano_layer_2 # codec layer 2
nano_layer_3: nano_layer_3 # codec layer 3
nano_layer_4: nano_layer_4 # codec layer 4
encoded_len: encoded_len # Audio length in frames
speaker_id: "alice" # OPTIONAL: speaker identifier May be `null` if you want to tune no support speaker_id model
max_len: 10000 # OPTIONAL: limit number of samples
Required Fields:
reponame: Your HuggingFace dataset repository (must be tokenized with NanoCodec)text_col_name: Column name containing text transcriptionsnano_layer_1/2/3/4: Column names for the 4 codec layersencoded_len: Column with audio length in codec framesOptional Fields:
speaker_id (HIGHLY RECOMMENDED for multi-speaker datasets):
"alice: Hello world")speaker_id: "alice"max_len:
categorical_filter:
categorical_filter:
column_name: "speaker"
value: "speaker_001"
column_name == valueWhen you run training, the dataset processor:
max_duration_sec)max_len is setThe processing uses multiprocessing for speed, automatically detecting your CPU count.
max_duration_sec: 12
hf_datasets:
- reponame: "my-username/alice-voice-nano"
name: null
split: "train"
text_col_name: text
nano_layer_1: nano_layer_1
nano_layer_2: nano_layer_2
nano_layer_3: nano_layer_3
nano_layer_4: nano_layer_4
encoded_len: encoded_len
speaker_id: "alice"
max_duration_sec: 12
hf_datasets:
# Alice's voice
- reponame: "my-username/alice-voice-nano"
name: null
split: "train"
text_col_name: text
nano_layer_1: nano_layer_1
nano_layer_2: nano_layer_2
nano_layer_3: nano_layer_3
nano_layer_4: nano_layer_4
encoded_len: encoded_len
speaker_id: "alice"
max_len: 5000
# Bob's voice
- reponame: "my-username/bob-voice-nano"
name: null
split: "train"
text_col_name: text
nano_layer_1: nano_layer_1
nano_layer_2: nano_layer_2
nano_layer_3: nano_layer_3
nano_layer_4: nano_layer_4
encoded_len: encoded_len
speaker_id: "bob"
max_len: 5000
Key Point: Notice each dataset has a different
speaker_id. This is crucial for the model to learn to distinguish between speakers!
config/experiments.yaml)This file defines your training experiments. You can run multiple experiments with different hyperparameters in a single training run.
base_model: "nineninesix/kani-tts-450m-0.2-pt"
project_name: "my-tts-experiments"
experiments:
- base:
model_id: "alice-tts-v1-lora16"
run_name: "alice-experiment-001"
desc: "Standard LoRA rank 16"
lora_args:
r: 16
lora_alpha: 16
lora_dropout: 0.1
target_modules: [q_proj, v_proj, w1, w2, w3]
bias: "none"
task_type: CAUSAL_LM
use_rslora: true
trainer_args:
num_train_epochs: 2
per_device_train_batch_size: 1
gradient_accumulation_steps: 4
learning_rate: 5e-5
lr_scheduler_type: cosine
warmup_ratio: 0.1
LoRA (Low-Rank Adaptation) is a technique that lets you finetune large models efficiently:
This pipeline is designed specifically for LFM2-based models like KaniTTS.
r (rank): Controls the size of adapter matrices
lora_alpha (scaling factor): Usually set equal to r
rlora_dropout: Regularization to prevent overfitting
target_modules: Which parts of the model to finetune
Available modules and what they do:
q_proj, k_proj, v_proj: Attention query/key/value (core attention mechanism)out_proj: Attention output projectionw1, w2, w3: Feed-forward network layers (most of the model's capacity)in_proj: Input projection (less commonly used)Common patterns:
# Minimal (fastest, good for testing)
target_modules: [q_proj, v_proj]
# Balanced (recommended for most cases)
target_modules: [q_proj, v_proj, w1, w2, w3]
# Comprehensive (best quality, slower)
target_modules: [q_proj, k_proj, v_proj, out_proj, w1, w2, w3]
# Full (everything, highest quality)
target_modules: [q_proj, k_proj, v_proj, out_proj, w1, w2, w3, in_proj]
use_rslora: Improved LoRA variant
true (better training stability)num_train_epochs: How many times to go through the dataset
per_device_train_batch_size: Samples per GPU
gradient_accumulation_steps: Accumulate gradients before update
batch_size Γ accumulation_stepslearning_rate: How fast the model learns
lr_scheduler_type: Learning rate schedule
cosine (gradually decreases LR)linear, constantwarmup_ratio: Fraction of training for warmup
weight_decay: Regularization
optim: Optimizer
adamw_torch (standard choice)bf16: Use bfloat16 precision
true (faster, less memory, supported by modern GPUs like Blackwell)You can run many experiments in one go:
experiments:
# Experiment 1: Conservative
- base:
model_id: "alice-conservative"
run_name: "exp-conservative"
lora_args:
r: 8
target_modules: [q_proj, v_proj]
trainer_args:
learning_rate: 2e-5
num_train_epochs: 1
# Experiment 2: Balanced
- base:
model_id: "alice-balanced"
run_name: "exp-balanced"
lora_args:
r: 16
target_modules: [q_proj, v_proj, w1, w2, w3]
trainer_args:
learning_rate: 5e-5
num_train_epochs: 2
# Experiment 3: Aggressive
- base:
model_id: "alice-aggressive"
run_name: "exp-aggressive"
lora_args:
r: 32
target_modules: [q_proj, k_proj, v_proj, out_proj, w1, w2, w3]
trainer_args:
learning_rate: 5e-5
num_train_epochs: 3
The pipeline will:
./checkpoints/<model_id>You can then evaluate all of them and pick the best one. This is perfect for hyperparameter optimization with tools like Optuna.
The default base model is:
base_model: "nineninesix/kani-tts-400m-0.3-pt"
This model is pretrained on multiple languages:
Coming soon: More advanced versions with support for additional languages including French, Portuguese, and more.
config/eval_config.yaml & config/eval_set.yaml)paths:
audio_output_dir: "./audio_samples"
checkpoints_dir: "./checkpoints"
huggingface:
upload_dataset: true
repo_name: "your-username/tts-evaluation-results"
private: true
processing:
num_proc: 4
audio_output_dir: Where to save generated audio filescheckpoints_dir: Where your trained models are savedupload_dataset: Whether to upload results to HuggingFace Hubrepo_name: Your HuggingFace dataset repo for evaluation resultsprivate: Keep evaluation dataset privateThis file contains the prompts for evaluation:
eval_set:
- prompt_1: "alice: Hello, this is a test of the text to speech system."
- prompt_2: "alice: The quick brown fox jumps over the lazy dog."
- prompt_3: "alice: Machine learning is transforming the world of artificial intelligence."
When to include speaker ID:
alice:) if you trained with speaker_id in dataset configWhen you run make eval, the pipeline:
eval_set.yaml./checkpoints/experiment_id: Model identifiertrain_configuration: Complete hyperparameter config (!)sentence_id: Prompt identifiersentence: The text promptaudio: The generated audio fileOn HuggingFace Hub, you can:
This makes it easy to pick the best model or iterate on your experiments.
Defines the token space and codec settings. You usually don't need to modify this.
Controls inference behavior:
max_new_tokens: Maximum audio lengthtemperature: Sampling randomness (0.6 = balanced)top_p: Nucleus sampling thresholdrepetition_penalty: Discourage repetitionThis pipeline uses NeMo NanoCodec which compresses audio into discrete tokens:
The model learns to predict these codec tokens from text, then the codec reconstructs them into audio.
The model's vocabulary is extended beyond text:
Training sequences look like:
[start_of_human] <text_tokens> [end_of_text] [end_of_human]
[start_of_ai] [start_of_speech] <audio_tokens> [end_of_speech] [end_of_ai]
Dataset preprocessing uses multiprocessing:
n_shards_per_dataset parameterThis makes preprocessing fast even for large datasets!
The notebook is available in the notebooks/ directory, so you can run experiments without a local GPU.
# Validate configuration files
make test-config
# Clean cache files
make clean
# Upload a trained model to HuggingFace
make upload-model
# Show all available commands
make help
per_device_train_batch_size to 1gradient_accumulation_steps to maintain effective batch sizer: 8 instead of r: 16)max_duration_sec in dataset configdataset_config.yaml match your datasetmake test-config to validate config filesbase_model path is correct in experiments.yamlmake login)Need help or want to share your results?
Join our Discord to:
This pipeline is built on top of open-source projects:
This project is under Apache 2. See LICENSE file for details.
8 commits
2 commits
Jupyter Notebook
43.5%
Python
36.2%
Shell
12.6%
Makefile
7.7%