Skip to content

fix(voice): keep preemptive generation when a transcript only changes formatting - #2794

Open
u9g wants to merge 1 commit into
mainfrom
jason/preflight-transcript-equivalent
Open

u9g wants to merge 1 commit into
mainfrom
jason/preflight-transcript-equivalent

Conversation

@u9g

@u9g u9g commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Description

AgentActivity.onPreemptiveGeneration cancels the in-flight preemptive reply and starts a new LLM request on every call. AudioRecognition calls it on every PREFLIGHT_TRANSCRIPT, and on a FINAL_TRANSCRIPT that is not an exact string match of the last preflight.

STTs revise punctuation within a turn. Deepgram Flux through LiveKit Inference (deepgram/flux-general-en, default settings) often sends a second EagerEndOfTurn that only adds a question mark:

2.170s  preflight  "Could you tell me the opening hours"
2.289s  preflight  "Could you tell me the opening hours?"
2.333s  final      "Could you tell me the opening hours?"

Across 42 synthesized Flux turns, 8 had a second preflight that differed only in punctuation. Each one threw away the running LLM request and started over, so the head start shrank by the gap between the two preflights (about 120 to 280 ms) and the LLM was called twice. The restart never changes what the agent says: at end of turn the reply is already reused when the transcripts are transcriptsEquivalent.

Same fix in Python: livekit/agents#7991 (the demo there replays the captured Flux turn: main sends 2 LLM requests, the fix sends 1 and reuses it with a longer preemptive_lead_time).

Changes Made

  • onPreemptiveGeneration returns early, before cancelling or counting a retry, when the in-flight attempt's transcript is transcriptsEquivalent to the new one. That covers a formatting-only second preflight and a final that only reformats the preflight. A transcript with new words still cancels and restarts, and the end-of-turn check still compares transcript, chat context, tools and tool choice before reusing the reply.
  • The onPreemptiveGeneration guard tests now give each call distinct words, so the retry-counter tests still exercise restarts.
  • Patch changeset for @livekit/agents.

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: see the Python PR above; the change is not visible in Agent Playground

Testing

  • Automated tests added/updated: restarts for the revised transcript keeps the first attempt when only punctuation or case changes (fails on main) and restarts when words change.
  • All tests pass: pnpm test agents/src/voice (1440 passed), pnpm build:agents, tsc --noEmit, eslint and prettier.
  • Make sure both restaurant_agent.ts and realtime_agent.ts work properly (for major changes): not a major change

@changeset-bot

changeset-bot Bot commented Oct 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: eb2661b

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

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

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.

2 participants