diff options
Diffstat (limited to 'desktop/modules/ai')
| -rw-r--r-- | desktop/modules/ai/AiModule.qml | 16 | ||||
| -rw-r--r-- | desktop/modules/ai/AiPage.qml | 2 | ||||
| -rw-r--r-- | desktop/modules/ai/README.md | 10 | ||||
| -rwxr-xr-x | desktop/modules/ai/ai-state.sh | 27 | ||||
| -rwxr-xr-x | desktop/modules/ai/test-ai-state.sh | 22 |
5 files changed, 16 insertions, 61 deletions
diff --git a/desktop/modules/ai/AiModule.qml b/desktop/modules/ai/AiModule.qml index d58ebfe..4c50224 100644 --- a/desktop/modules/ai/AiModule.qml +++ b/desktop/modules/ai/AiModule.qml @@ -41,16 +41,12 @@ Module { sd: "stable-diffusion.cpp", assistant: "Desktop assistant", chat: "Local chat", - imggen: "imggen", - fanfic: "Fanfictioner", }) readonly property string assistantSh: Quickshell.env("HOME") + "/Programming/GIT/desktop-assistant/assistant.sh" - // Each project's own control. Fanfictioner has no start, a run needs a - // story file, and its stop needs the pid, see stop(). llamachat has no - // restart, and --quit answers before the app is gone, so a --daemon + // Each project's own control. llamachat has no restart, and --quit answers before the app is gone, so a --daemon // straight after would find it still running and do nothing: wait for // --ping to fail first, up to 5s. readonly property var controls: ({ @@ -59,7 +55,6 @@ Module { chat: { start: ["llamachat", "--daemon"], stop: ["llamachat", "--quit"], restart: ["sh", "-c", "llamachat --quit; for _ in $(seq 50); do " + "llamachat --ping || break; sleep 0.1; done; exec llamachat --daemon"] }, - imggen: { start: ["imggen", "start"], stop: ["imggen", "stop"] }, }) function canStart(app) { return controls[app.name] !== undefined; } @@ -75,14 +70,7 @@ Module { } function stop(app) { - if (app.name !== "fanfic") { - exec(controls[app.name].stop); - return; - } - // The sd-cli children first, then the script, by pid only: a name - // match would take unrelated sd-cli and python processes with it. - if (!/^[0-9]+$/.test(app.detail)) return; - exec(["sh", "-c", 'pkill -TERM -P "$1"; kill -TERM "$1"', "sh", app.detail]); + exec(controls[app.name].stop); } // The router frees the model's VRAM; the next request for it loads it diff --git a/desktop/modules/ai/AiPage.qml b/desktop/modules/ai/AiPage.qml index 369c1b5..c1cb07c 100644 --- a/desktop/modules/ai/AiPage.qml +++ b/desktop/modules/ai/AiPage.qml @@ -68,7 +68,7 @@ Column { detail: { if (!modelData.running) return "Stopped"; if (modelData.detail === "") return "Running"; - return "Running · " + (modelData.name === "fanfic" ? "pid " : "") + modelData.detail; + return "Running · " + modelData.detail; } action: modelData.running ? "Stop" : page.ai.canStart(modelData) ? "Start" : "" danger: modelData.running diff --git a/desktop/modules/ai/README.md b/desktop/modules/ai/README.md index e71159b..d87087a 100644 --- a/desktop/modules/ai/README.md +++ b/desktop/modules/ai/README.md @@ -18,10 +18,10 @@ llama's state comes from its API: `/models` for the loaded model, then `autoload=false` matters: a plain `/slots?model=` on an unloaded model loads it into VRAM, which is how this was found. -The sd row covers two processes. A running `sd-cli`, the one-shot runs -fanfictioner makes, reads up and generating with its model marked `(sd-cli)`, -whatever the web UI is doing: it holds VRAM for as long as it lives. The first -version watched only `sd-server` and showed the engine down mid-run. +The sd row covers two processes. A running one-shot `sd-cli` reads up and +generating with its model marked `(sd-cli)`, whatever the web UI is doing: it +holds VRAM for as long as it lives. The first version watched only +`sd-server` and showed the engine down mid-run. sd-server has no progress endpoint. Its log, `~/.cache/sd-server.log`, streams progress bars while it generates, so the row reads busy while the log was @@ -33,8 +33,6 @@ written in the last 5s. A step slower than that reads idle. | --- | --- | --- | --- | --- | | desktop-assistant | `assistant.sh status` | `assistant.sh start` | `assistant.sh stop` | `assistant.sh restart` | | local chat | `llamachat --ping` | `llamachat --daemon` | `llamachat --quit` | quit, wait for `--ping` to fail (5s at most), `--daemon` | -| imggen | `imggen status` | `imggen start` (default model) | `imggen stop` | none | -| fanfictioner | `pgrep` on `python3 .../fanfictioner` | none | TERM its children, then it, by pid | none | Restart shows only while an app is running. llamachat's `--quit` answers before the app has exited, so a `--daemon` sent straight after finds it still diff --git a/desktop/modules/ai/ai-state.sh b/desktop/modules/ai/ai-state.sh index 8b10368..a4406ce 100755 --- a/desktop/modules/ai/ai-state.sh +++ b/desktop/modules/ai/ai-state.sh @@ -12,19 +12,17 @@ # GNU General Public License for more details. # # One sweep of the local AI stack for the drawer's AI page. Always prints -# these six lines, tab separated, and exits 0: +# these four lines, tab separated, and exits 0: # # engine<TAB>llama<TAB>up|down<TAB>idle|busy<TAB>model # engine<TAB>sd<TAB>up|down<TAB>idle|busy<TAB>model, "(sd-cli)" for a CLI run # app<TAB>assistant<TAB>running|stopped<TAB>- # app<TAB>chat<TAB>running|stopped<TAB>- -# app<TAB>imggen<TAB>running|stopped<TAB>model -# app<TAB>fanfic<TAB>running|stopped<TAB>pid # # An empty value is "-". A probe that fails reads as down or stopped, not as # an error: every row is something that may simply not be running. # -# The test stubs curl, pgrep, llamachat and imggen on PATH and points +# The test stubs curl, pgrep and llamachat on PATH and points # AI_ASSISTANT and AI_SD_LOG at fixtures; see test-ai-state.sh. set -u @@ -65,7 +63,7 @@ model_of() { sd() { local line busy=idle mtime - # A one-shot sd-cli (fanfictioner runs them) holds VRAM and generates for + # A one-shot sd-cli holds VRAM and generates for # as long as it lives, so it outranks whatever the web UI is doing. if line="$(pgrep -axo sd-cli)"; then row engine sd up busy "$(model_of "$line") (sd-cli)" @@ -81,8 +79,6 @@ sd() { } apps() { - local out pid - if "$ASSISTANT" status >/dev/null 2>&1; then row app assistant running - else @@ -94,23 +90,6 @@ apps() { else row app chat stopped - fi - - # imggen status exits 0 either way: the daemon's JSON when it is up, - # "daemon down" when it is not. - out="$(imggen status 2>/dev/null)" - if [[ "$out" == "{"* ]]; then - row app imggen running "$(jq -r '.model // "-"' <<<"$out" 2>/dev/null || echo -)" - else - row app imggen stopped - - fi - - # It runs through env, so the command line is python3 then the script, - # by path from ~/bin or by ./fanfictioner from the repo. - if pid="$(pgrep -u "$USER" -fo '^[^ ]*python3[^ ]* [^ ]*fanfictioner( |$)')"; then - row app fanfic running "$pid" - else - row app fanfic stopped - - fi } llama diff --git a/desktop/modules/ai/test-ai-state.sh b/desktop/modules/ai/test-ai-state.sh index e3e8ba0..aac83fb 100755 --- a/desktop/modules/ai/test-ai-state.sh +++ b/desktop/modules/ai/test-ai-state.sh @@ -11,8 +11,8 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # -# The one runnable check for ai-state.sh. It puts stub curl, pgrep, -# llamachat and imggen on PATH and a stub assistant.sh beside them, then runs +# The one runnable check for ai-state.sh. It puts stub curl, pgrep +# and llamachat on PATH and a stub assistant.sh beside them, then runs # the real script, so nothing here touches the live stack. T_* variables pick # the state each stub reports. # @@ -57,9 +57,6 @@ case "$*" in *sd-server*) [[ -n "${T_SD:-}" ]] || exit 1 echo "4242 sd-server --listen-port 7860 --diffusion-model /data/SD/z_image_turbo-Q8_0.gguf --vae /data/SD/vae/flux1-ae.safetensors" ;; - *fanfictioner*) - [[ -n "${T_FANFIC:-}" ]] || exit 1 - echo 31337 ;; *) exit 1 ;; esac STUB @@ -69,13 +66,6 @@ cat > "$stub/llamachat" <<'STUB' [[ "$1" == --ping && -n "${T_CHAT:-}" ]] STUB -# The real imggen exits 0 either way and says which on stdout. -cat > "$stub/imggen" <<'STUB' -#!/bin/bash -[[ "$1" == status ]] || exit 1 -if [[ -n "${T_IMG:-}" ]]; then echo '{"model": "realvis", "ready": true}'; else echo "daemon down"; fi -STUB - cat > "$stub/assistant.sh" <<'STUB' #!/bin/bash [[ "$1" == status && -n "${T_ASSIST:-}" ]] @@ -106,7 +96,7 @@ run() { bash "$here/ai-state.sh" } -apps_down="$(l app assistant stopped -; l app chat stopped -; l app imggen stopped -; l app fanfic stopped -)" +apps_down="$(l app assistant stopped -; l app chat stopped -)" want="$(l engine llama down idle -; l engine sd down idle -) $apps_down" @@ -131,7 +121,7 @@ touch -d '1 minute ago' "$log" got="$(run T_SD=1 | sed -n 2p)" check "sd running, log quiet" "$(l engine sd up idle z_image_turbo-Q8_0.gguf)" "$got" -# A one-shot sd-cli (fanfictioner's) holds VRAM and is generating for as +# A one-shot sd-cli holds VRAM and is generating for as # long as it runs, whatever the web UI is doing. Its prompt is free text, so # a "-m" inside it must not be read as the model. got="$(run T_CLI=1 | sed -n 2p)" @@ -140,8 +130,8 @@ check "sd-cli running" "$(l engine sd up busy "Krea-2-Turbo-Q6_K.gguf (sd-cli)") got="$(run T_CLI=1 T_SD=1 | sed -n 2p)" check "sd-cli wins over an idle web UI" "$(l engine sd up busy "Krea-2-Turbo-Q6_K.gguf (sd-cli)")" "$got" -want="$(l app assistant running -; l app chat running -; l app imggen running realvis; l app fanfic running 31337)" -got="$(run T_ASSIST=1 T_CHAT=1 T_IMG=1 T_FANFIC=1 | tail -n4)" +want="$(l app assistant running -; l app chat running -)" +got="$(run T_ASSIST=1 T_CHAT=1 | tail -n2)" check "every app running" "$want" "$got" printf '\n%d passed, %d failed\n' "$pass" "$fail" |
