From 8088ef9e002ec1429f673c23f9db36914894fb96 Mon Sep 17 00:00:00 2001 From: claude Date: Sun, 2 Aug 2026 22:29:57 +0400 Subject: [PATCH 1/3] mavgpud: build it with the rest, and ship the workstation config and unit (V-489) make build now catches a broken supervisor on homesrv. deploy/mavgpud.json carries the owner's gemma-4-12b line with the MTP draft model, passed to llama-server untouched. The unit is a systemd user unit because sudo on the workstation wants a password; lingering is the one command left to the owner. --- .gitignore | 1 + Makefile | 10 ++++++++-- deploy/mavgpud.json | 31 +++++++++++++++++++++++++++++++ deploy/mavgpud.service | 24 ++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 deploy/mavgpud.json create mode 100644 deploy/mavgpud.service diff --git a/.gitignore b/.gitignore index b6b2424..d240800 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /mavwaked /mavmaild /mavupdate +/mavgpud # Certs (private keys, don't commit) certs/ diff --git a/Makefile b/Makefile index 1721e39..7fbf5ff 100644 --- a/Makefile +++ b/Makefile @@ -16,11 +16,11 @@ PIPER_BIN := $(shell pwd)/deps/piper/piper PIPER_MODEL := $(shell pwd)/models/tts/ru_RU-irina-medium.onnx PIPER_ESPEAK := $(shell pwd)/deps/piper/espeak-ng-data -.PHONY: simulate stt-fixtures test-stt-golden all build build-stt build-tts build-daemon build-client build-waked build-web build-poll build-caldav clean test fmt-check vet run-stt run-tts run-web download-embedder deps-go eval-router eval-recall eval-phrasing eval-models +.PHONY: simulate stt-fixtures test-stt-golden all build build-stt build-tts build-daemon build-client build-waked build-web build-poll build-caldav clean test fmt-check vet run-stt run-tts run-web download-embedder deps-go eval-router eval-recall eval-phrasing eval-models build-gpud all: build -build: build-stt build-tts build-daemon build-client build-waked build-web build-poll build-caldav build-mail build-update +build: build-stt build-tts build-daemon build-client build-waked build-web build-poll build-caldav build-mail build-update build-gpud build-stt: CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" LD_LIBRARY_PATH="$(shell pwd)/deps/lib" \ @@ -59,6 +59,12 @@ build-mail: build-update: $(GO) build $(GOFLAGS) -o mavupdate ./cmd/mavupdate/ +# mavgpud runs on the workstation, not here. It is built with the rest so a +# broken supervisor is caught by `make build` on homesrv rather than by the +# workstation refusing to serve. Copy the binary over, do not `make deploy` it. +build-gpud: + $(GO) build $(GOFLAGS) -o mavgpud ./cmd/mavgpud/ + run-web: build-web ./mavweb -addr :9200 -voice 127.0.0.1:9100 diff --git a/deploy/mavgpud.json b/deploy/mavgpud.json new file mode 100644 index 0000000..fb33c2f --- /dev/null +++ b/deploy/mavgpud.json @@ -0,0 +1,31 @@ +{ + "listen": ":8080", + "llama_addr": "127.0.0.1:10000", + "llama_bin": "llama-server", + "llama_args": [ + "-m", "/mnt/D/AI/gemma4/gemma-4-12B-it-qat-UD-Q4_K_XL.gguf", + "-md", "/mnt/D/AI/gemma4/mtp-gemma-4-12B-it-BF16.gguf", + "-ngl", "99", + "-fa", "on", + "-np", "1", + "--host", "127.0.0.1", + "--port", "10000", + "--ctx-size", "32768", + "--threads", "6", + "--batch-size", "2048", + "--ubatch-size", "512", + "--jinja", + "--spec-type", "draft-mtp", + "--spec-draft-n-max", "2" + ], + + "kfd_root": "/sys/class/kfd/kfd/proc", + "drm_device": "/sys/class/drm/card1/device", + + "poll": "1s", + "idle_timeout": "15m", + "stop_grace": "20s", + "min_free_vram_bytes": 10737418240, + "evict_after_polls": 2, + "start_after_polls": 5 +} diff --git a/deploy/mavgpud.service b/deploy/mavgpud.service new file mode 100644 index 0000000..b200baa --- /dev/null +++ b/deploy/mavgpud.service @@ -0,0 +1,24 @@ +[Unit] +# Runs on the workstation (bugmachine), not on homesrv. Install as a systemd +# user unit and turn on lingering, so the card is supervised after a reboot +# with nobody logged in: +# +# scp mavgpud workpc:~/.local/bin/mavgpud +# scp deploy/mavgpud.json workpc:~/.config/mavgpud.json +# scp deploy/mavgpud.service workpc:~/.config/systemd/user/mavgpud.service +# ssh workpc 'systemctl --user daemon-reload && systemctl --user enable --now mavgpud' +# sudo loginctl enable-linger kami +Description=Maven GPU supervisor (holds llama-server while the card is free) +After=network.target + +[Service] +ExecStart=%h/.local/bin/mavgpud -config %h/.config/mavgpud.json +Restart=always +RestartSec=5 +# The card must come back when the supervisor goes down. mavgpud stops +# llama-server on SIGTERM, so give it longer than stop_grace to do that. +KillSignal=SIGTERM +TimeoutStopSec=60 + +[Install] +WantedBy=default.target From cc423567e7256eb6a095704d56288ddedc017cf4 Mon Sep 17 00:00:00 2001 From: claude Date: Sun, 2 Aug 2026 22:29:58 +0400 Subject: [PATCH 2/3] docs: record that contention is KFD presence, not a VRAM threshold (V-489) --- docs/offload.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/offload.md b/docs/offload.md index 7b2957f..4c6a6c8 100644 --- a/docs/offload.md +++ b/docs/offload.md @@ -71,6 +71,22 @@ It arbitrates nothing between callers. It reports whether it can take work and manages one process to back that answer. Maven never asks it to start anything and never learns that it did. +Contention is decided by presence under `/sys/class/kfd/kfd/proc`, not by a VRAM +threshold. A ROCm process registers there when it initialises HIP, before it +allocates anything. So the supervisor sees a contender during that job's startup, +and yields before the job loses the memory it asked for. A +threshold reads the card too late. By the time free VRAM has dropped, the other +job has already lost the allocation race. Free VRAM is still read, but only as a +precondition for loading, never as the eviction signal. One blind spot is known. +A job can take the card without registering on the KFD, as a Vulkan or a +video-decode job would. `describe()` logs every contender's comm, and that log is +how we find out whether the blind spot is real. + +`mavgpud` runs from a systemd unit on the workstation with +`deploy/mavgpud.json` as its config, and `llama_args` is passed to llama-server +untouched. The model, the context size, the layer count and the MTP flags are the +owner's business and not this daemon's schema. + ## What stays on homesrv, permanently The **embedder** (multilingual-e5-small, ONNX, CPU). It backs the classifier, which From eca41798bdd8ea1ee54d4cbaa6ab3c7518a5b2b2 Mon Sep 17 00:00:00 2001 From: claude Date: Sun, 2 Aug 2026 22:44:10 +0400 Subject: [PATCH 3/3] mavgpud: turn gemma's thinking off in the chat template (V-489) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner's call, 02-08-2026. Without it the 12B spends the reply budget on reasoning tokens and answers empty at low max_tokens. Verified on the box: "Столица Франции?" now answers "Париж" with no reasoning_content. --- deploy/mavgpud.json | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/mavgpud.json b/deploy/mavgpud.json index fb33c2f..41d001d 100644 --- a/deploy/mavgpud.json +++ b/deploy/mavgpud.json @@ -15,6 +15,7 @@ "--batch-size", "2048", "--ubatch-size", "512", "--jinja", + "--chat-template-kwargs", "{\"enable_thinking\":false}", "--spec-type", "draft-mtp", "--spec-draft-n-max", "2" ],