Ampel / ampel (push) Failing after 21s
Neuer Bereich "Aufraeumen" auf der Modelle-Seite: Eintraege ohne heutige Rolle und Ordner, auf die kein Eintrag zeigt, mit Groesse und Erklaerung (Rueckweg, Reserve, alte Drafts). Geloescht wird nur auf Knopfdruck mit Rueckfrage. delete_model loescht keine Dateien mehr, die ein anderer Eintrag nennt - seit den Bild-Zwillingen haette sonst das Loeschen eines Zwillings den Coder mitgerissen. Der Projektor des Hirn-Zwillings liegt jetzt neben den Hirn-Gewichten, damit der Original-Ordner loeschbar bleibt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
3.6 KiB
Python
68 lines
3.6 KiB
Python
"""Aufräumen der Modell-Platte: nur Ungenutztes, nur auf Knopfdruck, geteilte Dateien bleiben."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from services import aufraeumen, llamaswap
|
|
|
|
|
|
@pytest.fixture
|
|
def platte(tmp_path, monkeypatch):
|
|
"""Nachbau der Box: Hirn + Bild-Zwilling teilen Gewichte, der Projektor liegt im Original-Ordner."""
|
|
for ordner, datei, groesse in (("Hirn-GGUF", "hirn.gguf", 3000), ("Original-GGUF", "mmproj.gguf", 500),
|
|
("Coder-GGUF", "coder.gguf", 2000), ("Alt-GGUF", "alt.gguf", 4000),
|
|
("Muse-GGUF", "muse.gguf", 1500), ("Reserve-GGUF", "reserve.gguf", 2500),
|
|
("radar", "log.txt", 10), (".cache", "x", 10)):
|
|
(tmp_path / ordner).mkdir()
|
|
(tmp_path / ordner / datei).write_bytes(b"x" * groesse)
|
|
m = str(tmp_path)
|
|
cfg = {"models": {
|
|
"hirn": {"cmd": f"llama-server -m {m}/Hirn-GGUF/hirn.gguf", "aliases": ["hermes", "fast"]},
|
|
"hirn-bild": {"cmd": f"llama-server -m {m}/Hirn-GGUF/hirn.gguf --mmproj {m}/Original-GGUF/mmproj.gguf",
|
|
"aliases": ["vision"]},
|
|
"coder": {"cmd": f"llama-server -m {m}/Coder-GGUF/coder.gguf", "aliases": ["coder"]},
|
|
"alt": {"cmd": f"llama-server -m {m}/Alt-GGUF/alt.gguf"},
|
|
"muse": {"cmd": f"llama-server -m {m}/Muse-GGUF/muse.gguf", "aliases": ["debugger"]},
|
|
}, "groups": {"brains": {"persistent": True, "members": ["hirn"]}}}
|
|
monkeypatch.setattr(aufraeumen, "MODELS_DIR", tmp_path)
|
|
monkeypatch.setattr(aufraeumen, "AUF_DER_BOX", True)
|
|
monkeypatch.setattr(llamaswap, "read_config", lambda: cfg)
|
|
monkeypatch.setattr(llamaswap, "write_config", lambda c: None)
|
|
return tmp_path, cfg
|
|
|
|
|
|
def test_kandidaten_sind_rollenlose_eintraege_und_verwaiste_ordner(platte):
|
|
namen = {(k["art"], k["name"]) for k in aufraeumen.kandidaten()}
|
|
assert namen == {("eintrag", "alt"), ("eintrag", "muse"), ("ordner", "Reserve-GGUF")}
|
|
# Der Original-Ordner ist KEIN Kandidat: der Bild-Zwilling nutzt seinen Projektor.
|
|
muse = next(k for k in aufraeumen.kandidaten() if k["name"] == "muse")
|
|
assert "debugger" in muse["hinweis"]
|
|
|
|
|
|
def test_eintrag_loeschen_nimmt_ihn_aus_der_config_und_seinen_ordner_mit(platte):
|
|
wurzel, cfg = platte
|
|
ergebnis = aufraeumen.loeschen("eintrag", "alt")
|
|
assert ergebnis["ok"] and "alt gelöscht" in ergebnis["text"]
|
|
assert "alt" not in cfg["models"] and not (wurzel / "Alt-GGUF").exists()
|
|
assert (wurzel / "Hirn-GGUF" / "hirn.gguf").exists() and (wurzel / "Coder-GGUF").exists()
|
|
|
|
|
|
def test_nur_aktuelle_kandidaten_und_nie_systemordner(platte):
|
|
wurzel, _ = platte
|
|
assert not aufraeumen.loeschen("ordner", "Hirn-GGUF")["ok"] # wird genutzt
|
|
assert not aufraeumen.loeschen("ordner", "radar")["ok"] # Systemordner
|
|
assert not aufraeumen.loeschen("ordner", "../etwas")["ok"]
|
|
assert (wurzel / "Hirn-GGUF").exists() and (wurzel / "radar").exists()
|
|
assert aufraeumen.loeschen("ordner", "Reserve-GGUF")["ok"] and not (wurzel / "Reserve-GGUF").exists()
|
|
|
|
|
|
def test_delete_model_laesst_geteilte_gewichte_liegen(platte):
|
|
"""Das Löschen des Bild-Zwillings darf die Gewichte des Hirns nicht mitnehmen (24.09.)."""
|
|
wurzel, cfg = platte
|
|
assert llamaswap.delete_model("hirn-bild") is True
|
|
assert "hirn-bild" not in cfg["models"]
|
|
assert (wurzel / "Hirn-GGUF" / "hirn.gguf").exists()
|
|
# Im Zweifel liegen lassen: der Ordner taucht danach als verwaist im Aufräumen auf.
|
|
assert Path(wurzel / "Original-GGUF" / "mmproj.gguf").exists()
|
|
assert ("ordner", "Original-GGUF") in {(k["art"], k["name"]) for k in aufraeumen.kandidaten()}
|