Spaces:
Sleeping
Sleeping
File size: 5,571 Bytes
15fbd84 | 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 | """
Verifies the app ACTUALLY LAUNCHES under the pinned gradio, and that every
event handler is wired with a matching signature.
This is the check that was missing before: the previous app.py used
`stream_every`, which does not exist in gradio 4.44 β it would have crashed on
Space startup no matter how correct the rest of the code was.
Models are stubbed, so this tests the app wiring, not the ML.
"""
import os
import sys
import types
import numpy as np
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
# ββ Stub the pipeline so no 3.5GB download happens βββββββββββββββββββββββββββ
import pipeline as _pl
def _fake_transcribe(self, audio, sr=16000):
return "duba asusuna sannan ka aika 35000 zuwa Amina"
def _fake_translate(self, text, src, tgt, **kw):
table = {
"duba asusuna sannan ka aika 35000 zuwa Amina":
"check my balance and also send 35000 to amina",
"2234567890": "2234567890",
"eh": "yes",
}
return table.get(text, text)
def _fake_tts(self, text):
return 16000, (np.sin(np.arange(8000) / 20) * 8000).astype(np.int16)
_pl.HausaVoiceAIPipeline.transcribe = _fake_transcribe
_pl.HausaVoiceAIPipeline.transcribe_partial = _fake_transcribe
_pl.HausaVoiceAIPipeline.translate = _fake_translate
_pl.HausaVoiceAIPipeline.synthesize = _fake_tts
_pl.HausaVoiceAIPipeline.hausa_text_to_audio = _fake_tts
_pl.HausaVoiceAIPipeline._load_asr = lambda self: None
_pl.HausaVoiceAIPipeline._load_asr_fast = lambda self: None
_pl.HausaVoiceAIPipeline._load_nllb = lambda self: None
_pl.HausaVoiceAIPipeline._load_tts = lambda self: None
os.environ.setdefault("SHOW_PARTIALS", "0")
PASS, FAIL = "\033[92mPASS\033[0m", "\033[91mFAIL\033[0m"
results = []
def check(name, cond, detail=""):
results.append((name, cond))
print(f" [{PASS if cond else FAIL}] {name}" + (f" β {detail}" if detail else ""))
print("\nββ App imports and builds under the pinned gradio ββ")
import gradio as gr
print(f" gradio {gr.__version__}")
import app as A
check("app module imported", True)
check("Blocks object built", isinstance(A.demo, gr.Blocks))
print("\nββ Streaming API exists in this gradio version ββ")
import inspect
p = inspect.signature(gr.Audio(streaming=True).stream).parameters
check("Audio.stream accepts stream_every", "stream_every" in p)
check("gr.skip available", hasattr(gr, "skip"))
print("\nββ Event handlers are wired ββ")
fns = A.demo.fns
check("events registered", len(fns) > 0, f"{len(fns)} handlers")
print("\nββ Text handler: full compound-request conversation ββ")
st = None
audio, convo, status, st = A.on_text(
"duba asusuna sannan ka aika 35000 zuwa Amina", st)
check("turn 1 returns audio", audio is not None and audio is not gr.skip())
check("turn 1 acknowledges BOTH tasks",
"one at a time" in convo.lower() or "balance" in convo.lower(),
status[:70])
audio, convo, status, st = A.on_text("2234567890", st)
check("turn 2 delivers balance + continues transfer",
"balance is" in convo.lower() and "amina" in convo.lower())
audio, convo, status, st = A.on_text("eh", st)
check("turn 3 executes the transfer", "sent to amina" in convo.lower())
check("latency breakdown in status", "total" in status, status[-52:])
print("\nββ Empty input does not crash ββ")
a, c, s, st2 = A.on_text("", None)
check("empty text handled", a == gr.skip() or a is None)
a, c, s, st2 = A.on_record(None, None)
check("no recording handled", a == gr.skip() or a is None)
print("\nββ Streaming handler with synthetic audio ββ")
SR = 16000
def sil(ms, n=0.0005):
k = int(SR * ms / 1000)
return (np.random.randn(k) * n).astype(np.float32)
def sp(ms, amp=0.25):
k = int(SR * ms / 1000)
t = np.arange(k) / SR
s = (np.sin(2*np.pi*120*t) + 0.5*np.sin(2*np.pi*700*t)
+ 0.3*np.sin(2*np.pi*1220*t))
s = s * (0.6 + 0.4*np.sin(2*np.pi*4*t)) + np.random.randn(k)*0.01
return (s / np.abs(s).max() * amp).astype(np.float32)
st = A.new_state()
stream = np.concatenate([sil(400), sp(1600), sil(1200)])
step = int(SR * 0.5)
got_reply = False
n_skips = 0
for i in range(0, len(stream), step):
out = A.on_stream((SR, stream[i:i+step]), st)
check_len = len(out) == 5
audio_o, convo_o, status_o, partial_o, st = out
if audio_o == gr.skip():
n_skips += 1
elif audio_o is not None:
got_reply = True
check("stream handler returns 5 values", check_len)
check("VAD endpointed and produced a reply", got_reply)
check("idle ticks return gr.skip (no player restart)", n_skips > 0,
f"{n_skips} skipped ticks")
print("\nββ Reset ββ")
r = A.reset(st)
check("reset returns 5 values", len(r) == 5)
check("history cleared", "Press" in r[1] or "empty" in r[1])
print("\nββ Launch smoke test (real server, then shut down) ββ")
try:
A.demo.queue(max_size=4)
_, url, _ = A.demo.launch(prevent_thread_lock=True, quiet=True,
server_port=7899, show_api=False)
check("Gradio server started", True, url or "local")
import urllib.request
code = urllib.request.urlopen("http://127.0.0.1:7899/", timeout=15).getcode()
check("HTTP 200 from the app root", code == 200, f"status {code}")
A.demo.close()
except Exception as e:
check("Gradio server started", False, str(e)[:110])
passed = sum(1 for _, ok in results if ok)
print(f"\n{'='*62}\n {passed}/{len(results)} checks passed\n{'='*62}")
sys.exit(0 if passed == len(results) else 1)
|