mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
213 lines
7.0 KiB
Python
213 lines
7.0 KiB
Python
"""Scripted contracts for the guided interactive workflow."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
|
|
from obliteratus import interactive
|
|
from obliteratus.presets import ModelPreset
|
|
|
|
|
|
def _preset(*, quantization: str | None = None) -> ModelPreset:
|
|
return ModelPreset(
|
|
name="Safe model",
|
|
hf_id="org/safe-model",
|
|
description="fixture",
|
|
tier="tiny",
|
|
params="1B",
|
|
recommended_dtype="float32",
|
|
recommended_quantization=quantization,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("vram_gb", "expected"),
|
|
[(4, "small"), (8, "medium"), (19.9, "medium"), (20, "large")],
|
|
)
|
|
def test_compute_tier_maps_cuda_memory_boundaries(monkeypatch, vram_gb, expected):
|
|
from obliteratus import device
|
|
|
|
monkeypatch.setattr(device, "is_cuda", lambda: True)
|
|
monkeypatch.setattr(device, "is_mps", lambda: False)
|
|
torch = SimpleNamespace(
|
|
cuda=SimpleNamespace(
|
|
get_device_properties=lambda _index: SimpleNamespace(
|
|
total_memory=vram_gb * 1024**3,
|
|
)
|
|
)
|
|
)
|
|
monkeypatch.setitem(__import__("sys").modules, "torch", torch)
|
|
|
|
assert interactive._detect_compute_tier() == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("memory_gb", "expected"),
|
|
[(16, "small"), (24, "medium")],
|
|
)
|
|
def test_compute_tier_maps_mps_unified_memory(monkeypatch, memory_gb, expected):
|
|
from obliteratus import device
|
|
|
|
monkeypatch.setattr(device, "is_cuda", lambda: False)
|
|
monkeypatch.setattr(device, "is_mps", lambda: True)
|
|
monkeypatch.setattr(
|
|
device,
|
|
"get_memory_info",
|
|
lambda: SimpleNamespace(total_gb=memory_gb),
|
|
)
|
|
|
|
assert interactive._detect_compute_tier() == expected
|
|
|
|
|
|
def test_compute_tier_falls_back_to_cpu_when_device_probe_is_unavailable(monkeypatch):
|
|
from obliteratus import device
|
|
|
|
monkeypatch.setattr(device, "is_cuda", Mock(side_effect=ImportError("torch")))
|
|
|
|
assert interactive._detect_compute_tier() == "tiny"
|
|
|
|
|
|
def test_custom_model_selection_preserves_safe_tier_defaults(monkeypatch):
|
|
monkeypatch.setattr(interactive, "get_presets_by_tier", lambda _tier: [_preset()])
|
|
monkeypatch.setattr(interactive.IntPrompt, "ask", lambda *_args, **_kwargs: 0)
|
|
monkeypatch.setattr(
|
|
interactive.Prompt,
|
|
"ask",
|
|
lambda *_args, **_kwargs: "org/custom-model",
|
|
)
|
|
|
|
selected = interactive._pick_model("tiny")
|
|
|
|
assert selected.hf_id == "org/custom-model"
|
|
assert selected.recommended_dtype == "float32"
|
|
assert selected.recommended_quantization is None
|
|
|
|
|
|
def test_invalid_model_selection_falls_back_to_first_recommendation(monkeypatch):
|
|
first = _preset()
|
|
monkeypatch.setattr(interactive, "get_presets_by_tier", lambda _tier: [first])
|
|
monkeypatch.setattr(interactive.IntPrompt, "ask", lambda *_args, **_kwargs: 99)
|
|
|
|
assert interactive._pick_model("tiny") is first
|
|
|
|
|
|
def test_custom_strategy_and_sample_mappings_are_exact(monkeypatch):
|
|
answers = iter(["5", "3"])
|
|
monkeypatch.setattr(
|
|
interactive.Prompt,
|
|
"ask",
|
|
lambda *_args, **_kwargs: next(answers),
|
|
)
|
|
|
|
strategies = interactive._pick_strategies()
|
|
|
|
assert [item["name"] for item in strategies] == [
|
|
"layer_removal",
|
|
"head_pruning",
|
|
"ffn_ablation",
|
|
"embedding_ablation",
|
|
]
|
|
assert strategies[-1]["params"] == {"chunk_size": 48}
|
|
assert interactive._pick_sample_size() == 500
|
|
|
|
|
|
def test_guided_run_builds_safe_config_and_returns_study_result(monkeypatch, tmp_path):
|
|
from obliteratus import device, runner
|
|
|
|
preset = _preset()
|
|
study = SimpleNamespace(
|
|
name="Fast",
|
|
strategies=[{"name": "layer_removal", "params": {"limit": 1}}],
|
|
max_samples=7,
|
|
batch_size=2,
|
|
max_length=64,
|
|
)
|
|
monkeypatch.chdir(tmp_path)
|
|
monkeypatch.setattr(interactive, "_pick_compute_tier", lambda: "tiny")
|
|
monkeypatch.setattr(interactive, "_pick_model", lambda _tier: preset)
|
|
monkeypatch.setattr(interactive, "_pick_study_preset", lambda: study)
|
|
monkeypatch.setattr(device, "get_device", lambda: "cpu")
|
|
monkeypatch.setattr(interactive.Confirm, "ask", lambda *_args, **_kwargs: True)
|
|
run_study = Mock(return_value="study-result")
|
|
monkeypatch.setattr(runner, "run_study", run_study)
|
|
|
|
assert interactive.run_interactive() == "study-result"
|
|
config = run_study.call_args.args[0]
|
|
assert config.model.name == "org/safe-model"
|
|
assert config.model.device == "cpu"
|
|
assert config.model.trust_remote_code is False
|
|
assert config.dataset.max_samples == 7
|
|
assert config.output_dir == "results/org_safe-model"
|
|
|
|
|
|
def test_guided_run_cancellation_does_not_start_a_study(monkeypatch):
|
|
from obliteratus import device, runner
|
|
|
|
monkeypatch.setattr(interactive, "_pick_compute_tier", lambda: "tiny")
|
|
monkeypatch.setattr(interactive, "_pick_model", lambda _tier: _preset())
|
|
monkeypatch.setattr(
|
|
interactive,
|
|
"_pick_study_preset",
|
|
lambda: SimpleNamespace(
|
|
name="Fast",
|
|
strategies=[{"name": "layer_removal", "params": {}}],
|
|
max_samples=1,
|
|
batch_size=1,
|
|
max_length=8,
|
|
),
|
|
)
|
|
monkeypatch.setattr(device, "get_device", lambda: "cpu")
|
|
monkeypatch.setattr(interactive.Confirm, "ask", lambda *_args, **_kwargs: False)
|
|
run_study = Mock()
|
|
monkeypatch.setattr(runner, "run_study", run_study)
|
|
|
|
assert interactive.run_interactive() is None
|
|
run_study.assert_not_called()
|
|
|
|
|
|
def test_quantized_guided_run_returns_quantized_result(monkeypatch):
|
|
from obliteratus import device
|
|
|
|
monkeypatch.setattr(interactive, "_pick_compute_tier", lambda: "small")
|
|
monkeypatch.setattr(
|
|
interactive,
|
|
"_pick_model",
|
|
lambda _tier: _preset(quantization="4bit"),
|
|
)
|
|
monkeypatch.setattr(
|
|
interactive,
|
|
"_pick_study_preset",
|
|
lambda: SimpleNamespace(
|
|
name="Fast",
|
|
strategies=[{"name": "layer_removal", "params": {}}],
|
|
max_samples=1,
|
|
batch_size=1,
|
|
max_length=8,
|
|
),
|
|
)
|
|
monkeypatch.setattr(device, "get_device", lambda: "cuda")
|
|
monkeypatch.setattr(interactive.Confirm, "ask", lambda *_args, **_kwargs: True)
|
|
run_quantized = Mock(return_value="quantized-result")
|
|
monkeypatch.setattr(interactive, "_run_quantized", run_quantized)
|
|
|
|
assert interactive.run_interactive() == "quantized-result"
|
|
config, quantization = run_quantized.call_args.args
|
|
assert quantization == "4bit"
|
|
assert config.model.device == "auto"
|
|
|
|
|
|
def test_quantized_runner_sets_loader_contract_before_execution(monkeypatch):
|
|
from obliteratus import runner
|
|
|
|
config = SimpleNamespace(model=SimpleNamespace(device="cuda", quantization=None))
|
|
run_study = Mock(return_value="done")
|
|
monkeypatch.setattr(runner, "run_study", run_study)
|
|
|
|
assert interactive._run_quantized(config, "8bit") == "done"
|
|
assert config.model.device == "auto"
|
|
assert config.model.quantization == "8bit"
|
|
run_study.assert_called_once_with(config)
|