Spaces:
Sleeping
Sleeping
File size: 6,750 Bytes
335196b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | import argparse
import os
import subprocess
import sys
import uuid
from pathlib import Path
PAUSE_FLAG = Path("/workspace/outputs/train_paused.flag")
WANDB_RUN_ID_FILE = Path("/workspace/outputs/wandb_run_id.txt")
DATASET_AUDIT_SCRIPT = Path("/workspace/scripts/pipeline/audit_dataset_integrity.py")
def _clear_pause_flag() -> None:
try:
if PAUSE_FLAG.exists():
PAUSE_FLAG.unlink()
print(f"[INFO] Cleared pause flag: {PAUSE_FLAG}")
except Exception as exc:
print(f"[WARNING] Failed to clear pause flag {PAUSE_FLAG}: {exc}")
def _wandb_credentials_present() -> bool:
if os.environ.get("WANDB_API_KEY", "").strip():
return True
try:
import wandb
return bool(getattr(getattr(wandb, "api", None), "api_key", None))
except Exception:
return False
def _ensure_wandb_run_id() -> str | None:
explicit = os.environ.get("WANDB_RUN_ID", "").strip()
if explicit:
return explicit
if not _wandb_credentials_present():
return None
try:
if WANDB_RUN_ID_FILE.exists():
persisted = WANDB_RUN_ID_FILE.read_text(encoding="utf-8").strip()
if persisted:
os.environ["WANDB_RUN_ID"] = persisted
return persisted
run_id = uuid.uuid4().hex[:8]
WANDB_RUN_ID_FILE.parent.mkdir(parents=True, exist_ok=True)
WANDB_RUN_ID_FILE.write_text(run_id + "\n", encoding="utf-8")
os.environ["WANDB_RUN_ID"] = run_id
print(f"[INFO] Using WANDB_RUN_ID={run_id} (persisted to {WANDB_RUN_ID_FILE})")
return run_id
except Exception as exc:
print(f"[WARNING] Failed to persist WANDB_RUN_ID: {exc}")
return None
def main() -> None:
parser = argparse.ArgumentParser(description="Launch training with WandB monitoring")
parser.add_argument("--project_name", required=True, help="Project name (e.g. cortazar_v2)")
parser.add_argument(
"--exp_name",
default=os.environ.get("EXP_NAME", "F5TTS_v1_Base"),
help="Experiment name (F5TTS_v1_Base, F5TTS_Base, E2TTS_Base)",
)
parser.add_argument("--epochs", type=int, default=2500, help="Training epochs")
parser.add_argument("--batch_size", type=int, default=1600, help="Batch size per GPU")
parser.add_argument(
"--base_model_path", default="F5-TTS/ckpts/base_models/model_last.pt", help="Base model to finetune from"
)
parser.add_argument(
"--tokenizer",
default="custom",
choices=["pinyin", "char", "custom"],
help="Tokenizer type",
)
parser.add_argument("--tokenizer_path", default=None, help="Path to tokenizer vocab (for custom)")
args = parser.parse_args()
print(f"--- Starting Core Training Pipeline for {args.project_name} ---")
_clear_pause_flag()
_ensure_wandb_run_id()
# Fail-fast: validate the prepared dataset before burning GPU hours.
skip_audit = os.environ.get("SKIP_DATA_AUDIT", "").strip().lower() in ("1", "true", "yes", "y", "on")
if not skip_audit and DATASET_AUDIT_SCRIPT.exists():
dataset_root = f"/workspace/F5-TTS/data/{args.project_name}_{args.tokenizer}"
speaker_report = os.environ.get(
"SPEAKER_REPORT_PATH",
"/workspace/dataset_prepared/speaker_prune_report.jsonl",
)
speaker_threshold = os.environ.get("SPEAKER_THRESHOLD", "0.35")
audit_cmd = [
"python",
str(DATASET_AUDIT_SCRIPT),
"--dataset_root",
dataset_root,
"--speaker_report",
speaker_report,
"--require_speaker_report",
"--speaker_threshold",
speaker_threshold,
"--forbid_audio_path_contains",
"SPEAKER_01",
]
print(f"[INFO] Running dataset audit: {' '.join(audit_cmd)}")
try:
subprocess.check_call(audit_cmd)
except subprocess.CalledProcessError as exc:
try:
PAUSE_FLAG.parent.mkdir(parents=True, exist_ok=True)
PAUSE_FLAG.write_text(
"paused_by=train.py\nreason=dataset_audit_failed\n"
f"dataset_root={dataset_root}\nexit_code={exc.returncode}\n",
encoding="utf-8",
)
print(f"[ERROR] Dataset audit failed; wrote pause flag: {PAUSE_FLAG}")
except Exception as pause_exc:
print(f"[WARNING] Failed to write pause flag after audit failure: {pause_exc}")
raise
elif not skip_audit:
print(f"[WARN] Dataset audit script not found: {DATASET_AUDIT_SCRIPT} (set SKIP_DATA_AUDIT=1 to silence)")
# Check Environment
if not _wandb_credentials_present():
print(
"[WARNING] W&B credentials not detected (WANDB_API_KEY empty and no wandb login). Logging will be disabled."
)
else:
print("[INFO] W&B credentials detected.")
tokenizer_path = args.tokenizer_path
if not tokenizer_path:
env_vocab = os.environ.get("TOKENIZER_PATH")
if env_vocab:
tokenizer_path = env_vocab
elif os.path.exists("/workspace/vocab_es.txt"):
tokenizer_path = "/workspace/vocab_es.txt"
else:
tokenizer_path = "F5-TTS/ckpts/base_models/vocab.txt"
cmd = [
"accelerate",
"launch",
"-m",
"f5_tts.train.finetune_cli",
# Finetuning Mode
"--finetune",
"--pretrain",
args.base_model_path,
# Identity
"--dataset_name",
args.project_name,
"--exp_name",
args.exp_name,
# Hyperparams
"--epochs",
str(args.epochs),
"--batch_size_per_gpu",
str(args.batch_size),
"--learning_rate",
"1e-5",
# Observability (CRITICAL for V2)
"--logger",
"wandb",
"--log_samples", # Enables the patched validation logic
"--save_per_updates",
"1000", # Validate every 1000 steps
"--last_per_updates",
"500", # Save 'last' checkpoint frequently
# Disk hygiene: keep only the last N checkpoints (multi-GB each). Override via KEEP_LAST_N_CHECKPOINTS.
"--keep_last_n_checkpoints",
os.environ.get("KEEP_LAST_N_CHECKPOINTS", "15"),
# Data/Tokenizer
"--tokenizer",
args.tokenizer,
"--tokenizer_path",
tokenizer_path,
]
print(f"Executing: {' '.join(cmd)}")
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError as e:
print(f"Training failed with exit code {e.returncode}")
sys.exit(e.returncode)
if __name__ == "__main__":
main()
|