Spaces:
Sleeping
Sleeping
File size: 6,177 Bytes
3da2703 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | """
Unit tests for Node 7: Weight Signal Extractor
(src/envs/subenv3/node7_weight_extractor.py)
All tests use the ``synthetic_lora_path`` fixture defined in tests/conftest.py β
no real model weights are needed.
"""
from __future__ import annotations
import json
from unittest.mock import patch
import pytest
from src.envs.subenv3.node7_weight_extractor import extract_weight_signals
from src.schemas.subenv3 import WeightSignalObservation
from src.utils.canonical import canonicalize_lora_factors
# ``synthetic_lora_path`` is injected from tests/conftest.py
# ---------------------------------------------------------------------------
# Test 1 β return type and basic structural invariants
# ---------------------------------------------------------------------------
def test_returns_valid_observation(synthetic_lora_path):
"""extract_weight_signals must return a WeightSignalObservation with
lora_rank == 8 and exactly 3 layer_norm entries (one per LoRA layer).
"""
result = extract_weight_signals(synthetic_lora_path)
assert isinstance(result, WeightSignalObservation)
assert result.lora_rank == 8
assert len(result.layer_norms) == 3
# ---------------------------------------------------------------------------
# Test 2 β canonicalize_lora_factors called once per layer
# ---------------------------------------------------------------------------
def test_canonical_called_per_layer(synthetic_lora_path):
"""canonicalize_lora_factors must be invoked exactly 3 times (one per layer)."""
target = "src.envs.subenv3.node7_weight_extractor.canonicalize_lora_factors"
with patch(target, wraps=canonicalize_lora_factors) as mock_canon:
extract_weight_signals(synthetic_lora_path)
assert mock_canon.call_count == 3
# ---------------------------------------------------------------------------
# Test 3 β token mapping is None when no tokenizer config supplied
# ---------------------------------------------------------------------------
def test_token_mapping_none_without_config(synthetic_lora_path):
"""Without a tokenizer config, token_position_to_phoneme must be None."""
result = extract_weight_signals(synthetic_lora_path)
assert result.token_position_to_phoneme is None
# ---------------------------------------------------------------------------
# Test 4 β token mapping loaded and cast from JSON config
# ---------------------------------------------------------------------------
def test_token_mapping_loaded_from_config(synthetic_lora_path, tmp_path):
"""A tokenizer config with 'token_position_to_phoneme' must produce
a dict[int, str] with string keys parsed as integers.
"""
config = tmp_path / "tokenizer.json"
config.write_text(
json.dumps({"token_position_to_phoneme": {"0": "AH", "1": "EE"}})
)
result = extract_weight_signals(
synthetic_lora_path, tokenizer_config_path=config
)
assert result.token_position_to_phoneme == {0: "AH", 1: "EE"}
# ---------------------------------------------------------------------------
# Test 5 β rank utilization values in [0, 1]
# ---------------------------------------------------------------------------
def test_rank_utilization_in_range(synthetic_lora_path):
"""Every layer_rank_utilization value must be in [0.0, 1.0]."""
result = extract_weight_signals(synthetic_lora_path)
assert result.layer_rank_utilization, "layer_rank_utilization must be non-empty"
assert all(
0.0 <= v <= 1.0 for v in result.layer_rank_utilization.values()
), f"Out-of-range values: {result.layer_rank_utilization}"
# ---------------------------------------------------------------------------
# Test 6 β canonical entropy non-negative
# ---------------------------------------------------------------------------
def test_canonical_entropy_nonnegative(synthetic_lora_path):
"""Every canonical_entropy_per_layer value must be β₯ 0.0 (Shannon entropy β₯ 0)."""
result = extract_weight_signals(synthetic_lora_path)
assert result.canonical_entropy_per_layer, "canonical_entropy_per_layer must be non-empty"
assert all(
v >= 0.0 for v in result.canonical_entropy_per_layer.values()
), f"Negative entropy found: {result.canonical_entropy_per_layer}"
# ---------------------------------------------------------------------------
# Test 7 β overfitting signature in [0, 1]
# ---------------------------------------------------------------------------
def test_overfitting_signature_in_range(synthetic_lora_path):
"""overfitting_signature must be in [0.0, 1.0]."""
result = extract_weight_signals(synthetic_lora_path)
assert 0.0 <= result.overfitting_signature <= 1.0, (
f"overfitting_signature={result.overfitting_signature} out of range"
)
# ---------------------------------------------------------------------------
# Supplementary β structural sanity checks
# ---------------------------------------------------------------------------
def test_layer_keys_consistent(synthetic_lora_path):
"""layer_norms, layer_sparsity, layer_rank_utilization, and
canonical_entropy_per_layer must all share the same key set.
"""
result = extract_weight_signals(synthetic_lora_path)
keys = set(result.layer_norms)
assert set(result.layer_sparsity) == keys
assert set(result.layer_rank_utilization) == keys
assert set(result.canonical_entropy_per_layer) == keys
def test_target_modules_count(synthetic_lora_path):
"""target_modules must list exactly 3 module names."""
result = extract_weight_signals(synthetic_lora_path)
assert len(result.target_modules) == 3
def test_weight_file_id_matches_filename(synthetic_lora_path):
"""weight_file_id must equal the filename of the provided path."""
result = extract_weight_signals(synthetic_lora_path)
assert result.weight_file_id == synthetic_lora_path.name
def test_missing_file_raises(tmp_path):
"""extract_weight_signals must raise FileNotFoundError for nonexistent paths."""
with pytest.raises(FileNotFoundError):
extract_weight_signals(tmp_path / "nonexistent.safetensors")
|