File size: 2,076 Bytes
4a3fec4 952b23c 4a3fec4 | 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 | """Render and stream real assessment stages without estimated percentages."""
import html
from contextvars import copy_context
from queue import Queue
from threading import Thread
def stage_names(mode):
steps = [("audio", "Prepare audio"), ("model", "Prepare model")]
if mode == "Reference-free":
steps.append(("transcribe", "Transcribe speech"))
return steps + [("score", "Scoring")]
def stage_markup(mode, active=None, complete=False, failed=False):
steps = stage_names(mode)
index = next((i for i, (key, _) in enumerate(steps) if key == active), -1)
items = []
for i, (key, label) in enumerate(steps):
state = "done" if complete or 0 <= i < index else "active" if i == index else "pending"
if failed and i == index:
state = "failed"
number = "✓" if state == "done" else str(i + 1)
items.append(f'<div class="assessment-step {state}" data-stage="{key}">'
f'<span class="step-number">{number}</span><span>{label}</span>'
'<div class="step-track"><i></i></div></div>')
caption = "Assessment complete" if complete else "Assessment stopped" if failed else (
f"Stage {index + 1} of {len(steps)} · {steps[index][1]}" if index >= 0 else f"{len(steps)} assessment stages")
return '<div class="assessment-progress" role="status" aria-live="polite"><div class="step-caption">' + html.escape(caption) + '</div><div class="assessment-steps">' + ''.join(items) + '</div></div>'
def stream_work(work):
"""Run blocking inference while forwarding stage transitions to Gradio."""
events = Queue()
def run():
try:
result = work(lambda stage: events.put(("stage", stage)))
events.put(("result", result))
except Exception as error:
events.put(("error", error))
context = copy_context()
Thread(target=lambda: context.run(run), daemon=True).start()
while True:
kind, payload = events.get()
yield kind, payload
if kind != "stage":
return
|