| """Smoke test for the joint tagger+parser pipeline's tensor plumbing: a tiny, randomly |
| initialized encoder + JointModel, fed a synthetic mini-batch, produces correctly-shaped |
| tag/lemma/UPOS/arc/label predictions end to end. Does NOT test tagging/parsing quality |
| (real weights, real treebank) -- only that packing/pooling/scalar-mix/biaffine survive a |
| refactor without shape or index errors.""" |
| import sys |
| from pathlib import Path |
|
|
| import torch |
|
|
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) |
|
|
| from model.char_bert import CharBertConfig |
| from tagger.backbone import CharBertWithHidden |
| from tagger.edits import LabelVocab |
| from tagger.model import TaggerConfig |
| from parser.biaffine import ParserConfig |
| from parser.joint_model import JointModel |
|
|
|
|
| def _tiny_vocab(): |
| return LabelVocab( |
| scripts=[("", "")], |
| xpos_alpha=[["-", "n", "v"] for _ in range(9)], |
| tags=["n-s---fa-", "v2spma---"], |
| upos=["NOUN", "VERB"], |
| lex_ft={}, lex_f={}, nongreek={}, |
| ) |
|
|
|
|
| def test_joint_model_forward_pass(): |
| enc_cfg = CharBertConfig(d_model=32, n_heads=4, depth=2, char_window=8, attn_impl="sdpa") |
| encoder = CharBertWithHidden(enc_cfg) |
| encoder.return_layers = True |
| encoder.eval() |
|
|
| vocab = _tiny_vocab() |
| tcfg = TaggerConfig(pool="mean", use_cap=False, scalar_mix=True, w_flat=0.0) |
| pcfg = ParserConfig(d_arc=16, d_rel=8, dropout=0.0, n_labels=4) |
| W = 6 |
|
|
| model = JointModel(encoder, vocab, tcfg, pcfg, W=W) |
| model.eval() |
|
|
| |
| T = 20 |
| B = 1 |
| input_ids = torch.randint(0, 24, (B, T)) |
| boundary = torch.zeros(B, T, dtype=torch.long) |
| boundary[:, [4, 9, 14, 19]] = 1 |
| boundary[:, 19] = 2 |
| dia = torch.zeros(B, T, dtype=torch.long) |
| punct = torch.zeros(B, T, dtype=torch.long) |
| seg_id = torch.zeros(B, T, dtype=torch.long) |
| |
| |
| word_id = torch.tensor([[w for w in range(4) for _ in range(5)]], dtype=torch.long) |
|
|
| |
| slots = [[(0, 0), (0, 1), (0, 2), (0, 3)]] |
|
|
| batch = dict(input_ids=input_ids, boundary=boundary, dia=dia, punct=punct, |
| seg_id=seg_id, word_id=word_id, slots=slots) |
|
|
| with torch.no_grad(): |
| tag_out, arc_scores, rel_scores, word_mask, sent_ids = model(batch) |
|
|
| |
| assert len(tag_out["xpos"]) == 9 |
| assert tag_out["xpos"][0].shape[:2] == (B, W) |
| assert tag_out["upos"].shape[:2] == (B, W) |
| assert tag_out["script"].shape[:2] == (B, W) |
| |
| assert arc_scores.shape[0] == 1 |
| assert arc_scores.shape[1] == word_mask.shape[1] |
| assert rel_scores.shape[0] == 1 |
| assert sent_ids == [0] |
|
|