Piko-9b / tests /test_model_loading.py
Dexy2's picture
Remove machine-specific filesystem paths from published reports
12cd919 verified
Raw
History Blame Contribute Delete
4.85 kB
"""Configuration and loading contracts.
These assertions encode facts established in reports/repository_audit.md. If one
of them starts failing, either the checkpoint changed or the audit is stale —
both are worth knowing.
"""
from __future__ import annotations
import json
from pathlib import Path
import pytest
# --------------------------------------------------------------------------- #
# fast tier: no weights required
# --------------------------------------------------------------------------- #
def test_architecture_is_qwen3_5_conditional_generation(model_config: dict) -> None:
assert model_config["architectures"] == ["Qwen3_5ForConditionalGeneration"]
assert model_config["model_type"] == "qwen3_5"
def test_language_config_matches_audit(model_config: dict) -> None:
text = model_config["text_config"]
assert text["hidden_size"] == 4096
assert text["num_hidden_layers"] == 32
assert text["num_attention_heads"] == 16
assert text["num_key_value_heads"] == 4
assert text["head_dim"] == 256
assert text["vocab_size"] == 248320
assert text["max_position_embeddings"] == 262144
def test_layer_stack_is_hybrid(model_config: dict) -> None:
"""24 linear-attention layers, 8 full-attention, every 4th layer."""
layers = model_config["text_config"]["layer_types"]
assert len(layers) == 32
assert layers.count("linear_attention") == 24
assert layers.count("full_attention") == 8
interval = model_config["text_config"]["full_attention_interval"]
for index, kind in enumerate(layers):
expected = "full_attention" if (index + 1) % interval == 0 else "linear_attention"
assert kind == expected, f"layer {index} is {kind}, expected {expected}"
def test_vision_tower_projects_into_language_space(model_config: dict) -> None:
vision = model_config["vision_config"]
assert vision["depth"] == 27
assert vision["hidden_size"] == 1152
assert vision["patch_size"] == 16
assert vision["out_hidden_size"] == model_config["text_config"]["hidden_size"]
def test_rope_is_native_not_scaled(model_config: dict) -> None:
"""The 262K context is architectural; no scaling factor should be present."""
rope = model_config["text_config"]["rope_parameters"]
assert rope["rope_type"] == "default"
assert "factor" not in rope
assert rope["mrope_section"] == [11, 11, 10]
assert rope["mrope_interleaved"] is True
def test_no_remote_code_required(model_config: dict, config_dir: Path) -> None:
assert "auto_map" not in model_config
assert not list(config_dir.glob("*.py"))
def test_config_contains_no_absolute_paths(model_config: dict) -> None:
"""Regression guard for the absolute-path leak found in the original release."""
blob = json.dumps(model_config)
for marker in ("/mnt/", "/home/", "C:\\", "C:/", "\\Users\\"):
assert marker not in blob, f"config.json leaks a local path containing {marker!r}"
def test_generation_config_defaults_to_greedy(config_dir: Path) -> None:
path = config_dir / "generation_config.json"
if not path.is_file():
pytest.skip("generation_config.json not present")
generation = json.loads(path.read_text(encoding="utf-8"))
assert not generation.get("do_sample", False)
assert "temperature" not in generation
def test_tokenizer_declares_vision_tokens(config_dir: Path) -> None:
tokenizer = json.loads((config_dir / "tokenizer_config.json").read_text(encoding="utf-8"))
special = tokenizer["model_specific_special_tokens"]
assert special["image_token"] == "<|image_pad|>"
assert special["vision_bos_token"] == "<|vision_start|>"
assert tokenizer["padding_side"] == "left", "batched generation needs left padding"
def test_chat_template_present_and_handles_images(config_dir: Path) -> None:
template = config_dir / "chat_template.jinja"
assert template.is_file()
body = template.read_text(encoding="utf-8")
assert "<|vision_start|>" in body
assert "<|image_pad|>" in body
assert "add_generation_prompt" in body
# --------------------------------------------------------------------------- #
# slow tier: needs weights + GPU
# --------------------------------------------------------------------------- #
@pytest.mark.slow
def test_model_loads_without_trust_remote_code(loaded_model) -> None:
model, _ = loaded_model
assert type(model).__name__ == "Qwen3_5ForConditionalGeneration"
@pytest.mark.slow
def test_processor_loads(loaded_model) -> None:
_, processor = loaded_model
assert processor.__class__.__name__.startswith("Qwen3VL")
@pytest.mark.slow
def test_vision_tower_is_present_in_weights(loaded_model) -> None:
model, _ = loaded_model
vision_parameters = sum(p.numel() for p in model.model.visual.parameters())
assert vision_parameters > 400_000_000