Skip to content
deniskostadinov1995Public

About

Frees your GPU for games: unloads Ollama models from VRAM and pauses Home Assistant AI automations while a game is running.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

GPU Guard

Gives your GPU back to whatever game you launch. While a game runs, GPU Guard unloads your local Ollama models from VRAM. It also tells Home Assistant to pause the automations that would load them straight back. When the game exits, everything comes back on its own.

Platform Python Dependencies License

If you run a local AI assistant (Ollama + Home Assistant voice, Whisper, etc.) on your gaming PC, the models sit in VRAM all day. On my machine that was ~11.8 GB: a 14B model kept resident "forever" plus a GPU speech-to-text container. GPU Guard hands all of it to the game (12,882 MiB → 1,048 MiB measured) and quietly restores it afterwards.


How it works

game starts ──► gpu_guard.py (hidden, runs on the PC)
                  ├─ unloads every Ollama model from VRAM   (/api/generate keep_alive:0)
                  ├─ optionally stops a GPU Docker container (e.g. faster-whisper-gpu)
                  ├─ input_boolean.gaming_mode = on          (Home Assistant REST API)
                  └─ refreshes input_datetime.gaming_heartbeat every 60 s

while gaming   ── HA automations guarded by gaming_mode don't run.
                  A model you load on purpose (e.g. a voice command) is left alone
                  for 150 s, then its VRAM is reclaimed again.

game exits     ──► 45 s grace ─► container back + gaming_mode = off

How a game is recognised

  1. Game folders: any process running from a folder in game_dirs, from every Steam library (read live from libraryfolders.vdf) or from an Epic Games install (read from Epic's manifests).
  2. Named executables: anything listed in extra_game_exes.
  3. Fullscreen fallback: the foreground window covers a whole monitor and its exe isn't in ignore_exes. Browsers, video players, editors, launchers etc. are ignored, so fullscreen YouTube doesn't count.

Gaming mode lasts as long as the game process lives, so alt-tabbing out doesn't end it.

Fail-safes

  • Heartbeat watchdog: if the PC crashes or the guard dies mid-game, the heartbeat goes stale. A Home Assistant automation then clears gaming_mode within 10 minutes, so your assistant never stays muted.
  • Container recovery: an explicit docker stop overrides a container's unless-stopped policy. So on startup the guard restarts the container if it's stopped and no game is running, and it keeps retrying a failed docker start every 60 s.
  • Loud failures: a broken detector looks exactly like "no game running". If detection fails for a solid minute, the guard raises a persistent notification in Home Assistant, and clears it on recovery. Repeated log lines are collapsed so real events aren't flushed out of the log.

Requirements

  • Windows 10/11
  • Python 3.8+ (standard library only, nothing to pip install)
  • Ollama: the main thing being freed
  • Optional: Home Assistant, to pause automations while gaming
  • Optional: Docker Desktop, if you want a GPU container stopped while gaming

Installation

  1. Download this repository (Code → Download ZIP) and extract it somewhere permanent, e.g. C:\Tools\gpu-guard.
  2. Copy config.example.json to config.json and edit it (see Configuration).
  3. (Home Assistant users) Install the package from homeassistant/gaming_mode.yaml. It creates input_boolean.gaming_mode, input_datetime.gaming_heartbeat and the watchdog automation. Instructions are in the file.
  4. Test it in a console first, so you can watch the log:
    python gpu_guard.py
    Start a game. You should see it detected and the models unloaded.
  5. Install it as a hidden scheduled task that starts at logon:
    powershell -ExecutionPolicy Bypass -File .\install_task.ps1

Configuration

All settings live in config.json. Anything you leave out falls back to the defaults in gpu_guard.py. Restart the task after editing:

Stop-ScheduledTask -TaskName GPUGuard; Start-ScheduledTask -TaskName GPUGuard
Key Default What it does
ollama_url http://127.0.0.1:11434 Your Ollama server
ha_url http://homeassistant.local:8123 Your Home Assistant
ha_token / ha_token_file A Home Assistant long-lived access token, inline or in a file. Leave empty to run without HA.
game_dirs ["D:\\Games"] Extra folders that contain games (Steam & Epic are found automatically)
extra_game_exes [] Games the folder rules miss, e.g. ["eldenring.exe"]
fullscreen_detection true Set false to rely on game folders only
ignore_exes (built-in list) Exes that never count as games for the fullscreen fallback. This replaces the built-in list rather than extending it, so copy the default list from gpu_guard.py and append to it.
model_idle_grace_seconds 150 How long a model loaded on purpose mid-game keeps its VRAM
exit_grace_seconds 45 Delay after the game closes before everything is restored
stop_whisper_gpu false Stop a GPU Docker container while gaming
whisper_container faster-whisper-gpu Name of that container
docker_exe docker Path to docker.exe if it isn't on PATH
poll_seconds / heartbeat_seconds 5 / 60 Detection and heartbeat intervals

Pausing your own Home Assistant automations

Add this condition to any automation that would load a model (pre-warming, periodic LLM tasks, etc.):

conditions:
  - condition: state
    entity_id: input_boolean.gaming_mode
    state: "off"

Voice commands still work mid-game: the model loads and answers, and 150 s later the VRAM goes back to the game. If a speech-to-text container is stopped while gaming, voice input is down until the game exits. Point your Assist pipeline at a CPU STT engine if you'd rather keep voice working.


Checking on it

Get-Content .\gpu_guard.log -Tail 20
Get-ScheduledTask -TaskName GPUGuard | Get-ScheduledTaskInfo

The log rotates at 1 MB (gpu_guard.log.1).

Turning it off / uninstalling

Disable-ScheduledTask -TaskName GPUGuard; Stop-ScheduledTask -TaskName GPUGuard
# or remove it completely:
Unregister-ScheduledTask -TaskName GPUGuard -Confirm:$false

Home Assistant then never sees gaming_mode turn on, so everything behaves as before.


Design notes: the HMONITOR overflow bug

One real-world failure is worth documenting. A game ran laggy because the guard had silently been dead for ~15 hours. The poll loop threw OverflowError: int too long to convert every 5 seconds, so no game was ever detected.

  • Cause: GetMonitorInfoW was called through ctypes without argtypes. ctypes then passes the handle as a C int, but an HMONITOR is a real pointer (e.g. 0xffffffff9cdb0e45) that doesn't fit. Because the pointer value depends on address layout, it worked on some boots and not others.
  • Fixes: argtypes declared on every handle-taking Win32 call. Epic installs auto-discovered so they don't depend on fullscreen detection. The fullscreen heuristic isolated in its own try/except so it can never abort the folder scan. And the "loud failure" notification described above.

License

MIT © Denis Kostadinov

About

Frees your GPU for games: unloads Ollama models from VRAM and pauses Home Assistant AI automations while a game is running.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages