Seed Assistent personas as overlay folders and tighten Ollama/Assistent glue.

gpu-rent now writes personas/<id>/ on the VM (not legacy personas.json), adds seed-personas/doctor checks, and shortens mid/high keep-alive now that Assistent parks the LLM before Generate.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-22 01:00:14 +03:00
co-authored by Cursor
parent 789fa26918
commit 03ba4cb6ed
22 changed files with 430 additions and 53 deletions
+3 -2
View File
@@ -16,9 +16,10 @@ def test_collect_links_swarm_and_ollama(monkeypatch):
links = collect_access_links(_Cfg(), tunneled=True)
labels = [x.label for x in links]
assert "SwarmUI UI" in labels
assert "Assistent" in labels
assert "SwarmUI MCP" in labels
assert "Ollama API" in labels
assert any("17811" in x.url for x in links)
assert any(x.label == "Assistent" and "вкладка" in x.note for x in links)
def test_collect_links_no_tunnel():
@@ -57,7 +58,7 @@ def test_access_panel_hides_stale_llm_error_when_ollama_ok(monkeypatch):
{
"name": "ollama",
"ok": True,
"detail": "1 models (huihui_ai/qwen2.5-vl-abliterated:7b)",
"detail": "1 models (huihui_ai/qwen3-vl-abliterated:8b-instruct)",
}
],
}
+81
View File
@@ -0,0 +1,81 @@
"""Unit tests for assistent personas overlay seed helpers."""
from __future__ import annotations
import json
from pathlib import Path
from unittest.mock import MagicMock
import pytest
from gpu_rent.provision import _safe_persona_id, count_wanted_models_on_vm, seed_assistent_personas
def test_safe_persona_id():
assert _safe_persona_id("neutral") == "neutral"
assert _safe_persona_id("lewd_v2") == "lewd_v2"
assert _safe_persona_id("../x") is None
assert _safe_persona_id("a/b") is None
assert _safe_persona_id("") is None
def test_seed_assistent_personas_writes_overlay(tmp_path: Path, monkeypatch):
yaml_path = tmp_path / "assistent-personas.yaml"
yaml_path.write_text(
"default: cinema\n"
"personas:\n"
" - id: cinema\n"
" title: Кино\n"
" prompt: |\n"
" You are a DP.\n"
" - id: neutral\n"
" title: Нейтральный\n"
" prompt: Calm.\n",
encoding="utf-8",
)
puts: dict[str, str] = {}
ssh_cmds: list[str] = []
def fake_put(cfg, host, remote, text, mode=0o644):
puts[remote] = text
def fake_ssh(cfg, host, cmd, check=False, timeout=60):
ssh_cmds.append(cmd)
if ".gpu-rent-gpu.json" in cmd:
return json.dumps({"vram_mib": 24576, "name": "4090", "compute_cap": "8.9"})
return ""
monkeypatch.setattr("gpu_rent.provision.put_text", fake_put)
monkeypatch.setattr("gpu_rent.provision.run_ssh", fake_ssh)
monkeypatch.setattr(
"gpu_rent.paths.assistent_personas_manifest_path", lambda: yaml_path
)
monkeypatch.setattr(
"gpu_rent.paths.assistent_personas_example_path", lambda: tmp_path / "missing"
)
cfg = MagicMock()
cfg.assistent_personas_manifest = str(yaml_path)
logs: list[str] = []
seed_assistent_personas(cfg, "1.2.3.4", logs.append)
assert any("personas/cinema/persona.json" in p for p in puts)
assert any("personas/cinema/extra.md" in p for p in puts)
assert "/mnt/swarm_data/Assistent/_base/assistant.json" in puts
asst = json.loads(puts["/mnt/swarm_data/Assistent/_base/assistant.json"])
assert asst["default_persona"] == "cinema"
assert asst["num_ctx"] == 16384
assert any("rm -f" in c and "personas.json" in c for c in ssh_cmds)
assert not any(p.endswith("personas.yaml") for p in puts)
assert not any(p.endswith("personas.json") for p in puts)
assert any("overlay personas/2" in m for m in logs)
def test_count_wanted_models(monkeypatch):
raw = "lora:\n - url: https://civitai.red/x?modelVersionId=1\n title: A\n"
monkeypatch.setattr(
"gpu_rent.provision.run_ssh",
lambda *a, **k: raw,
)
assert count_wanted_models_on_vm(MagicMock(), "h") == 1
+61
View File
@@ -0,0 +1,61 @@
"""Doctor LLM / Assistent local checks."""
from __future__ import annotations
from pathlib import Path
from gpu_rent.doctor import Check, _llm_assistent
class _Cfg:
llm_runtime = "ollama"
ollama_models_manifest = None
extensions_manifest = None
def test_llm_assistent_warns_without_ollama_yaml(tmp_path: Path, monkeypatch):
cfg = _Cfg()
cfg.ollama_models_manifest = tmp_path / "missing-ollama.yaml"
cfg.extensions_manifest = tmp_path / "extensions.yaml"
cfg.extensions_manifest.write_text(
"swarmui:\n"
" - url: https://gitea.example/swarm-assistent.git\n"
" dir: swarm-assistent\n"
" requires: ollama\n",
encoding="utf-8",
)
monkeypatch.setattr(
"gpu_rent.paths.ollama_models_manifest_path",
lambda: cfg.ollama_models_manifest,
)
checks: list[Check] = []
_llm_assistent(cfg, checks)
names = {c.name: c for c in checks}
assert names["ollama-models.yaml"].ok is False
assert names["ollama-models.yaml"].blocking is True
assert names["Assistent ext"].ok is True
def test_llm_assistent_ok_with_manifests(tmp_path: Path, monkeypatch):
ollama = tmp_path / "ollama-models.yaml"
ollama.write_text(
"models:\n - name: foo:7b\n use: chat\n default: true\n",
encoding="utf-8",
)
ext = tmp_path / "extensions.yaml"
ext.write_text(
"swarmui:\n"
" - url: https://gitea.example/swarm-assistent.git\n"
" dir: swarm-assistent\n"
" requires: ollama\n",
encoding="utf-8",
)
cfg = _Cfg()
cfg.ollama_models_manifest = ollama
cfg.extensions_manifest = ext
cfg.llm_runtime = "ollama"
checks: list[Check] = []
_llm_assistent(cfg, checks)
by = {c.name: c for c in checks}
assert by["ollama-models.yaml"].ok
assert "swarm-assistent" in by["Assistent ext"].detail
+3 -1
View File
@@ -56,7 +56,9 @@ def test_write_preset(tmp_path: Path):
path = tmp_path / "out.yaml"
write_ollama_models_preset(path, "recommended")
entries = parse_ollama_models(path)
assert entries[0].name == "huihui_ai/qwen2.5-vl-abliterated:7b"
assert entries[0].name == "huihui_ai/qwen3-vl-abliterated:8b-instruct"
assert entries[0].default is True
assert entries[1].name == "huihui_ai/qwen2.5-vl-abliterated:7b"
write_ollama_models_preset(path, "big")
assert parse_ollama_models(path)[0].name == "huihui_ai/qwen2.5-vl-abliterated:32b"
write_ollama_models_preset(path, "text")
+2 -2
View File
@@ -43,10 +43,10 @@ def test_warmup_skips_when_ps_has_model(monkeypatch):
def fake_urlopen(req, timeout=None):
url = getattr(req, "full_url", str(req))
assert "/api/ps" in url
return FakeResp('{"models":[{"name":"huihui_ai/qwen2.5-vl-abliterated:7b"}]}')
return FakeResp('{"models":[{"name":"huihui_ai/qwen3-vl-abliterated:8b-instruct"}]}')
monkeypatch.setattr(_mod.urllib.request, "urlopen", fake_urlopen)
msg = _mod.warmup("huihui_ai/qwen2.5-vl-abliterated:7b", keep_alive="15m", num_ctx=16384, timeout=5)
msg = _mod.warmup("huihui_ai/qwen3-vl-abliterated:8b-instruct", keep_alive="15m", num_ctx=16384, timeout=5)
assert "skip" in msg
assert "VRAM" in msg
+2 -2
View File
@@ -82,6 +82,6 @@ def test_ollama_mid_4090_context_16k():
)
tune = ollama_tune_for(info)
assert tune.context_length == 16384
assert tune.keep_alive == "15m"
assert tune.keep_alive == "5m"
assert "OLLAMA_CONTEXT_LENGTH=16384" in "\n".join(ollama_env_lines(tune))
assert "OLLAMA_KEEP_ALIVE=15m" in "\n".join(ollama_env_lines(tune))
assert "OLLAMA_KEEP_ALIVE=5m" in "\n".join(ollama_env_lines(tune))
+1 -1
View File
@@ -86,7 +86,7 @@ def test_install_ollama_skips_restart_when_unit_unchanged():
text = files("gpu_rent.remote").joinpath("install_ollama.sh").read_text(encoding="utf-8")
assert "cmp -s" in text
assert "skip restart" in text
assert '"mid", 10 * 1024**3, "15m"' in text
assert '"mid", 10 * 1024**3, "5m"' in text
def test_provision_llm_skips_on_api_tags_not_cli_list():