# `Transmuter.Text.ZeroShotEntityRecognition`
[🔗](https://github.com/georgeguimaraes/transmuter/blob/v2.0.0/lib/transmuter/text/zero_shot_entity_recognition.ex#L1)

The zero-shot entity recognition task with GLiNER models. See `Transmuter.Text.zero_shot_entity_recognition/2`.

The steps follow gliner 0.2.29. The text splits into words. The input of the model is a prompt with the labels, `<<ENT>>` and the label for each label and then `<<SEP>>`, followed by the words of the text. Each word is encoded alone, as the tokenizer of Python encodes a list of words. A word that gives no tokens, such as a DEL character for DeBERTa, has no number in the words mask, so the words after it get lower numbers, as in gliner. The offsets of the entities follow these numbers, as gliner gives them, so an entity after such a word can have the offsets of the word before it. The model scores the words against the labels. `gliner_config.json` gives the variant of the model:

  * A span model, such as `onnx-community/gliner_small-v2.1`, scores each span of up to `max_width` words for each label. A span is an entity when its score is more than the threshold.

  * A token model (`span_mode` is `"token_level"`), such as `knowledgator/gliner-pii-small-v1.0`, scores each word as the start, the end and the inside of an entity of each label. A start and an end of one label with scores more than the threshold give an entity when all words from the start to the end have an inside score of at least the threshold. The score of the entity is the lowest of these scores.

Then the entities go from the highest score to the lowest. An entity stays when it does not overlap an entity that stayed before it.

The inputs of the model are those of gliner, with one change for the compiler. The word axis of the model is the largest word count of the batch, and the model finds the first token of each word with NonZero on the words mask. So the shapes after these nodes depend on the word counts, and each new word count would compile segments again. The serving gives each batch a word axis from its bucket instead: a power of two from 16 up to `max_len` of `gliner_config.json`, and one spare word. The first padding row of the batch has this word count. A full batch has no padding row, so it runs one more row, which costs as much as one more text. With a batch size of 1, each request runs 2 rows. Each token that is not the first token of a word, such as the prompt, the special tokens and the padding, points to the spare word, so NonZero always finds all tokens. The spare word comes after the words of each row, and the model reads only the words of a row, so the results of the rows do not change. Then the shapes of a batch depend only on its sequence length, its bucket, its label count and whether it is full. The compiled model of each sequence length keeps the segments of 8 label counts for each bucket, for full batches and, with a batch size of more than 1, for batches with padding rows. Within these, a new text with the same shapes compiles nothing.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
