Skip to content

fix(deepgram): use punctuated_word for word-level transcripts - #2227

Merged
chenghao-mou merged 2 commits into
mainfrom
fix/deepgram-punctuated-words
Aug 14, 2026
Merged

fix(deepgram): use punctuated_word for word-level transcripts#2227
chenghao-mou merged 2 commits into
mainfrom
fix/deepgram-punctuated-words

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • use Deepgram punctuated_word values for word-level transcripts when punctuate or smart_format is enabled
  • preserve raw word values when formatting is disabled and fall back to them when punctuated_word is absent or empty
  • apply the behavior to both prerecorded and streaming transcription paths

Ports livekit/agents#6699.

Source diff coverage

Source diff coverage

  • livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt.py: adapted to plugins/deepgram/src/stt.ts. The target already has corresponding prerecorded and streaming conversion paths, so the Python option forwarding and _word_text selection logic were translated to camelCase TypeScript while preserving defaults and fallback behavior.
  • Source tests: not applicable. The authoritative source PR did not add or modify test files, so no target tests were added.

Validation

  • pnpm test plugins/deepgram (4 passed, 3 credential-gated tests skipped)
  • pnpm build (40 packages passed)
  • pnpm --filter @livekit/agents-plugin-deepgram lint (passed with pre-existing warnings)
  • pnpm lint (blocked by an unrelated existing Prettier error in plugins/minimax/src/models.ts)
  • cue-cli runtime validation was not run because DEEPGRAM_API_KEY is unavailable in the environment

Ported from livekit/agents#6699

Original PR description

Summary

SpeechData.text and SpeechData.words are built from different Deepgram fields, so the two disagree on the same object.

text comes from the transcript, which honours the punctuate option. The word list was built from the raw per-word field, which is lowercase and unpunctuated regardless of any option:

text=alt["transcript"],                    # honours `punctuate`
...
words=[
    TimedString(
        text=word.get("word", ""),         # never punctuated

Deepgram returns punctuated_word alongside word, in the very dict that comprehension iterates:

keys : ['confidence', 'end', 'punctuated_word', 'start', 'word']
word            : hello my name is alex
punctuated_word : Hello. My name is Alex.

Field selection across the four cases:

_word_text({"word": "alex", "punctuated_word": "Alex."}, punctuate=True)   # -> "Alex."
_word_text({"word": "alex"},                             punctuate=True)   # -> "alex"
_word_text({"word": "alex", "punctuated_word": ""},      punctuate=True)   # -> "alex"
_word_text({"word": "alex", "punctuated_word": "Alex."}, punctuate=False)  # -> "alex"

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from a team as a code owner August 5, 2026 14:44
@changeset-bot

changeset-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f5741b4

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

This PR includes changesets to release 39 packages
Name Type
@livekit/agents-plugin-deepgram Patch
@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-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra 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-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-tavus Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch
@livekit/agents-plugins-test 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 potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

Copy link
Copy Markdown
Member

Port verification: livekit/agents#6699 → this PR

Compared this PR's diff against the merged Python source (livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt.py) line-by-line.

Verdict: Faithful, mechanical port. No correctness issues found. Labeled effort:low — a single small, well-isolated helper function extracted and threaded through two existing call sites with matching default values.

Full analysis
  • _word_text (Python) → wordText (JS): identical logic — return raw word when use_punctuated_word is false; otherwise fall back from punctuated_word to word when the punctuated field is absent or empty (or raw / || raw).
  • Both call sites thread punctuate or smart_format (Python) / punctuate || smartFormat (JS) into the helper, applied identically to the streaming (live_transcription_to_speech_data / liveTranscriptionToSpeechData) and prerecorded (prerecorded_transcription_to_speech_event / prerecordedTranscriptionToSpeechEvent) paths.
  • Default value for the new parameter (use_punctuated_word: bool = True / usePunctuatedWord: boolean = true) matches in both languages, so any caller that doesn't pass the flag explicitly keeps prior (punctuated) behavior.
  • The source PR added no tests (test coverage for this behavior was added in a different, previously-merged PR), so the JS port correctly adds none either — matches the "not applicable" note in the PR's own source diff coverage table.
  • Verified the JS STTOptions.punctuate/smartFormat fields already existed pre-PR with the same semantics as Python's punctuate/smart_format, so no config drift was introduced by this change.

Not independently re-run: relied on the PR's own reported pnpm test plugins/deepgram result (4 passed, 3 credential-gated tests skipped), since DEEPGRAM_API_KEY isn't available here either.


Generated by Claude Code

@chenghao-mou chenghao-mou added the effort:low label Aug 11, 2026 — with Claude
@chenghao-mou chenghao-mou self-assigned this Aug 14, 2026
@chenghao-mou
chenghao-mou merged commit 48a721f into main Aug 14, 2026
5 checks passed
@chenghao-mou
chenghao-mou deleted the fix/deepgram-punctuated-words branch August 14, 2026 13:19
@github-actions github-actions Bot mentioned this pull request Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant