shangeth-anyreach commited on
Commit
213dae6
Β·
verified Β·
1 Parent(s): bf7bc8e

Fix streaming ONNX: audio_ctx was zero-initialized (Mimi not zero-prefix-invariant) -> streaming diverged 0.17-0.66 from offline. Now grows from empty (dynamic audio_ctx), matches offline to 0.019. Rebuild both stream_tick graphs + helper.

Browse files
Files changed (4) hide show
  1. README.md +8 -8
  2. onnx_streaming.py +2 -2
  3. stream_tick.onnx +2 -2
  4. stream_tick_240.onnx +2 -2
README.md CHANGED
@@ -65,7 +65,7 @@ Four ready-to-use paths (all **fp32, same weights**). **Offline** processes a wh
65
  | 1 | Offline | PyTorch β€” `model(wav, sr)` | ~7.5 ms/frame (batch, ~11Γ— real-time) | torch + transformers |
66
  | 2 | Streaming | PyTorch β€” `model.streaming()` | **~63 ms / 80 ms tick** (real-time, flat) | torch + transformers |
67
  | 3 | Offline | ONNX β€” `model.onnx` | ~7.3 ms/frame (~11Γ— real-time) | onnxruntime |
68
- | 4 | Streaming | ONNX β€” `stream_tick.onnx` | **~48 ms / 80 ms tick** (real-time, flat, tightest tail) | onnxruntime |
69
 
70
  *Offline latency is amortized batch throughput (all frames returned after the file is processed); streaming
71
  latency is the real per-tick cost in a live call β€” both well under the 80 ms budget. Streaming is causal +
@@ -88,14 +88,14 @@ runs to keep up with one live stream (`latency Γ— calls/sec`):
88
 
89
  | graph | infer every | latency / call | calls / audio-sec | grace / call | CPU busy / stream |
90
  |---|---|---|---|---|---|
91
- | `stream_tick.onnx` | **80 ms** | 48 ms | 12.5 | 32 ms | ~60% |
92
- | `stream_tick_240.onnx` | **240 ms** | 80 ms | 4.17 | 160 ms | ~33% |
93
 
94
- - **80 ms β€” snappiest, but heaviest.** Each call eats 48 ms β†’ only **32 ms grace**, pool busy **~60%** per
95
  stream. Fastest reactions, least room for anything else.
96
- - **240 ms β€” much cheaper, lots of slack.** Each call takes 80 ms (vs 3 Γ— 48 = 144 ms for three 80 ms ticks)
97
- but leaves **160 ms grace** and sits at **~33% busy**.
98
- - **The real win is at scale.** CPU per second of audio drops **~1.8Γ—** (600 β†’ 332 ms/s, β‰ˆ45% less), so **one
99
  machine holds roughly ~1.8Γ— as many concurrent calls** β€” the per-stream % looks modest, but that factor
100
  multiplies across every simultaneous call in your fleet. *(`CPU busy %` is a single-stream duty cycle
101
  measured with 4 threads β€” read it as relative cost between graphs, not absolute single-core load.)*
@@ -187,7 +187,7 @@ graph is fully self-contained β€” no `torch` or `transformers` needed at inferen
187
 
188
  Torch-free real-time streaming via `stream_tick.onnx` + the `onnx_streaming.py` helper (`DualTurnONNXStreamer`).
189
  Each 80 ms tick only computes the **new frame** β€” the graph carries all state (conv buffer, transformer **KV
190
- window**, downsample history, LSTM state) in/out, so latency is low (**~48 ms/tick**) and **flat over long
191
  calls**. Decision-equivalent to the PyTorch model.
192
 
193
  ```python
 
65
  | 1 | Offline | PyTorch β€” `model(wav, sr)` | ~7.5 ms/frame (batch, ~11Γ— real-time) | torch + transformers |
66
  | 2 | Streaming | PyTorch β€” `model.streaming()` | **~63 ms / 80 ms tick** (real-time, flat) | torch + transformers |
67
  | 3 | Offline | ONNX β€” `model.onnx` | ~7.3 ms/frame (~11Γ— real-time) | onnxruntime |
68
+ | 4 | Streaming | ONNX β€” `stream_tick.onnx` | **~52 ms / 80 ms tick** (real-time, flat, tightest tail) | onnxruntime |
69
 
70
  *Offline latency is amortized batch throughput (all frames returned after the file is processed); streaming
71
  latency is the real per-tick cost in a live call β€” both well under the 80 ms budget. Streaming is causal +
 
88
 
89
  | graph | infer every | latency / call | calls / audio-sec | grace / call | CPU busy / stream |
90
  |---|---|---|---|---|---|
91
+ | `stream_tick.onnx` | **80 ms** | 52 ms | 12.5 | 28 ms | ~65% |
92
+ | `stream_tick_240.onnx` | **240 ms** | 85 ms | 4.17 | 155 ms | ~36% |
93
 
94
+ - **80 ms β€” snappiest, but heaviest.** Each call eats 52 ms β†’ only **28 ms grace**, pool busy **~65%** per
95
  stream. Fastest reactions, least room for anything else.
96
+ - **240 ms β€” much cheaper, lots of slack.** Each call takes 85 ms (vs 3 Γ— 52 = 156 ms for three 80 ms ticks)
97
+ but leaves **155 ms grace** and sits at **~36% busy**.
98
+ - **The real win is at scale.** CPU per second of audio drops **~1.8Γ—** (650 β†’ 354 ms/s, β‰ˆ45% less), so **one
99
  machine holds roughly ~1.8Γ— as many concurrent calls** β€” the per-stream % looks modest, but that factor
100
  multiplies across every simultaneous call in your fleet. *(`CPU busy %` is a single-stream duty cycle
101
  measured with 4 threads β€” read it as relative cost between graphs, not absolute single-core load.)*
 
187
 
188
  Torch-free real-time streaming via `stream_tick.onnx` + the `onnx_streaming.py` helper (`DualTurnONNXStreamer`).
189
  Each 80 ms tick only computes the **new frame** β€” the graph carries all state (conv buffer, transformer **KV
190
+ window**, downsample history, LSTM state) in/out, so latency is low (**~52 ms/tick**) and **flat over long
191
  calls**. Decision-equivalent to the PyTorch model.
192
 
193
  ```python
onnx_streaming.py CHANGED
@@ -48,8 +48,8 @@ class _BaseStreamer:
48
 
49
  def reset(self):
50
  z = np.zeros
51
- self.state = {"audio_ctx": z((2, self.RF), np.float32),
52
- "pk": z((self.NL, 2, self.H, 0, self.HD), np.float32), # KV starts empty, grows, capped in-graph
53
  "pv": z((self.NL, 2, self.H, 0, self.HD), np.float32),
54
  "tf_hist": z((2, self.TFK, 512), np.float32),
55
  "h": z((2, 1, 256), np.float32), "c": z((2, 1, 256), np.float32),
 
48
 
49
  def reset(self):
50
  z = np.zeros
51
+ self.state = {"audio_ctx": z((2, 0), np.float32), # EMPTY: grow from true start (no
52
+ "pk": z((self.NL, 2, self.H, 0, self.HD), np.float32), # zero-prefix; graph caps at RF). KV likewise grows/caps in-graph
53
  "pv": z((self.NL, 2, self.H, 0, self.HD), np.float32),
54
  "tf_hist": z((2, self.TFK, 512), np.float32),
55
  "h": z((2, 1, 256), np.float32), "c": z((2, 1, 256), np.float32),
stream_tick.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:737418bae8eec4321f9f72120eb2250739f230e1d087e01b469d0beebe80ef7d
3
- size 161721665
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6700ea2f919b4c66355b3dafb4f91f2db9dae9e18a302b812730c04340bf819f
3
+ size 161722822
stream_tick_240.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:b406cd4ced3fb6f9614713fc742e23bd3da8b0a498ced5a9aa39a7d80ac9bd14
3
- size 162399971
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e841d80d2a004ab4ea9d2e85f168505853064c4a9ba7341d180cf352062ed7c7
3
+ size 162401094