from typing import Callable, List, Tuple from thinc.api import Model, chain, with_array from thinc.types import Floats1d, Floats2d from ...tokens import Doc from ...util import registry InT = List[Doc] OutT = Floats2d @registry.architectures("spacy.SpanFinder.v1") def build_finder_model( tok2vec: Model[InT, List[Floats2d]], scorer: Model[OutT, OutT] ) -> Model[InT, OutT]: logistic_layer: Model[List[Floats2d], List[Floats2d]] = with_array(scorer) model: Model[InT, OutT] = chain(tok2vec, logistic_layer, flattener()) model.set_ref("tok2vec", tok2vec) model.set_ref("scorer", scorer) model.set_ref("logistic_layer", logistic_layer) return model def flattener() -> Model[List[Floats2d], Floats2d]: """Flattens the input to a 1-dimensional list of scores""" def forward( model: Model[Floats1d, Floats1d], X: List[Floats2d], is_train: bool ) -> Tuple[Floats2d, Callable[[Floats2d], List[Floats2d]]]: lens = model.ops.asarray1i([len(doc) for doc in X]) Y = model.ops.flatten(X) def backprop(dY: Floats2d) -> List[Floats2d]: return model.ops.unflatten(dY, lens) return Y, backprop return Model("Flattener", forward=forward)