fix(deepgram): use punctuated_word for word-level transcripts - #6699
Merged
Conversation
SpeechData.text comes from alt["transcript"], which Deepgram punctuates. The word list was built from alt["words"][].word, which is always lowercase and unpunctuated, so the two fields of the same SpeechData disagreed: .text "We are so excited for you to join the Ribbon team." .words[].text "we are so excited for you to join the ribbon team" Deepgram returns punctuated_word alongside word whenever punctuate is enabled (it is on by default), so the punctuated form was already in the payload the comprehension iterates. Prefer it, falling back to word when punctuation is disabled or the key is absent. This matters for consumers that render or align on the word list — clickable transcripts, captions, time-aligned analysis — where the words are the display text and currently read as an uncased, unpunctuated wall of text. Applied to both the streaming and prerecorded paths. Word timing is untouched.
Follows the `punctuate` setting rather than inferring from key presence, so the word list matches SpeechData.text in both configurations: punctuate=True text and words both punctuated punctuate=False text and words both raw Threads the option from STTOptions through both conversion helpers. The new keyword defaults to True, matching STT(punctuate=True), so existing callers of these module-level functions are unaffected.
`word` is an untyped dict, so `.get()` returns Any and returning it directly from a `-> str` function trips mypy's strict no-any-return. The original code was inline inside the TimedString(...) call, where there was no declared return type to violate; extracting the helper is what surfaced it. Bind to str-annotated locals so the narrowing happens once. Behaviour unchanged.
mdylan2
marked this pull request as ready for review
August 4, 2026 23:14
chenghao-mou
reviewed
Aug 5, 2026
Per review: smart_format also produces a formatted transcript, so gating the word form on `punctuate` alone left a hole. Verified against the API: punctuate=F smart_format=F transcript raw punctuated_word ABSENT punctuate=F smart_format=T transcript PUNCTUATED punctuated_word present punctuate=T smart_format=F transcript punctuated punctuated_word present So STT(punctuate=False, smart_format=True) got a punctuated `text` and raw `words` — the exact inconsistency this PR removes, reintroduced. Both call sites now pass `punctuate or smart_format`. Checked the neighbouring options too: dictation, numerals, and filler_words leave punctuated_word absent when punctuate is off, so those two are the whole set. Renamed the keyword to `use_punctuated_word`: the value is a decision derived from two options, not the `punctuate` option, and naming it after the latter invites someone to "simplify" it back and silently restore the hole. The keyword does not exist on main, so the rename breaks no caller. Streamed live audio through all four combinations; `.words` now matches `.text` in every one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SpeechData.textandSpeechData.wordsare built from different Deepgram fields, so the two disagree on the same object.textcomes from the transcript, which honours thepunctuateoption. The word list was built from the raw per-word field, which is lowercase and unpunctuated regardless of any option:Deepgram returns
punctuated_wordalongsideword, in the very dict that comprehension iterates:Field selection across the four cases: