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:
@@ -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)",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user