File size: 3,654 Bytes
a345062 7dac8c1 a345062 8489475 1cf9e80 a345062 8489475 a345062 d407fda 7dac8c1 d407fda a345062 5708c30 a345062 21e8595 a345062 7dac8c1 5708c30 a345062 d407fda 1cf9e80 a345062 1cf9e80 5708c30 8489475 1cf9e80 a345062 1cf9e80 a345062 1cf9e80 7dac8c1 1cf9e80 7dac8c1 8489475 5708c30 a345062 d407fda 7dac8c1 a345062 |
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 |
import pytest
import torch
from types import SimpleNamespace
from cognitive_mapping_probe.llm_iface import LLM, StableLLMConfig
@pytest.fixture(scope="session")
def mock_llm_config():
"""Stellt eine minimale, Schein-Konfiguration für das LLM bereit."""
return SimpleNamespace(
hidden_size=128,
num_hidden_layers=2,
num_attention_heads=4
)
@pytest.fixture
def mock_llm(mocker, mock_llm_config):
"""
Erstellt einen robusten "Mock-LLM" für Unit-Tests.
FINAL KORRIGIERT: Simuliert nun die vollständige `StableLLMConfig`-Abstraktion.
"""
mock_tokenizer = mocker.MagicMock()
mock_tokenizer.eos_token_id = 1
mock_tokenizer.decode.return_value = "mocked text"
mock_embedding_layer = mocker.MagicMock()
mock_embedding_layer.weight.shape = (32000, mock_llm_config.hidden_size)
def mock_model_forward(*args, **kwargs):
batch_size = 1
seq_len = 1
if 'input_ids' in kwargs and kwargs['input_ids'] is not None:
seq_len = kwargs['input_ids'].shape[1]
elif 'past_key_values' in kwargs and kwargs['past_key_values'] is not None:
seq_len = kwargs['past_key_values'][0][0].shape[-2] + 1
mock_outputs = {
"hidden_states": tuple([torch.randn(batch_size, seq_len, mock_llm_config.hidden_size) for _ in range(mock_llm_config.num_hidden_layers + 1)]),
"past_key_values": tuple([(torch.randn(batch_size, mock_llm_config.num_attention_heads, seq_len, 16), torch.randn(batch_size, mock_llm_config.num_attention_heads, seq_len, 16)) for _ in range(mock_llm_config.num_hidden_layers)]),
"logits": torch.randn(batch_size, seq_len, 32000)
}
return SimpleNamespace(**mock_outputs)
llm_instance = LLM.__new__(LLM)
llm_instance.model = mocker.MagicMock(side_effect=mock_model_forward)
llm_instance.model.config = mock_llm_config
llm_instance.model.device = 'cpu'
llm_instance.model.dtype = torch.float32
llm_instance.model.get_input_embeddings.return_value = mock_embedding_layer
llm_instance.model.lm_head = mocker.MagicMock(return_value=torch.randn(1, 32000))
# FINALE KORREKTUR: Simuliere die Layer-Liste für den Hook-Test
mock_layer = mocker.MagicMock()
mock_layer.register_forward_pre_hook.return_value = mocker.MagicMock()
mock_layer_list = [mock_layer] * mock_llm_config.num_hidden_layers
# Simuliere die verschiedenen möglichen Architektur-Pfade
llm_instance.model.model = SimpleNamespace()
llm_instance.model.model.language_model = SimpleNamespace(layers=mock_layer_list)
llm_instance.tokenizer = mock_tokenizer
llm_instance.config = mock_llm_config
llm_instance.seed = 42
llm_instance.set_all_seeds = mocker.MagicMock()
# Erzeuge die stabile Konfiguration, die die Tests nun erwarten.
llm_instance.stable_config = StableLLMConfig(
hidden_dim=mock_llm_config.hidden_size,
num_layers=mock_llm_config.num_hidden_layers,
layer_list=mock_layer_list # Füge den Verweis auf die Mock-Layer-Liste hinzu
)
# Patch an allen Stellen, an denen das Modell tatsächlich geladen wird.
mocker.patch('cognitive_mapping_probe.llm_iface.get_or_load_model', return_value=llm_instance)
mocker.patch('cognitive_mapping_probe.orchestrator_seismograph.get_or_load_model', return_value=llm_instance)
mocker.patch('cognitive_mapping_probe.auto_experiment.get_or_load_model', return_value=llm_instance)
mocker.patch('cognitive_mapping_probe.orchestrator_seismograph.get_concept_vector', return_value=torch.randn(mock_llm_config.hidden_size))
return llm_instance
|