Token Classification
Transformers
Safetensors
English
Hebrew
xlm-roberta
code-switching
hebrew
transliteration
romanization
text-to-speech
Eval Results (legacy)
Instructions to use Hebrish/Hebrew-Latin-Token-Classifier with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Hebrish/Hebrew-Latin-Token-Classifier with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="Hebrish/Hebrew-Latin-Token-Classifier")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("Hebrish/Hebrew-Latin-Token-Classifier") model = AutoModelForTokenClassification.from_pretrained("Hebrish/Hebrew-Latin-Token-Classifier", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 3,175 Bytes
e303bc1 | 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 69 70 71 72 73 74 75 76 77 | # /// script
# requires-python = ">=3.11"
# dependencies = ["torch", "transformers>=4.46,<5"]
# ///
"""Find Hebrew-in-Latin spans in English text with the published classifier.
uv run training/predict.py "I need to go to Bituach Leumi before the makolet closes."
Words are pre-split with the same regex the corpus was tokenised with, and each word
takes the label of its first sub-token, which is the only one trained. This is why
it is used instead of the transformers `pipeline`. The pipeline splits on whitespace,
so trailing punctuation sticks to spans ("makolet?"), and the "simple" aggregation
cuts words short ("mako").
"""
from __future__ import annotations
import re
import sys
import torch
from transformers import AutoModelForTokenClassification, AutoTokenizer
MODEL = "Hebrish/Hebrew-Latin-Token-Classifier"
TOKEN_RE = re.compile(r"\w+(?:'\w+)?|[^\w\s]") # = scripts/lib/corpus.py
class HebrewSpans:
def __init__(self, model: str = MODEL, device: str | None = None):
self.tok = AutoTokenizer.from_pretrained(model)
self.model = AutoModelForTokenClassification.from_pretrained(model).eval()
self.device = device or ("cuda" if torch.cuda.is_available() else "cpu")
self.model.to(self.device)
@torch.no_grad()
def __call__(self, text: str, threshold: float = 0.5) -> list[dict]:
words = list(TOKEN_RE.finditer(text))
if not words:
return []
enc = self.tok([m.group(0) for m in words], is_split_into_words=True,
truncation=True, return_tensors="pt").to(self.device)
probs = self.model(**enc).logits[0].softmax(-1).cpu()
labels = self.model.config.id2label
tags, seen = {}, set()
for i, w in enumerate(enc.word_ids()):
if w is None or w in seen:
continue
seen.add(w)
p = probs[i]
# A word counts as Hebrew when P(B)+P(I) clears the threshold; raise it
# for fewer false positives, which is what a TTS pipeline usually wants.
he = float(p[1] + p[2])
tags[w] = (labels[int(p[1:].argmax()) + 1] if he >= threshold else "O", he)
spans: list[dict] = []
for w, m in enumerate(words):
tag, score = tags.get(w, ("O", 0.0))
if tag == "O":
continue
prev = spans[-1] if spans else None
# I-HE extends a span only when it directly follows one; an orphan I-HE
# starts its own span rather than being dropped.
if prev and tag == "I-HE" and prev["_last"] == w - 1:
prev.update(end=m.end(), _last=w, score=min(prev["score"], score))
else:
spans.append({"start": m.start(), "end": m.end(), "score": score, "_last": w})
for s in spans:
s.pop("_last")
s["text"] = text[s["start"]:s["end"]]
s["score"] = round(s["score"], 3)
return spans
if __name__ == "__main__":
finder = HebrewSpans()
for line in sys.argv[1:] or sys.stdin:
line = line.strip()
print(line, "->", [(s["text"], s["score"]) for s in finder(line)])
|