Spaces:
Sleeping
Sleeping
Add SmartTurn model selector
Browse files
app.py
CHANGED
|
@@ -35,6 +35,22 @@ DEFAULT_PVAD_ONNX = MODELS / "pvad_core.onnx"
|
|
| 35 |
DEFAULT_PVAD_H256_ONNX = MODELS / "pvad_core_h256.onnx"
|
| 36 |
DEFAULT_SILERO_JIT = MODELS / "silero_vad.jit"
|
| 37 |
DEFAULT_SMARTTURN_ONNX = MODELS / "smartturn-v3.1.onnx"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
DUALTURN_MODEL_ID = "anyreach-ai/dualturn-qwen2.5-mimi-0.5B"
|
| 39 |
DEFAULT_DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 40 |
|
|
@@ -69,6 +85,10 @@ def default_audio_value(path: Path) -> str | None:
|
|
| 69 |
return str(path) if path.exists() else None
|
| 70 |
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
def write_wav(path: Path, audio: np.ndarray, sample_rate: int = 16000) -> str:
|
| 73 |
path.parent.mkdir(parents=True, exist_ok=True)
|
| 74 |
sf.write(str(path), np.asarray(audio, dtype=np.float32), sample_rate)
|
|
@@ -76,12 +96,13 @@ def write_wav(path: Path, audio: np.ndarray, sample_rate: int = 16000) -> str:
|
|
| 76 |
|
| 77 |
|
| 78 |
def make_ort_session(path: str | Path) -> ort.InferenceSession:
|
|
|
|
| 79 |
opts = ort.SessionOptions()
|
| 80 |
opts.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
|
| 81 |
opts.intra_op_num_threads = 1
|
| 82 |
opts.inter_op_num_threads = 1
|
| 83 |
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
|
| 84 |
-
return ort.InferenceSession(
|
| 85 |
|
| 86 |
|
| 87 |
def frame_audio(audio: np.ndarray, frame_size: int = 512) -> np.ndarray:
|
|
@@ -327,6 +348,7 @@ def run_pipeline(
|
|
| 327 |
smartturn_threshold: float,
|
| 328 |
pvad_threshold: float,
|
| 329 |
pvad_model_path: str,
|
|
|
|
| 330 |
min_active_target_ms: float,
|
| 331 |
silence_fallback_ms: float,
|
| 332 |
asr_cut_silence_ms: float,
|
|
@@ -342,7 +364,7 @@ def run_pipeline(
|
|
| 342 |
assistant = assistant[: int(round(assistant_max_playback_sec * 16000))]
|
| 343 |
|
| 344 |
pvad = PvadOnnx(pvad_model_path, DEFAULT_SILERO_JIT)
|
| 345 |
-
smartturn = SmartTurnOnnx(
|
| 346 |
dualturn = DualTurnHF(DUALTURN_MODEL_ID, device)
|
| 347 |
|
| 348 |
pvad_probs = pvad.predict_target_probs(mic, enroll)
|
|
@@ -645,6 +667,7 @@ def run_gradio(
|
|
| 645 |
smartturn_threshold: float,
|
| 646 |
pvad_threshold: float,
|
| 647 |
pvad_model_path: str,
|
|
|
|
| 648 |
min_active_target_ms: float,
|
| 649 |
silence_fallback_ms: float,
|
| 650 |
asr_cut_silence_ms: float,
|
|
@@ -665,6 +688,7 @@ def run_gradio(
|
|
| 665 |
smartturn_threshold=float(smartturn_threshold),
|
| 666 |
pvad_threshold=float(pvad_threshold),
|
| 667 |
pvad_model_path=pvad_model_path,
|
|
|
|
| 668 |
min_active_target_ms=float(min_active_target_ms),
|
| 669 |
silence_fallback_ms=float(silence_fallback_ms),
|
| 670 |
asr_cut_silence_ms=float(asr_cut_silence_ms),
|
|
@@ -722,7 +746,7 @@ def run_gradio(
|
|
| 722 |
"models": {
|
| 723 |
"pvad": str(pvad_model_path),
|
| 724 |
"silero": str(DEFAULT_SILERO_JIT),
|
| 725 |
-
"smartturn": str(
|
| 726 |
"dualturn": DUALTURN_MODEL_ID,
|
| 727 |
},
|
| 728 |
"state_counts": {state: sum(1 for r in result.rows if r["state"] == state) for state in STATE_COLORS},
|
|
@@ -744,6 +768,12 @@ def select_cut_audio(cut_path: str | None) -> str | None:
|
|
| 744 |
|
| 745 |
|
| 746 |
def build_app() -> gr.Blocks:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 747 |
with gr.Blocks(title="Half Duuplex Demo") as demo:
|
| 748 |
gr.Markdown("## Half Duuplex Demo")
|
| 749 |
with gr.Row():
|
|
@@ -766,6 +796,11 @@ def build_app() -> gr.Blocks:
|
|
| 766 |
label="PVAD ONNX model",
|
| 767 |
)
|
| 768 |
check_ms = gr.Slider(80, 1000, value=240, step=80, label="Model check interval ms")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 769 |
with gr.Row():
|
| 770 |
min_active = gr.Slider(0, 2000, value=300, step=50, label="Min active target ms")
|
| 771 |
silence_fallback = gr.Slider(0, 3000, value=800, step=100, label="Silence fallback END ms")
|
|
@@ -791,6 +826,7 @@ def build_app() -> gr.Blocks:
|
|
| 791 |
smart_threshold,
|
| 792 |
pvad_threshold,
|
| 793 |
pvad_model,
|
|
|
|
| 794 |
min_active,
|
| 795 |
silence_fallback,
|
| 796 |
asr_cut_silence,
|
|
|
|
| 35 |
DEFAULT_PVAD_H256_ONNX = MODELS / "pvad_core_h256.onnx"
|
| 36 |
DEFAULT_SILERO_JIT = MODELS / "silero_vad.jit"
|
| 37 |
DEFAULT_SMARTTURN_ONNX = MODELS / "smartturn-v3.1.onnx"
|
| 38 |
+
CHECKPOINT50_SMARTTURN_ONNX = MODELS / "official_vi_plus_synthinc2000_headonly_lr1e5_checkpoint50_staticcalib8.onnx"
|
| 39 |
+
LOCAL_CHECKPOINT50_SMARTTURN_ONNX = Path(
|
| 40 |
+
"/Utilisateurs/tnguye28/smartturn-vn/outputs/lumi_turn/onnx_exports/"
|
| 41 |
+
"official_vi_plus_synthinc2000_headonly_lr1e5_checkpoint50_staticcalib8/"
|
| 42 |
+
"model_int8_static_calib8.onnx"
|
| 43 |
+
)
|
| 44 |
+
EXAMPLE_SMARTTURN_ONNX = (
|
| 45 |
+
ROOT
|
| 46 |
+
/ ".."
|
| 47 |
+
/ "smartturn-vn"
|
| 48 |
+
/ "outputs"
|
| 49 |
+
/ "lumi_turn"
|
| 50 |
+
/ "onnx_exports"
|
| 51 |
+
/ "official_vi_plus_synthinc2000_headonly_lr1e5_checkpoint25_staticcalib8"
|
| 52 |
+
/ "model_int8_static_calib8.onnx"
|
| 53 |
+
).resolve()
|
| 54 |
DUALTURN_MODEL_ID = "anyreach-ai/dualturn-qwen2.5-mimi-0.5B"
|
| 55 |
DEFAULT_DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 56 |
|
|
|
|
| 85 |
return str(path) if path.exists() else None
|
| 86 |
|
| 87 |
|
| 88 |
+
def checkpoint50_smartturn_path() -> Path:
|
| 89 |
+
return LOCAL_CHECKPOINT50_SMARTTURN_ONNX if LOCAL_CHECKPOINT50_SMARTTURN_ONNX.exists() else CHECKPOINT50_SMARTTURN_ONNX
|
| 90 |
+
|
| 91 |
+
|
| 92 |
def write_wav(path: Path, audio: np.ndarray, sample_rate: int = 16000) -> str:
|
| 93 |
path.parent.mkdir(parents=True, exist_ok=True)
|
| 94 |
sf.write(str(path), np.asarray(audio, dtype=np.float32), sample_rate)
|
|
|
|
| 96 |
|
| 97 |
|
| 98 |
def make_ort_session(path: str | Path) -> ort.InferenceSession:
|
| 99 |
+
path = str(path).strip()
|
| 100 |
opts = ort.SessionOptions()
|
| 101 |
opts.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
|
| 102 |
opts.intra_op_num_threads = 1
|
| 103 |
opts.inter_op_num_threads = 1
|
| 104 |
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
|
| 105 |
+
return ort.InferenceSession(path, sess_options=opts, providers=["CPUExecutionProvider"])
|
| 106 |
|
| 107 |
|
| 108 |
def frame_audio(audio: np.ndarray, frame_size: int = 512) -> np.ndarray:
|
|
|
|
| 348 |
smartturn_threshold: float,
|
| 349 |
pvad_threshold: float,
|
| 350 |
pvad_model_path: str,
|
| 351 |
+
smartturn_model_path: str,
|
| 352 |
min_active_target_ms: float,
|
| 353 |
silence_fallback_ms: float,
|
| 354 |
asr_cut_silence_ms: float,
|
|
|
|
| 364 |
assistant = assistant[: int(round(assistant_max_playback_sec * 16000))]
|
| 365 |
|
| 366 |
pvad = PvadOnnx(pvad_model_path, DEFAULT_SILERO_JIT)
|
| 367 |
+
smartturn = SmartTurnOnnx(smartturn_model_path)
|
| 368 |
dualturn = DualTurnHF(DUALTURN_MODEL_ID, device)
|
| 369 |
|
| 370 |
pvad_probs = pvad.predict_target_probs(mic, enroll)
|
|
|
|
| 667 |
smartturn_threshold: float,
|
| 668 |
pvad_threshold: float,
|
| 669 |
pvad_model_path: str,
|
| 670 |
+
smartturn_model_path: str,
|
| 671 |
min_active_target_ms: float,
|
| 672 |
silence_fallback_ms: float,
|
| 673 |
asr_cut_silence_ms: float,
|
|
|
|
| 688 |
smartturn_threshold=float(smartturn_threshold),
|
| 689 |
pvad_threshold=float(pvad_threshold),
|
| 690 |
pvad_model_path=pvad_model_path,
|
| 691 |
+
smartturn_model_path=smartturn_model_path,
|
| 692 |
min_active_target_ms=float(min_active_target_ms),
|
| 693 |
silence_fallback_ms=float(silence_fallback_ms),
|
| 694 |
asr_cut_silence_ms=float(asr_cut_silence_ms),
|
|
|
|
| 746 |
"models": {
|
| 747 |
"pvad": str(pvad_model_path),
|
| 748 |
"silero": str(DEFAULT_SILERO_JIT),
|
| 749 |
+
"smartturn": str(smartturn_model_path),
|
| 750 |
"dualturn": DUALTURN_MODEL_ID,
|
| 751 |
},
|
| 752 |
"state_counts": {state: sum(1 for r in result.rows if r["state"] == state) for state in STATE_COLORS},
|
|
|
|
| 768 |
|
| 769 |
|
| 770 |
def build_app() -> gr.Blocks:
|
| 771 |
+
default_smartturn = EXAMPLE_SMARTTURN_ONNX if EXAMPLE_SMARTTURN_ONNX.exists() else DEFAULT_SMARTTURN_ONNX
|
| 772 |
+
checkpoint50_smartturn = checkpoint50_smartturn_path()
|
| 773 |
+
smartturn_choices = [
|
| 774 |
+
("original", str(default_smartturn)),
|
| 775 |
+
("finetuned", str(checkpoint50_smartturn)),
|
| 776 |
+
]
|
| 777 |
with gr.Blocks(title="Half Duuplex Demo") as demo:
|
| 778 |
gr.Markdown("## Half Duuplex Demo")
|
| 779 |
with gr.Row():
|
|
|
|
| 796 |
label="PVAD ONNX model",
|
| 797 |
)
|
| 798 |
check_ms = gr.Slider(80, 1000, value=240, step=80, label="Model check interval ms")
|
| 799 |
+
smartturn_model = gr.Dropdown(
|
| 800 |
+
choices=smartturn_choices,
|
| 801 |
+
value=str(default_smartturn),
|
| 802 |
+
label="SmartTurn ONNX model",
|
| 803 |
+
)
|
| 804 |
with gr.Row():
|
| 805 |
min_active = gr.Slider(0, 2000, value=300, step=50, label="Min active target ms")
|
| 806 |
silence_fallback = gr.Slider(0, 3000, value=800, step=100, label="Silence fallback END ms")
|
|
|
|
| 826 |
smart_threshold,
|
| 827 |
pvad_threshold,
|
| 828 |
pvad_model,
|
| 829 |
+
smartturn_model,
|
| 830 |
min_active,
|
| 831 |
silence_fallback,
|
| 832 |
asr_cut_silence,
|