new tasks, model pricing, auto quantisation, etc...
This commit is contained in:
@@ -148,3 +148,41 @@ def test_hf_pricing_log_persists_and_is_queryable(tmp_path):
|
||||
# Reopening against the same db path recovers the log (billing.py pattern).
|
||||
reopened = HfPricingLog(db_path=db_path)
|
||||
assert len(reopened.history()) == 1
|
||||
|
||||
|
||||
def test_preset_price_keys_cover_name_repo_and_aliases():
|
||||
from meshnet_tracker.server import _preset_price_keys
|
||||
|
||||
preset = {
|
||||
"hf_repo": "unsloth/Qwen3.6-35B-A3B",
|
||||
"aliases": ["qwen3.6-35b-a3b", "Qwen/Qwen3.6-35B-A3B"],
|
||||
}
|
||||
keys = _preset_price_keys("qwen3.6-35b-a3b", preset)
|
||||
assert keys == {
|
||||
"qwen3.6-35b-a3b",
|
||||
"unsloth/Qwen3.6-35B-A3B",
|
||||
"Qwen/Qwen3.6-35B-A3B",
|
||||
}
|
||||
assert _preset_price_keys("bare", {}) == {"bare"}
|
||||
|
||||
|
||||
def test_qwen_preset_prices_apply_to_all_aliases(tmp_path):
|
||||
"""Requests naming the repo id (what nodes register) bill at the preset price."""
|
||||
from meshnet_tracker.server import TrackerServer
|
||||
|
||||
import pytest
|
||||
|
||||
tracker = TrackerServer(billing_db=str(tmp_path / "billing.sqlite"))
|
||||
try:
|
||||
billing = tracker._billing
|
||||
assert billing is not None
|
||||
for key in (
|
||||
"qwen3.6-35b-a3b",
|
||||
"unsloth/Qwen3.6-35B-A3B",
|
||||
"Qwen/Qwen3.6-35B-A3B",
|
||||
):
|
||||
assert billing.price_for(key) == pytest.approx(0.00044), key
|
||||
# Unknown models keep the default rate
|
||||
assert billing.price_for("some/other-model") == pytest.approx(0.02)
|
||||
finally:
|
||||
pass
|
||||
|
||||
@@ -388,6 +388,48 @@ def test_legacy_start_treats_repo_model_as_model_id(monkeypatch):
|
||||
assert captured["model_id"] == "Qwen/Qwen2.5-0.5B-Instruct"
|
||||
|
||||
|
||||
def test_legacy_start_falls_back_to_env_tracker_and_model(monkeypatch):
|
||||
"""`meshnet-node start` uses env defaults when tracker/model flags are omitted."""
|
||||
import importlib
|
||||
|
||||
from meshnet_node import config as config_mod
|
||||
from meshnet_node.cli import main
|
||||
|
||||
monkeypatch.setenv("MESHNET_TRACKER_URL", "http://env-tracker:8081")
|
||||
monkeypatch.setenv("MESHNET_MODEL", "Qwen/Qwen2.5-0.5B-Instruct")
|
||||
importlib.reload(config_mod)
|
||||
|
||||
captured = {}
|
||||
|
||||
def fake_run_startup(*args, **kwargs):
|
||||
captured.update(kwargs)
|
||||
class _FakeNode:
|
||||
chat_completion_count = 0
|
||||
def stop(self): pass
|
||||
return _FakeNode()
|
||||
|
||||
monkeypatch.setattr(sys, "argv", [
|
||||
"meshnet-node", "start",
|
||||
"--port", "0",
|
||||
])
|
||||
|
||||
try:
|
||||
with patch("meshnet_node.startup.run_startup", side_effect=fake_run_startup):
|
||||
with patch("time.sleep", side_effect=KeyboardInterrupt):
|
||||
try:
|
||||
main()
|
||||
except SystemExit as exc:
|
||||
assert exc.code == 0
|
||||
finally:
|
||||
monkeypatch.delenv("MESHNET_TRACKER_URL", raising=False)
|
||||
monkeypatch.delenv("MESHNET_MODEL", raising=False)
|
||||
importlib.reload(config_mod)
|
||||
|
||||
assert captured["tracker_url"] == "http://env-tracker:8081"
|
||||
assert captured["model"] == "Qwen2.5-0.5B-Instruct"
|
||||
assert captured["model_id"] == "Qwen/Qwen2.5-0.5B-Instruct"
|
||||
|
||||
|
||||
def test_legacy_start_without_port_uses_next_available_port(monkeypatch):
|
||||
"""Omitting --port skips an occupied default port before startup loads the model."""
|
||||
from meshnet_node.cli import main
|
||||
|
||||
@@ -1449,3 +1449,67 @@ def test_cli_loads_local_env_before_config_defaults(tmp_path, monkeypatch):
|
||||
|
||||
assert config_mod.DEFAULTS["download_dir"] == "/run/media/popov/DATA/llm/safetensor/models"
|
||||
assert os.environ["HF_TOKEN"] == "hf_test_token"
|
||||
|
||||
|
||||
def test_default_quantization_is_auto(monkeypatch):
|
||||
import importlib
|
||||
|
||||
from meshnet_node import config as config_mod
|
||||
from meshnet_node.model_backend import validate_quantization
|
||||
|
||||
monkeypatch.delenv("MESHNET_DOWNLOAD_DIR", raising=False)
|
||||
importlib.reload(config_mod)
|
||||
|
||||
assert config_mod.DEFAULTS["quantization"] == "auto"
|
||||
assert validate_quantization("auto") == "auto"
|
||||
|
||||
|
||||
def test_auto_quantization_uses_native_model_dtype_for_unquantized_config():
|
||||
from meshnet_node.model_backend import _model_load_plan
|
||||
|
||||
class AutoConfigStub:
|
||||
@staticmethod
|
||||
def from_pretrained(model_id, cache_dir=None):
|
||||
assert model_id == "repo/model"
|
||||
assert cache_dir is None
|
||||
return types.SimpleNamespace(
|
||||
text_config=types.SimpleNamespace(dtype="torch.bfloat16"),
|
||||
)
|
||||
|
||||
torch_stub = types.SimpleNamespace(bfloat16="bf16", float16="fp16")
|
||||
|
||||
quant_config, dtype, uses_quantized_weights = _model_load_plan(
|
||||
AutoConfigStub,
|
||||
"repo/model",
|
||||
"auto",
|
||||
torch_stub,
|
||||
)
|
||||
|
||||
assert quant_config is None
|
||||
assert dtype == "bf16"
|
||||
assert uses_quantized_weights is False
|
||||
|
||||
|
||||
def test_auto_quantization_preserves_native_quantized_config():
|
||||
from meshnet_node.model_backend import _model_load_plan
|
||||
|
||||
class AutoConfigStub:
|
||||
@staticmethod
|
||||
def from_pretrained(model_id, cache_dir=None):
|
||||
return types.SimpleNamespace(
|
||||
quantization_config={"quant_method": "gptq"},
|
||||
torch_dtype="float16",
|
||||
)
|
||||
|
||||
torch_stub = types.SimpleNamespace(bfloat16="bf16", float16="fp16")
|
||||
|
||||
quant_config, dtype, uses_quantized_weights = _model_load_plan(
|
||||
AutoConfigStub,
|
||||
"repo/model",
|
||||
"auto",
|
||||
torch_stub,
|
||||
)
|
||||
|
||||
assert quant_config is None
|
||||
assert dtype == "fp16"
|
||||
assert uses_quantized_weights is True
|
||||
|
||||
Reference in New Issue
Block a user