Skip to content

fix(tts): prevent double [pause] in xAI auto speech tags for multi-paragraph text - #29417

Closed
EloquentBrush0x wants to merge 1 commit into
NousResearch:mainfrom
EloquentBrush0x:fix/xai-tts-double-pause
Closed

fix(tts): prevent double [pause] in xAI auto speech tags for multi-paragraph text#29417
EloquentBrush0x wants to merge 1 commit into
NousResearch:mainfrom
EloquentBrush0x:fix/xai-tts-double-pause

Conversation

@EloquentBrush0x

Copy link
Copy Markdown
Contributor

Summary

_apply_xai_auto_speech_tags applied two pause-insertion passes unconditionally:

  1. Paragraph breaks (\n\n) → " [pause] "
  2. First-sentence boundary → " [pause] "

Both fired on every call, so multi-paragraph input produced a double pause in the TTS audio:

# Input
"Hello world.\n\nSecond paragraph."

# Before fix
"Hello world. [pause] [pause] Second paragraph."

# After fix
"Hello world. [pause] Second paragraph."

Root cause

The tag-detection guard (_XAI_SPEECH_TAG_RE.search(clean)) only runs once, on the original input text. After the paragraph substitution injects [pause], there is no re-check — so the first-sentence substitution fires even when a pause was already inserted.

Fix

Wrap the first-sentence substitution in a _XAI_SPEECH_TAG_RE.search(clean) guard. If the paragraph pass already added a [pause] tag, the first-sentence pass is skipped. Single-paragraph behavior is unchanged.

clean = re.sub(r"\n\s*\n+", " [pause] ", clean)
clean = re.sub(r"\s*\n\s*", " ", clean)
if not _XAI_SPEECH_TAG_RE.search(clean):   # ← new guard
    clean = _XAI_FIRST_SENTENCE_RE.sub(r"\1 [pause] ", clean, count=1)

Test plan

  • Multi-paragraph input → single [pause] (bug case)
  • Single-paragraph input → first-sentence [pause] still added (regression)
  • Input with explicit speech tags → untouched (existing behavior)
  • Single newline (not paragraph break) → first-sentence pause still fires
  • Empty input → unchanged

…ragraph text

_apply_xai_auto_speech_tags runs two independent transformations:
  1. paragraph breaks (\n\n) → " [pause] "
  2. first-sentence boundary → " [pause] "

Both fired unconditionally, so multi-paragraph input produced
"Hello world. [pause] [pause] Second paragraph." — an unnatural
double pause in the TTS audio.

Guard the first-sentence substitution with _XAI_SPEECH_TAG_RE.search(clean):
if the paragraph pass already inserted a [pause] tag, skip the
first-sentence pass. Single-paragraph behavior is unchanged.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have tool/tts Text-to-speech and transcription provider/xai xAI (Grok) labels May 20, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Superseded by #32237 (teknium1 salvage with added regression tests + corrected repro). This PR's fix is correct but #32237 includes additional test coverage and a repro caveat.

teknium1 added a commit that referenced this pull request May 25, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline #29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
bridge25 pushed a commit to bridge25/hermes-agent that referenced this pull request May 27, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
@teknium1

Copy link
Copy Markdown
Contributor

Closing — merged via salvage PR #32237 (#32237).

Your one-line guard fix was cherry-picked onto main with authorship preserved. Salvage added 3 regression tests (multi_paragraph_emits_single_pause, single_paragraph_still_gets_first_sentence_pause, single_newline_still_gets_first_sentence_pause) so the fix can't silently regress.

One repro note for posterity — the example in your PR body ("Hello world.\n\nSecond paragraph.") actually didn't trip the bug because _XAI_FIRST_SENTENCE_RE has a 12-char floor on the first sentence. The bug DOES reproduce with anything longer (e.g. "Welcome to the demo of our new product line.\n\nIt has many features."), which is what the new tests use. Doesn't change the validity of the fix.

Thanks!

@teknium1 teknium1 closed this May 27, 2026
mathias3 pushed a commit to mathias3/hermes-agent that referenced this pull request May 28, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
Bryce-huang pushed a commit to wbkunlun/hermes-agent that referenced this pull request May 29, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.

#AI commit#
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline #29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
xyshanren pushed a commit to xyshanren/hermes-agent-cn that referenced this pull request Jun 25, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
Three new tests in tests/tools/test_tts_xai_speech_tags.py:

- multi_paragraph_emits_single_pause — the headline NousResearch#29417 case.
  Requires a first sentence of 12+ chars to hit the
  _XAI_FIRST_SENTENCE_RE length floor; the trivial 'Hello.\\n\\nWorld.'
  case dodged the bug by accident, which is why the PR's quoted
  repro didn't reproduce.  Uses the longer 'Welcome to the demo of
  our new product line.\\n\\nIt has many features.' shape that
  actually trips the bug.
- single_paragraph_still_gets_first_sentence_pause — sanity guard
  that the fix only suppresses the first-sentence pass when a
  paragraph pass injected [pause], so plain single-paragraph input
  still gets its leading pause.
- single_newline_still_gets_first_sentence_pause — single newline
  isn't a paragraph break, no [pause] from the paragraph pass, so
  the first-sentence pause MUST still fire.  Catches over-broad
  fixes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have provider/xai xAI (Grok) tool/tts Text-to-speech and transcription type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants