A lightweight AI-powered desktop assistant that helps users quickly understand unfamiliar terms or text while using their computer.
This tool runs in the background and allows users to:
The goal is to create a system-wide learning copilot that works across all applications (browser, IDE, PDF reader, etc.).
is_free providers with gpt-4.1-mini as fallbackThis project uses uv for dependency and environment management.
Install uv:
pip install uv
Create and activate environment:
uv venv
uv sync
User highlights text anywhere on screen
Presses the leader shortcut Alt + Q followed by a mode key (see hotkeys below)
Program:
Ctrl + CVoice mode follows the same controller pipeline, but starts with microphone capture instead of clipboard selection:
Alt + Q β VDefine the following word or term in {target_language}:
{text}
Explain the meaning of the following text in {target_language}.
Use clear language, intuition, and examples:
{text}
Summarize the following text in {target_language}:
{text}
Rewrite the following text in {target_language}. Keep the meaning but improve clarity and style:
{text}
User types a free-form instruction in the floating Alt + Q β P dialog. The instruction is applied to the currently highlighted text.
learning-agent/
β
βββ configs/
β βββ llm_api/ # LLM API JSON configs by family and model
β βββ gpt/ # GPT models (paid)
β βββ qwen/ # Qwen models (free tier available)
β βββ ... # Other families
β
βββ core/
β βββ hotkey.py # Leader-key global hotkey listener (Alt+Q chord)
β βββ orchestrator.py # Pipeline: hotkey β clipboard/voice β prompt β LLM β UI
β βββ free_llm_manager.py # Round-robin free-provider routing with fallback
β βββ wake_word_service.py # Continuous wake word detection via faster-whisper
β βββ browser_service.py # YouTube search-and-play browser integration
β βββ ... # clipboard, OCR, STT, TTS, settings, β¦
β
βββ llm/
β βββ base.py # LLM interface
β βββ openai_provider.py # OpenAI / OpenAI-compatible provider
β βββ openrouter_provider.py
β
βββ prompts/
β βββ templates.py # Prompt templates (Definition, Explain, Summary, Rewrite, Custom)
β
βββ session/
β βββ manager.py # Session & conversation state
β
βββ ui/
β βββ main_window.py # Main chat window (PySide6)
β βββ chat_widget.py # Chat message display
β βββ input_box.py # User input component
β βββ prompt_input_dialog.py # Floating custom-prompt dialog (Alt+Q β P)
β βββ settings_popup.py # Compact settings popup
β
βββ main.py # Entry point
β
βββ README.md
python main.py
The app can be bundled into a single Windows .exe with PyInstaller. Runtime paths now resolve bundled provider configs from the packaged data directory and look for an optional .env next to the executable.
.\scripts\build_exe.ps1
The script calls learning-agent.spec, which bundles configs\llm_api into the executable and keeps the build definition checked into the repo.
The build produces dist\learning-agent.exe. Keep API keys external by placing a .env file next to the executable or by setting the required environment variables on the target machine. Session and settings data still live under %APPDATA%\learning-agent.
Highlight any text
Press Alt + Q (the leader key) then a mode key:
| Second key | Action |
|---|---|
D | Definition mode |
E | Explain mode |
S | Summary mode |
R | Rewrite mode |
P | Custom prompt (opens floating input dialog) |
V | Voice mode (mic capture) |
W | Toggle wake word listener |
H | Hide / show the chat window |
L | Toggle between the chosen language and English |
X | Exit the program |
Esc β minimize the chat window to trayStop button β cancel the current requestCheck chat window output
Press the settings icon to open the popup and disable hotkeys if needed
If OCR is enabled, click the OCR context toggle on a user query to reveal the captured screen text above that query
The chosen language defaults to Vietnamese and is saved between runs. Screen OCR is off by default and can be enabled from the settings popup. When enabled, the app uses the selected text to localize a smaller OCR region before scanning it, but only for Definition mode.
Wake word mode (Alt + Q β W) toggles the continuous wake word listener. When active, the app listens in the background via faster-whisper and triggers voice mode automatically when the configured wake word is detected. The default wake word is Mario and the default model is small. Override them with LEARNING_AGENT_WAKE_WORD and LEARNING_AGENT_WAKE_WORD_DEVICE.
Free LLM mode can be selected from the settings popup. In this mode the app automatically picks an available is_free provider from configs/llm_api/ (round-robin, starting from the last known-good one) and falls back to gpt-4.1-mini if all free providers fail.
Browser integration: the assistant can open YouTube videos on request. When the selected LLM emits a <<<BROWSER_ACTION>>> block, the app parses it and opens the matching video in the default browser.
Voice mode uses sounddevice for microphone capture, openai/whisper-large-v3-turbo through the Transformers Whisper loader for the default English/non-Vietnamese STT path, faster-whisper for the fallback Whisper STT path, sherpa-onnx for the Vietnamese Zipformer STT path, and Chatterbox for the default non-Vietnamese TTS path. For Vietnamese, the app now defaults to hynt/Zipformer-30M-RNNT-6000h for STT and VieNeu TTS v1 for speech. The settings popup includes a VieNeu model dropdown with VieNeu TTS v1, VieNeu TTS 0.3B Q4 GGUF, and VieNeu TTS 0.3B. The voice preset dropdown refreshes when you switch engines and currently follows VieNeu's published preset catalog: Vinh, Binh, Tuyen, Doan, Ly, and Ngoc. The selected model and preset are saved between runs. The Vietnamese reply is fed to VieNeu sentence by sentence so playback can begin sooner. If you need to force a device override, prefer cuda or cuda:0; the TTS backends normalize gpu to CUDA when the installed PyTorch build exposes it. The current VieNeu models are loaded through the SDK's standard backend, which handles both transformer and GGUF backbones, and the codec path depends on torchao so the local VieNeu loader can initialize correctly. If the non-Vietnamese TTS model cannot be loaded, the app falls back to the local Windows speech engine so the response is still spoken. Chatterbox uses CUDA automatically when the installed PyTorch build exposes it.
If you want to override the English model, set LEARNING_AGENT_VOICE_STT_MODEL; to override the Vietnamese models, set LEARNING_AGENT_VOICE_STT_VI_MODEL, LEARNING_AGENT_VOICE_TTS_VI_REPO_ID, or LEARNING_AGENT_VOICE_TTS_VI_VOICE_NAME as needed. The app will use the Vietnamese engine when the selected language is Vietnamese and the default engines for other languages.
Run the unit tests with:
pytest
MIT License (recommended for open-source projects)
A lightweight AI-powered desktop assistant that helps users quickly understand unfamiliar terms or text while using their computer.
This tool runs in the background and allows users to:
The goal is to create a system-wide learning copilot that works across all applications (browser, IDE, PDF reader, etc.).
is_free providers with gpt-4.1-mini as fallbackThis project uses uv for dependency and environment management.
Install uv:
pip install uv
Create and activate environment:
uv venv
uv sync
User highlights text anywhere on screen
Presses the leader shortcut Alt + Q followed by a mode key (see hotkeys below)
Program:
Ctrl + CVoice mode follows the same controller pipeline, but starts with microphone capture instead of clipboard selection:
Alt + Q β VDefine the following word or term in {target_language}:
{text}
Explain the meaning of the following text in {target_language}.
Use clear language, intuition, and examples:
{text}
Summarize the following text in {target_language}:
{text}
Rewrite the following text in {target_language}. Keep the meaning but improve clarity and style:
{text}
User types a free-form instruction in the floating Alt + Q β P dialog. The instruction is applied to the currently highlighted text.
learning-agent/
β
βββ configs/
β βββ llm_api/ # LLM API JSON configs by family and model
β βββ gpt/ # GPT models (paid)
β βββ qwen/ # Qwen models (free tier available)
β βββ ... # Other families
β
βββ core/
β βββ hotkey.py # Leader-key global hotkey listener (Alt+Q chord)
β βββ orchestrator.py # Pipeline: hotkey β clipboard/voice β prompt β LLM β UI
β βββ free_llm_manager.py # Round-robin free-provider routing with fallback
β βββ wake_word_service.py # Continuous wake word detection via faster-whisper
β βββ browser_service.py # YouTube search-and-play browser integration
β βββ ... # clipboard, OCR, STT, TTS, settings, β¦
β
βββ llm/
β βββ base.py # LLM interface
β βββ openai_provider.py # OpenAI / OpenAI-compatible provider
β βββ openrouter_provider.py
β
βββ prompts/
β βββ templates.py # Prompt templates (Definition, Explain, Summary, Rewrite, Custom)
β
βββ session/
β βββ manager.py # Session & conversation state
β
βββ ui/
β βββ main_window.py # Main chat window (PySide6)
β βββ chat_widget.py # Chat message display
β βββ input_box.py # User input component
β βββ prompt_input_dialog.py # Floating custom-prompt dialog (Alt+Q β P)
β βββ settings_popup.py # Compact settings popup
β
βββ main.py # Entry point
β
βββ README.md
python main.py
The app can be bundled into a single Windows .exe with PyInstaller. Runtime paths now resolve bundled provider configs from the packaged data directory and look for an optional .env next to the executable.
.\scripts\build_exe.ps1
The script calls learning-agent.spec, which bundles configs\llm_api into the executable and keeps the build definition checked into the repo.
The build produces dist\learning-agent.exe. Keep API keys external by placing a .env file next to the executable or by setting the required environment variables on the target machine. Session and settings data still live under %APPDATA%\learning-agent.
Highlight any text
Press Alt + Q (the leader key) then a mode key:
| Second key | Action |
|---|---|
D | Definition mode |
E | Explain mode |
S | Summary mode |
R | Rewrite mode |
P | Custom prompt (opens floating input dialog) |
V | Voice mode (mic capture) |
W | Toggle wake word listener |
H | Hide / show the chat window |
L | Toggle between the chosen language and English |
X | Exit the program |
Esc β minimize the chat window to trayStop button β cancel the current requestCheck chat window output
Press the settings icon to open the popup and disable hotkeys if needed
If OCR is enabled, click the OCR context toggle on a user query to reveal the captured screen text above that query
The chosen language defaults to Vietnamese and is saved between runs. Screen OCR is off by default and can be enabled from the settings popup. When enabled, the app uses the selected text to localize a smaller OCR region before scanning it, but only for Definition mode.
Wake word mode (Alt + Q β W) toggles the continuous wake word listener. When active, the app listens in the background via faster-whisper and triggers voice mode automatically when the configured wake word is detected. The default wake word is Mario and the default model is small. Override them with LEARNING_AGENT_WAKE_WORD and LEARNING_AGENT_WAKE_WORD_DEVICE.
Free LLM mode can be selected from the settings popup. In this mode the app automatically picks an available is_free provider from configs/llm_api/ (round-robin, starting from the last known-good one) and falls back to gpt-4.1-mini if all free providers fail.
Browser integration: the assistant can open YouTube videos on request. When the selected LLM emits a <<<BROWSER_ACTION>>> block, the app parses it and opens the matching video in the default browser.
Voice mode uses sounddevice for microphone capture, openai/whisper-large-v3-turbo through the Transformers Whisper loader for the default English/non-Vietnamese STT path, faster-whisper for the fallback Whisper STT path, sherpa-onnx for the Vietnamese Zipformer STT path, and Chatterbox for the default non-Vietnamese TTS path. For Vietnamese, the app now defaults to hynt/Zipformer-30M-RNNT-6000h for STT and VieNeu TTS v1 for speech. The settings popup includes a VieNeu model dropdown with VieNeu TTS v1, VieNeu TTS 0.3B Q4 GGUF, and VieNeu TTS 0.3B. The voice preset dropdown refreshes when you switch engines and currently follows VieNeu's published preset catalog: Vinh, Binh, Tuyen, Doan, Ly, and Ngoc. The selected model and preset are saved between runs. The Vietnamese reply is fed to VieNeu sentence by sentence so playback can begin sooner. If you need to force a device override, prefer cuda or cuda:0; the TTS backends normalize gpu to CUDA when the installed PyTorch build exposes it. The current VieNeu models are loaded through the SDK's standard backend, which handles both transformer and GGUF backbones, and the codec path depends on torchao so the local VieNeu loader can initialize correctly. If the non-Vietnamese TTS model cannot be loaded, the app falls back to the local Windows speech engine so the response is still spoken. Chatterbox uses CUDA automatically when the installed PyTorch build exposes it.
If you want to override the English model, set LEARNING_AGENT_VOICE_STT_MODEL; to override the Vietnamese models, set LEARNING_AGENT_VOICE_STT_VI_MODEL, LEARNING_AGENT_VOICE_TTS_VI_REPO_ID, or LEARNING_AGENT_VOICE_TTS_VI_VOICE_NAME as needed. The app will use the Vietnamese engine when the selected language is Vietnamese and the default engines for other languages.
Run the unit tests with:
pytest
MIT License (recommended for open-source projects)