codewithmoin's picture
CPU inference off the GPU queue (dummy GPU probe only)
c86f0bd verified
Raw History Blame Contribute Delete
2.59 kB
"""Smart Turn Detection — Hugging Face Space demo (ONNX, CPU).
Runs the exported 8s model: raw 16k waveform -> P(turn complete).
Inference is CPU-only, so predictions don't touch the GPU queue. The one decorated
`_gpu_probe` below exists only so the ZeroGPU runtime accepts the Space; it's never called."""
import numpy as np
import onnxruntime as ort
import gradio as gr
try:
import spaces
@spaces.GPU
def _gpu_probe(): # satisfies ZeroGPU's "must expose a GPU function" check; unused
return None
except Exception:
pass
SR, WIN = 16000, 8
N = SR * WIN # 128000
SESS = ort.InferenceSession("smart_turn_8s.onnx", providers=["CPUExecutionProvider"])
def prob_complete(wav, sr):
wav = np.asarray(wav, dtype=np.float32)
if wav.ndim > 1:
wav = wav.mean(axis=1)
if sr != SR:
import librosa
wav = librosa.resample(wav, orig_sr=sr, target_sr=SR)
mx = np.abs(wav).max()
if mx > 0:
wav = wav / mx
x = wav[-N:] # last 8s
buf = np.zeros((1, N), np.float32)
buf[0, N - len(x):] = x # right-align (left-pad)
return float(SESS.run(None, {"waveform": buf})[0][0])
def predict(audio, threshold):
if audio is None:
return "Record or upload some speech.", None
sr, wav = audio
if wav.dtype.kind in "iu":
wav = wav.astype(np.float32) / np.iinfo(wav.dtype).max
p = prob_complete(wav, sr)
verdict = "✅ Turn COMPLETE — safe to respond" if p > threshold else "⏳ Still speaking — wait"
return f"{verdict}\n\nP(complete) = {p:.3f} (threshold {threshold:.2f})", {"complete": p, "still speaking": 1 - p}
with gr.Blocks(title="Smart Turn Detection") as demo:
gr.Markdown(
"# 🎙️ Smart Turn Detection (whisper-tiny, 8s)\n"
"Has the speaker **finished their turn**, or are they just pausing? Audio only, "
"no transcription. Tuned for English + Hindi/Hinglish. ~7.8M params, ~38 ms/clip on CPU.\n\n"
"_Try a finished sentence vs. trailing off with 'umm…'. Raise the threshold to interrupt less._")
inp = gr.Audio(sources=["microphone", "upload"], type="numpy", label="Speech")
thr = gr.Slider(0.05, 0.95, value=0.5, step=0.05, label="Decision threshold")
btn = gr.Button("Detect turn", variant="primary")
out_txt = gr.Textbox(label="Verdict")
out_lbl = gr.Label(label="Probabilities")
btn.click(predict, [inp, thr], [out_txt, out_lbl])
inp.stop_recording(predict, [inp, thr], [out_txt, out_lbl])
if __name__ == "__main__":
demo.launch()