import sys from pathlib import Path import pytest import torch sys.path.insert(0, str(Path(__file__).resolve().parents[1])) class FakeTokenizer: """Char-level tokenizer (ids = ord % vocab); enough for encode_record / encode_glint_record.""" vocab = 997 pad_token_id = 0 class _Out: def __init__(self, ids): self.input_ids = ids def __call__(self, text, add_special_tokens=False): return self._Out([1 + ord(c) % (self.vocab - 1) for c in text]) def convert_tokens_to_ids(self, token): return self.vocab - 1 class FakeBackbone(torch.nn.Module): """Stands in for Qwen3_5ForConditionalGeneration: .model(...) -> last_hidden_state, get_output_embeddings().""" def __init__(self, vocab=FakeTokenizer.vocab, hidden=32): super().__init__() class Inner(torch.nn.Module): def __init__(self): super().__init__() self.embed = torch.nn.Embedding(vocab, hidden) self.mix = torch.nn.Linear(hidden, hidden) def forward(self, input_ids, attention_mask, use_cache=False, return_dict=True, **media): class O: pass o = O(); o.last_hidden_state = torch.tanh(self.mix(self.embed(input_ids))) return o self.model = Inner() self.lm_head = torch.nn.Linear(hidden, vocab, bias=False) def get_output_embeddings(self): return self.lm_head @pytest.fixture def tok(): return FakeTokenizer() @pytest.fixture def records(): choice = {"screen": {"type": "choice", "instructions": "What screen?", "criteria": {"home": "Home", "error": "Error"}}, "has_error": {"type": "noul", "instructions": "Is an error visible?"}} box = {"btn": {"type": "box", "instructions": "the primary button in `screen`"}, "btn_visible": {"type": "noul", "instructions": "Is the primary button visible?"}, "badge": {"type": "box", "instructions": "the red badge"}} return {"choice": {"id": "c", "state": {"app": "X"}, "questions": choice}, "mixed": {"id": "m", "state": "s", "questions": {**choice, **box}}, "box_only": {"id": "b", "state": "s", "questions": {"btn": box["btn"]}}}