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