Spaces:
Sleeping
Sleeping
| """Drive a full examination end-to-end in the terminal (mock backend). | |
| python3 scripts/demo_playthrough.py | |
| Doubles as the dry-run harness referenced in the demo-video plan: it prints each | |
| turn's perceived stance, the witness's line, and the live contradiction verdict, | |
| then asserts the win fires with a cached voice-crack take. | |
| """ | |
| import os | |
| import sys | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| import numpy as np # noqa: E402 | |
| from witnessbox.backends import get_backends # noqa: E402 | |
| from witnessbox.engine import WitnessBoxEngine # noqa: E402 | |
| from witnessbox import stance as stance_mod # noqa: E402 | |
| SCRIPT = [ | |
| "So, Mr. Reid — comfortable up there?", # filler | |
| "The wire to Meridian cleared March 6th — before the board approved it on the 14th.", | |
| "Anything over $5 million needs the CFO's sign-off, and your credentials are on the authorization log.", | |
| "You were cc'd on Meridian's incorporation filing two years ago — Dana Voss, your colleague.", | |
| ] | |
| def bar(pct, n=20): | |
| f = int(round(pct / 100 * n)) | |
| return "█" * f + "·" * (n - f) | |
| def _speechlike(dur_s=2.4, sr=16000, syl_rate=5.0, pause_frac=0.15, wobble=0.0, seed=0): | |
| """A crude but *speech-like* clip: a voiced carrier (f0 + harmonics, optional | |
| pitch wobble) gated by a train of syllable bumps. Unlike a pure sine, its | |
| pause ratio, onset rate and pitch steadiness move the way real delivery does — | |
| so the stance read comes out in the right direction. | |
| high syl_rate + low pause_frac + flat pitch -> CONFIDENT | |
| low syl_rate + high pause_frac + wobble -> HESITANT | |
| """ | |
| rng = np.random.RandomState(seed) | |
| n = int(dur_s * sr) | |
| t = np.arange(n) / sr | |
| f0 = 135.0 * (1.0 + wobble * np.sin(2 * np.pi * 0.8 * t + rng.rand())) | |
| phase = 2 * np.pi * np.cumsum(f0) / sr | |
| carrier = np.sin(phase) + 0.5 * np.sin(2 * phase) + 0.33 * np.sin(3 * phase) | |
| env = np.zeros(n) | |
| period = max(1, int(sr / syl_rate)) | |
| syl_len = max(1, int(period * (1.0 - pause_frac))) | |
| for start in range(0, n, period): | |
| seg = min(syl_len, n - start) | |
| if seg <= 1: | |
| break | |
| env[start:start + seg] = 0.5 - 0.5 * np.cos(2 * np.pi * np.arange(seg) / seg) | |
| return (0.4 * carrier * env).astype(np.float32) | |
| def main(): | |
| eng = WitnessBoxEngine(get_backends()) | |
| intro = eng.start() | |
| print(f"\n BACKEND: {intro['backend']} — {intro['backend_note']}") | |
| print(f"\n ⚖️ THE COURT: {intro['narration']}") | |
| print(f" 🎙️ REID: {intro['opening_text']}\n") | |
| print(" " + "─" * 64) | |
| last = None | |
| for line in SCRIPT: | |
| last = eng.take_turn(typed_text=line) | |
| s, st = last.status, last.stance | |
| print(f"\n ⚖️ YOU [{st.tier.lower()}]: {last.examiner_text}") | |
| print(f" 🎙️ REID ({s['witness_tier']}): {last.witness_text}") | |
| if last.evidence: | |
| for ln in last.evidence.splitlines(): | |
| print(f" │ {ln}") | |
| audio = "🔊" if last.witness_audio is not None else "—" | |
| print(f" catches {s['catches']}/{s['catches_to_win']} " | |
| f"composure [{bar(s['composure'])}] standing [{bar(s['credibility'])}] {audio}") | |
| if last.events.won: | |
| print(f"\n 💥 HE BREAKS — voice-crack take: " | |
| f"{len(last.witness_audio)} samples @ {last.audio_sr} Hz, " | |
| f"epilogue {'present' if last.epilogue_audio is not None else 'missing'}") | |
| print("\n " + "─" * 64) | |
| print(" Stance scoring on speech-like clips (no real mic needed):") | |
| for name, (dur, syl_rate, pause_frac, wobble) in ( | |
| ("fluent / steady", (2.4, 5.0, 0.12, 0.0)), # dense syllables, few pauses, flat pitch | |
| ("halting / unsure", (3.2, 1.4, 0.72, 0.20)), # sparse syllables, long gaps, wavering pitch | |
| ): | |
| clip = _speechlike(dur_s=dur, syl_rate=syl_rate, pause_frac=pause_frac, wobble=wobble) | |
| r = stance_mod.analyze(clip, 16000) | |
| print(f" {name:18s} -> {r.tier:9s} conf={r.confidence:5.1f} " | |
| f"(pause={r.features.get('pause_ratio')}, rate={r.features.get('rate_hz')}, " | |
| f"pitch_std={r.features.get('pitch_std_semitones')})") | |
| assert last.events.won, "expected a win after three catches" | |
| print("\n ✅ End-to-end win path verified.\n") | |
| if __name__ == "__main__": | |
| main() | |