File size: 2,940 Bytes
fcf4209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Real-checkpoint parity for trained extraction graph wrappers."""

from pathlib import Path

import torch
from gliner2 import AutoExtractor, Schema
from gliner2.training.trainer import ExtractorCollator

from extraction_export import ExtractionFeaturesExport, ExtractionScoreExport, coreml_trace_patches
from extraction_pool import select_candidates
from preprocessing import prepare_extraction

SOURCE = (
    Path.home()
    / ".cache/huggingface/hub/models--fastino--gliner2.5-multi-v1/snapshots/a221b77a8baf4a613b8f8652661d41fa10a5641e"
)


def test_export_wrappers_match_native_entity_scores():
    torch.set_num_threads(4)
    native = AutoExtractor.from_pretrained(str(SOURCE), map_location="cpu").eval()
    text = "Alice founded Acme in Toronto in 2020."
    schema = Schema().entities(["person", "organization", "location"])
    batch = ExtractorCollator(native.processor, is_training=False, max_len=128, architecture=native.architecture)(
        [(text, schema.build())]
    )
    arrays, _ = prepare_extraction(native.processor, text, schema, 128, 64, 8)
    arguments = tuple(torch.from_numpy(value) for value in arrays.values())
    with torch.no_grad():
        core = native._encode_core(batch)
        expected = native.boundary_head(
            core["text_states"], core["text_mask"], core["query_states"], core["query_mask"]
        )
        with coreml_trace_patches():
            features = ExtractionFeaturesExport(native).eval()(*arguments)
        assert torch.allclose(features[0][:, : core["text_states"].shape[1]], core["text_states"], atol=1e-5)
        assert torch.allclose(features[1][:, : core["query_states"].shape[1]], core["query_states"], atol=1e-5)
        pool = select_candidates(
            features[8],
            features[9],
            features[3].bool(),
            arguments[5].bool(),
            features[4],
            features[5],
            boundary_top_k=native.boundary_head.shared_pool_builder.pool_boundary_top_k,
            pool_size=native.boundary_head.shared_pool_builder.pool_size,
            min_pool_per_query=native.boundary_head.shared_pool_builder.min_pool_per_query,
        )
        assert torch.equal(
            pool.indices.unsqueeze(1).expand_as(expected.candidates.indices), expected.candidates.indices
        )
        scores, candidate_states = ExtractionScoreExport(native).eval()(
            features[0],
            arguments[3],
            features[1],
            arguments[5],
            features[2],
            features[4],
            features[5],
            features[6],
            features[7],
            pool.indices.int(),
            pool.mask.float(),
            pool.compat_logits,
        )
        assert torch.allclose(scores[:, : core["query_states"].shape[1]], expected.candidates.pair_logits, atol=1e-4)
        assert torch.allclose(candidate_states.unsqueeze(1), expected.candidates.candidate_states[:, :1], atol=1e-4)