Skip to content

live: full-duplex personaplex-7b over gpt-live websocket sessions - #7

Merged
xiaguan merged 1 commit into
mainfrom
personaplex-live
Sep 26, 2026
Merged

xiaguan merged 1 commit into
mainfrom
personaplex-live

Conversation

@xiaguan

@xiaguan xiaguan commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Full-duplex serving, end to end: NVIDIA PersonaPlex-7B over OpenAI's GPT-Live WebSocket protocol, with a browser demo.

What

Crate / file Change
omni-engine::live The live contract. Sessions go over a channel. Frame n of a session is the nth frame the engine ran, so the agent's audio is one contiguous stream. Each session has a jitter buffer that starts playout after a prebuffer, refills it after an underrun, and discards the caller's audio of overrun ticks. A drift-free 80 ms clock skips overrun ticks instead of bursting. drive is the one loop both live engines run (clock, admission, Pulse counters) over a Ticker; Line is a running session. Property-tested.
omni-frontend GET /v1/live/sessions (GPT-Live: strict session.start, errors naming the param, unsupported events refused by name, server_busy keeps the socket for a retry, mute forwards silence). Demo page at /. GET /live/config and GET /live/stats. Tick counters in /metrics. The socket's paths (abort, engine stop, close grace, close before start, full queue, mute) are tested against an engine the test plays by hand.
omni-sim::live CPU live engine: a pure per-session echo core (the caller late, a word per half second heard) under drive.
omni-bench duplex Concurrent sessions at real time. Reports frame lateness and playback underrun per level; --ramp finds capacity.
omni-kern Manifest builder, weight loading, common kernels and host helpers, moved out of omni-qwen3-tts so both GPU engines share them.
omni-personaplex Mimi encoder → Helium → depformer → Mimi decoder as one kern manifest with its own kernels, one CUDA graph per tick over all sessions. Each session has a fixed ring of the model's 3000-frame context plus streaming codec state. The engine leases a session on arrival, prefills it in the next tick batched with other newcomers, and streams audio and the model's text. The role-prompt limit is derived so any allowed prompt fits the context. tests/host.rs covers batching, the tokenizer, the voice reader and the prompt without a checkpoint, so CI runs it.
pega-omni personaplex Server subcommand behind the personaplex feature.
tools/live_check.py GPT-Live protocol oracle. CI runs it plus a duplex ramp against sim-live.
docs/ duplex.md: how full duplex works, the protocol, options, design choices. personaplex.md: the engine. PersonaPlex section in bench.md.

Correctness

crates/omni-personaplex/tests/golden.rs runs the serving path against the reference implementation's recorded run. It uses three sessions: two in lockstep (bit-identical to each other) and one joining mid-run.

Check Result
Input rows and emitted frames exact
Text logits cosine ≥ 0.998
Depformer logits cosine ≥ 0.9996
Depformer argmax 98.8% agree
Voiced caller semantic codes 100% agree
Session prefilled in other batches vs its lockstep twin > 40 dB
Decoded audio SNR 31.8 dB

The qwen3-tts golden test still passes after the omni-kern move.

Performance (one GB300)

128 concurrent full-duplex sessions, each streaming real speech at real time, run clean:

Metric Result
Playback underrun none
Late ticks none once warm (the first call at each batch size captures its graph)
Frame lateness p99 12.6 ms
Tick at 128 sessions 15 ms of its 80 ms budget

The ceiling is memory (1.5 GiB of KV per session), not compute. Details are in docs/bench.md.

Try it

cargo build --release -p omni-server --features personaplex
target/release/pega-omni personaplex --model-path personaplex-7b-v1
# open http://127.0.0.1:8000/ (for a remote GPU: ssh -L 8000:127.0.0.1:8000)

🤖 Generated with Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Full-duplex serving end to end: a live engine contract next to the speech
one, OpenAI's GPT-Live WebSocket protocol, a browser demo, a simulated live
engine, a duplex load generator, and the first live GPU engine, NVIDIA
PersonaPlex-7B, with every session advancing one 80 ms frame per tick in one
CUDA graph.

- omni-engine::live: sessions over a channel; frame n of a session is the
  nth frame the engine ran, so the agent's audio is one contiguous stream;
  a per-session jitter buffer that plays out after a prebuffer, refills it
  when it runs dry and discards the caller's audio of overrun ticks; a
  drift-free clock that skips overrun ticks instead of bursting. `drive` is
  the loop both live engines run (clock, admission, `Pulse` counters) over a
  `Ticker`, and `Line` is a running session (jitter buffer, frame count,
  expiry, outputs). Property-tested.
- omni-frontend: `/v1/live/sessions` (GPT-Live events, strict parsing,
  errors naming the param, unsupported events refused by name, `server_busy`
  keeping the socket for a retry, mute forwarding silence), the demo at `/`
  (call UI with an orb, chat, device pickers, and the engine's live load
  from `/live/stats`), tick counters in /metrics. The socket's paths are
  tested against an engine the test plays by hand. `tools/live_check.py` is
  the protocol oracle; CI runs it and a duplex ramp against `sim-live`.
- omni-sim::live: the CPU live engine, a pure per-session echo core (the
  caller late, a word per half second heard) under `drive`.
- omni-bench duplex: concurrent sessions at real time, frame lateness and
  playback underrun per level, `--ramp` to find capacity.
- omni-kern: the manifest builder, weight loading, common kernels and the
  host-side helpers moved out of omni-qwen3-tts so both GPU engines share
  them.
- omni-personaplex: Mimi encoder, Helium, depformer and Mimi decoder with
  their own kernels; each session a fixed ring of the model's 3000-frame
  context plus its streaming codec state. The engine leases a session on
  arrival and prefills it in the next tick, batched (`batches`); the role
  prompt limit is derived so any allowed prompt fits the context.
  `tests/golden.rs` checks the serving path against the reference run;
  `tests/host.rs` covers batching, the tokenizer, the voice reader and the
  prompt without a checkpoint, so CI runs it.
- `pega-omni personaplex` behind the `personaplex` feature.
- docs: duplex.md (how full duplex works, protocol, options, design
  choices), personaplex.md, a PersonaPlex section in bench.md.

One GB300: 128 concurrent sessions with no playback underrun and no late
tick once warm; a tick takes 15 ms of its 80.

Dependencies: axum's `ws` feature (the live endpoint on the same server and
connection handling as HTTP); tokio-tungstenite for omni-bench's live client
(the tungstenite stack axum's `ws` already builds on).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: JinYan Su <751080330@qq.com>
@xiaguan
xiaguan merged commit 8d12bbe into main Sep 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant