Skip to content

Quit phrases never match when Whisper transcribes the comma ("Goodbye, Jarvis.") #23

Description

@pikedave

Two of the three quit-phrase checks in main.py still match against raw text.lower(), so a quit phrase that Whisper transcribes with an interior comma never fires. The natural, grammatically-correct way to say it ("Goodbye, Jarvis.") is exactly the case that fails.

Observed on: 84b3a6c, Python 3.12.14, macOS 26.6.2 arm64, small.en via mlx-whisper.

What happens

Say "goodbye jarvis" naturally. Whisper transcribes it as Goodbye, Jarvis. with the vocative comma. The session carries on as if nothing was said, and the reply is the agent answering the words as a normal turn. Nothing in the log indicates a quit was attempted, because none was.

It reads like a process that will not die. It was never told to quit.

Where

backtalk/main.py, on 84b3a6c:

895:            elif not expired and not any(q in text.lower()
896:                                         for q in QUIT_PHRASES):
899:        if any(q in text.lower() for q in QUIT_PHRASES):

Line 899 is the main turn handler, so it is the one users actually hit.

The fix already exists in the same file. _norm_speech() at line 127 was written for precisely this, and its docstring says so: "Whisper loves interior commas ("yes, confirm"); end-stripping alone misses them." The sibling confirm check at line 891 already routes through it, and the permission-ask quit override at line 876 got the treatment too:

if _norm_speech(text) in {_norm_speech(q) for q in QUIT_PHRASES}:

Lines 895 and 899 were simply missed.

Reproduction

from backtalk.config import CFG
import backtalk.main as m

t = "Goodbye, Jarvis."                                     # real Whisper output
print(any(q in t.lower()          for q in CFG["quit_phrases"]))  # False  <- current
print(any(q in m._norm_speech(t)  for q in CFG["quit_phrases"]))  # True

Default quit_phrases from config.py:251 are all lowercase letters and spaces, so normalising the transcript alone is enough for the defaults.

Note on the workaround we are running

We patched both sites to any(q in _norm_speech(text) for q in QUIT_PHRASES) locally and it works, but that keeps substring matching, which we suspect is not what you want. The exact-match shape you already used at line 876, normalising both sides, looks like the better answer, and it also respects the reasoning in your own comment there about "No! Don't hang up, skip it" needing to stay a deny rather than kill the session. We would rather converge on your idiom than have you take ours. Happy to open a PR in whichever shape you prefer.

Related: this masked a second, more serious bug underneath it, filed as #24. Note that fixing this issue alone will make that deadlock reachable by the normal exit route for everyone, where previously only Ctrl-C hit it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions