Skip to content

feat(eot): feed the local mini model its 2.0 s window and turn length - #2850

Draft
chenghao-mou wants to merge 7 commits into
mainfrom
chenghao/feat/AGT-3736-mini-2s-eot-model
Draft

chenghao-mou wants to merge 7 commits into
mainfrom
chenghao/feat/AGT-3736-mini-2s-eot-model

Conversation

@chenghao-mou

@chenghao-mou chenghao-mou commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Description

The next local mini model (v1.1-mini, @livekit/local-inference 0.2.8) reads the last 2.0 s of audio and takes the turn length as a feature. This ports livekit/agents#8113: the local transport keeps the window the binding reports as EOT_MAX_SAMPLES and sends turnSamples, counted from the user turn start, which AudioRecognition reports once per turn. The per-language thresholds match the Python SDK.

Warning

Blocked on the @livekit/local-inference 0.2.8 release. pnpm-lock.yaml still resolves 0.2.7, which rejects predict(pcm, turnSamples) and has no EOT_MAX_SAMPLES export, so CI fails until it ships.

Changes Made

  • LocalTransport buffers EOT_MAX_SAMPLES and passes turnSamples to the runner, which forwards it to predict. turnSamples never drops below the audio sent.
  • BaseStreamingTurnDetectorStream.onStartOfTurn(startedAt) measures the elapsed time when it queues the sentinel, so a backlog drained after a cloud reconnect does not stretch the turn.
  • AudioRecognition reports only a known speech start; a turn opened at end of speech counts from the last flush.
  • v1.1 thresholds in LOCAL_LANGUAGES; one memory note, ~540 MB measured in Node.

Pre-Review Checklist

  • Build passes: All builds (lint, typecheck, tests) pass locally
  • AI-generated code reviewed: Removed unnecessary comments and ensured code quality
  • Changes explained: All changes are properly documented and justified above
  • Scope appropriate: All changes relate to the PR title, or explanations provided for why they're included
  • Video demo: A small video demo showing changes works as expected and did not break any existing functionality using Agent Playground (if applicable)

Testing

  • Automated tests added/updated (if applicable)
  • All tests pass
  • Make sure both restaurant_agent.ts and realtime_agent.ts work properly (for major changes)

Additional Notes

Local checks ran against a 0.2.8 binding built from source.

Addresses AGT-3736

Initial prompt and agent context

Model: Claude Opus 5.5

can you update the agents client too for this new model?

Then, after the Python change and a threshold refit: "yes, open the PR and open the node js PR too."

@livekit/local-inference 0.2.8 ships v1.1-mini, which reads the last 2.0 s
of audio and takes the turn length, counted from the user's first speech,
as a feature. The local transport now buffers 2.0 s and sends turnSamples
to the runner; AudioRecognition marks the turn start on VAD start of
speech. The per-language thresholds match the Python SDK's v1.1 refit.
@chenghao-mou chenghao-mou added the review_effort:high Cross-cutting or subtle changes requiring broad context and substantial validation label Oct 24, 2026
@changeset-bot

changeset-bot Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1953fd2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-anthropic Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-azure Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-krisp Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-meta Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-protoface Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-speechify Patch
@livekit/agents-plugin-synthesia Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugins-test Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Rename markSpeechStart(lookback) to onStartOfTurn(startedAt), after the
endpointing peer onStartOfSpeech(startedAt). AudioRecognition now calls it
once per turn, where it sets userTurnStart, so the transport no longer
filters repeated starts and a turn that starts from STT gets a start too.
The stream turns the start time into a duration when called, so the
channel delay can't stretch the turn.
Both onStartOfTurn methods now take startedAt; the local transport turns it into a sample position when it reads the sentinel. The drain lag this adds is sub-millisecond on an idle loop, and a long stall already delays inference.
The local transport read the clock when it drained the start-of-turn
sentinel. During a cloud reconnect the audio channel backs up, so after
a fallback to local the turn length was too long by the backlog. The
stream now converts the start time to samples when it queues the
sentinel, and the transport takes that sample count.

- Keep one turn counter in the local transport, and send at least the
  audio the model reads.
- Size the window from the binding's EOT_MAX_SAMPLES, and require
  turnSamples on the inference request.
- Tell the turn detector only a known speech start. A turn opened at
  end of speech keeps the count from the last flush.
- Keep the measured memory figure in one place.
The sentinel carries the elapsed time measured when it is queued, and
the local transport converts it to samples. The name no longer collides
with the turnSamples sent to predict, which counts up to inference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review_effort:high Cross-cutting or subtle changes requiring broad context and substantial validation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant