CAMeLBERT-msa-ner — Apple Core AI, Arabic named entities
A Core AI (.aimodel) build of
CAMeL-Lab/bert-base-arabic-camelbert-msa-ner
for on-device Arabic named-entity recognition on Apple Silicon.
Upstream ships pytorch_model.bin, flax_model.msgpack and tf_model.h5 — and no MLX, no ONNX and
no Core AI. 17,133 downloads, and this is the Core AI build.
Output shape, and what a useful measurement is
This is token classification: one distribution per token, [1, 512, 9], not one pooled vector.
That changes the measurement. Comparing the logit tensor is necessary but weak — a graph can drift
and still pick the same label. So the check below also reports per-token argmax agreement across
every position, which is what a caller actually consumes.
Labels, in id2label order (BIO tagging):
0 B-LOC 1 B-MISC 2 B-ORG 3 B-PERS 4 I-LOC 5 I-MISC 6 I-ORG 7 I-PERS 8 O
B- opens a span, I- continues it. The graph returns raw logits and stops there — argmax is the
caller's step, exactly as in the library.
Verified equivalence
| Input | logits max abs diff | per-token argmax |
|---|---|---|
| أحمد يعمل في شركة أرامكو في الرياض. | 2.909e-05 | 12/12 |
| زار الملك سلمان جامعة الملك سعود في جدة. | 6.044e-05 | 11/11 |
| وقّعت مايكروسوفت اتفاقية مع وزارة الاتصالات. | 2.245e-05 | 9/9 |
| كيف أستعيد كلمة المرور؟ | 1.144e-05 | 8/8 |
Worst absolute difference 6.044e-05 — and it needs its magnitude to be read fairly: NER logits here run up to 9.4, so that is relative 6.4e-06, the same float32 rounding as every other bundle in this series. It is reported absolutely as well because a reader comparing across bundles should not have to guess.
Every case agreed on every token: 4/4. All 40 classified positions returned the same label as the original PyTorch model.
What the model extracts
Real output on the reference sentences, from reference-predictions.json in this repository:
| Input | Entities |
|---|---|
| أحمد يعمل في شركة أرامكو في الرياض. | PERS أحمد · ORG أرامكو · LOC الرياض |
| زار الملك سلمان جامعة الملك سعود في جدة. | PERS سلمان · ORG جامعة · ORG الملك سعود · LOC جدة |
| وقّعت مايكروسوفت اتفاقية مع وزارة الاتصالات. | ORG مايكروسوفت |
It finds people, organisations and places in Arabic. It is weaker on multi-word names — it splits
جامعة الملك سعود and misses وزارة الاتصالات — because the tokeniser fragments them and the
training data is what it is. That is the model's own behaviour, reproduced exactly by the conversion,
not a conversion defect.
Use
import asyncio, numpy as np
from coreai.runtime import AIModel, NDArray, SpecializationOptions
from transformers import AutoTokenizer
LABELS = ["B-LOC", "B-MISC", "B-ORG", "B-PERS", "I-LOC", "I-MISC", "I-ORG", "I-PERS", "O"]
SEQUENCE_LENGTH = 512 # fixed shape: pad to it
async def tag(text: str):
tok = AutoTokenizer.from_pretrained(".")
model = await AIModel.load("camelbert-arabic-ner.aimodel", SpecializationOptions.default())
fn = model.load_function("main")
enc = tok([text], padding="max_length", truncation=True, max_length=SEQUENCE_LENGTH,
return_tensors="np")
out = await fn({"input_ids": NDArray(enc["input_ids"].astype("int32")),
"attention_mask": NDArray(enc["attention_mask"].astype("int32"))})
# single output, flattened to 512*9: reshape it, do not index it by name
logits = np.asarray(list(out.values())[0].numpy()).reshape(SEQUENCE_LENGTH, len(LABELS))
n = int(enc["attention_mask"].sum())
return [LABELS[i] for i in logits.argmax(-1)[:n]]
print(tag.__name__, asyncio.run(tag("أحمد يعمل في شركة أرامكو في الرياض.")))
What is in here
| File | |
|---|---|
camelbert-arabic-ner.aimodel/ |
the graph |
manifest.json |
label order, shapes, output selection, precision |
validation.json |
every measured number above |
reference-predictions.json |
the reference logits and entities, so the numbers can be re-checked |
camelbert_ner_coreai.py |
the exporter and measurer — --check, --export, --measure |
| tokenizer files | so the tokenizer loads from this repository |
Limits
- Fixed at 512 tokens. Longer documents need chunking, and entities split across a boundary are lost.
- Four sentences measured. Dialect text, long documents and domain-specific names were not.
- No quality benchmark. No F1, no comparison against upstream's own reported scores. The claim here is arithmetic equivalence only, plus the four examples above.
- No speed or memory measurement.
Licence and attribution
Apache-2.0, as declared by upstream. A derivative work of
CAMeL-Lab/bert-base-arabic-camelbert-msa-ner; credit for the model is theirs.