Skip to content

Feature/custom dictionary - #768

Open
abishekmuthian wants to merge 3 commits into
VocaHQ:mainfrom
abishekmuthian:feature/custom-dictionary
Open

Feature/custom dictionary#768
abishekmuthian wants to merge 3 commits into
VocaHQ:mainfrom
abishekmuthian:feature/custom-dictionary

Conversation

@abishekmuthian

@abishekmuthian abishekmuthian commented Sep 2, 2026

Copy link
Copy Markdown

Description

When the model incorrectly transcripts a word, there's currently no mechanism to fix the word for the next use. This PR implements a simple dictionary where the incorrect words can be replaced during post processing. It also adds a dictionary section to the dictation tab of the GUI.

Related Issue

Partly fixes #408, #475

Type of Change

  • [*] ✨ New feature (non-breaking change which adds functionality)

Checklist

  • [*] My code follows the code style of this project (black, isort)
  • [*] I have updated the documentation accordingly
  • [*] I have added tests to cover my changes
  • [*] All new and existing tests pass locally
  • [*] Pre-commit hooks pass

Screenshots (if applicable)

image

Additional Notes

It just adds the dictionary to the config.json , words can be added in the UI and the text is replaced during post-processing.

"text_injection": {
    "custom_dictionary": [
        {"spoken": "super base", "replacement": "Supabase"},
        {"spoken": "next door", "replacement": "Nextdoor"}
    ]
}

Discussion : #483

…ript correction

Add a custom dictionary that replaces commonly misheard phrases with the
intended term in the final transcript (e.g. 'super base' -> 'Supabase').

- New dictionary_corrector module: case-insensitive whole-word phrase
  replacement, longest-phrase-first, regex metacharacters escaped
- New text_injection.custom_dictionary config key (list of
  {spoken, replacement} pairs)
- Corrections applied in SpeechRecognitionManager._process_audio_buffer
  after voice-command processing, so injected text and Test Dictation
  both show corrected output; config re-read per segment so Settings
  changes apply without a restart
- Settings dialog: 'Custom Dictionary' group on the dictation page with
  add fields (Heard as / Replace with), a removal list, and empty state
- Tests for the corrector, config round-trip, recognition integration,
  and the settings dialog UI
The dictation page is already wrapped in a vertical ScrolledWindow, so
the dictionary group's inner scroller (min 48 / max 160 px, copied from
the auto-pause editor) created a nested scroll area that hid entries
behind its own scrollbar once more than ~2 corrections were added.

Pack the Gtk.ListBox directly into the group and let the page scroller
handle overflow, matching the existing no-inner-ScrolledWindow precedent
elsewhere in the dialog.
@netlify

netlify Bot commented Sep 2, 2026

Copy link
Copy Markdown

Deploy Preview for voca-linux canceled.

Name Link
🔨 Latest commit b661b98
🔍 Latest deploy log https://app.netlify.com/projects/voca-linux/deploys/6a97cfa061db0c0007153ef2

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Thanks @abishekmuthian. A maintainer will review it.


Meanwhile, connect with us:

Discord X

@github-actions github-actions Bot added documentation Improvements or additions to documentation app Core Python application (src, packaging) tests Test suite changes labels Sep 2, 2026
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds user-defined transcript corrections, persists them under text-injection settings, applies them during recognition, and exposes add/remove controls in the Dictation settings page.

  • Adds validation and whole-phrase, case-insensitive replacement logic.
  • Reloads dictionary entries for each recognized segment.
  • Adds GTK controls and configuration round-trip support.
  • Extends unit coverage for correction, persistence, UI helpers, and recognition integration.

Confidence Score: 3/5

The PR should not merge until dictionary corrections are ordered safely relative to voice commands and failed persistence is surfaced instead of appearing successful.

Command-like phrases can trigger transformations or destructive actions before correction, and a failed config write leaves the UI showing dictionary state that runtime transcription cannot read.

Files Needing Attention: src/vocalinux/speech_recognition/recognition_manager.py, src/vocalinux/ui/settings_dialog.py, src/vocalinux/speech_recognition/dictionary_corrector.py

Important Files Changed

Filename Overview
src/vocalinux/speech_recognition/dictionary_corrector.py Adds disk-backed dictionary loading and regex-based phrase correction; the broad exception handler violates repository guidance.
src/vocalinux/speech_recognition/recognition_manager.py Integrates corrections after command processing, allowing command-like misrecognitions to be consumed before correction.
src/vocalinux/ui/settings_dialog.py Adds dictionary editing controls, but failed persistence is presented from in-memory state as successful and new callbacks lack required annotations.
src/vocalinux/ui/config_manager.py Adds the empty custom_dictionary default under text_injection without changing existing configuration semantics.
tests/test_dictionary_corrector.py Covers phrase matching, boundaries, malformed entries, and disk-loading behavior.
tests/test_speech_recognition.py Covers correction integration with commands enabled and disabled, but not command-phrase collisions.
tests/test_settings_dialog.py Covers dictionary UI structure and helper behavior, but not failed persistence.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Speech engine transcript] --> B{Voice commands enabled?}
    B -- Yes --> C[CommandProcessor]
    B -- No --> D[Trim transcript]
    C --> E[Load custom dictionary]
    D --> E
    F[Settings dictionary editor] --> G[Save config.json]
    G --> E
    E --> H[Apply phrase corrections]
    H --> I[Text callbacks]
    C --> J[Action callbacks]
Loading

Reviews (1): Last reviewed commit: "docs(agents): document custom dictionary..." | Re-trigger Greptile

Comment on lines +3054 to +3056
dictionary_entries = load_custom_dictionary()
if dictionary_entries:
processed_text = apply_dictionary(processed_text, dictionary_entries)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Commands Run Before Corrections

When voice commands are enabled and a dictionary phrase overlaps a command such as delete that, period, or capitalize, CommandProcessor consumes or transforms the uncorrected phrase before apply_dictionary runs. The configured correction is therefore skipped, and action phrases can dispatch unintended operations such as deleting previously typed text.

Comment on lines +2287 to +2289
self.config_manager.set("text_injection", "custom_dictionary", entries)
self.config_manager.save_config()
self._refresh_custom_dictionary_list()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Failed Saves Appear Successful

When writing config.json fails, this code ignores save_config() returning False and refreshes the list from already-mutated in-memory state. The dialog shows and logs the dictionary edit as successful, but recognition reloads entries from disk, so it does not apply the change and the edit disappears after restart.

Comment on lines +41 to +43
except Exception as e:
logger.debug(f"Could not read {CONFIG_KEY} setting: {e}")
return []

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Dictionary Errors Are Overcaught

The new loader catches every Exception, so programming defects during path resolution or configuration traversal are silently treated as an unreadable dictionary. This also accompanies new add/remove callback signatures without the parameter and return annotations required by AGENTS.md; narrow the expected file/JSON exceptions and annotate those callbacks.

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@GrahamJenkins

Copy link
Copy Markdown
Contributor

Cross-posting on both issues, #767 #768 functionally overlap, two separate implementations. Maintainers should compare each on their merits and decide accordingly.

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

Labels

app Core Python application (src, packaging) documentation Improvements or additions to documentation tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Post-transcription enhancement via cloud LLMs (OpenRouter support, custom dictionary, user-defined prompts)

3 participants