modernbert-coreml / convert.py
znaat's picture
ModernBERT-base in Core ML, fixed length 128, verified against PyTorch
dcff69c verified
Raw
History Blame Contribute Delete
2.06 kB
#!/usr/bin/env python3
"""ModernBERT -> Core ML, at a fixed sequence length.
python convert.py --length 128 [--model ModernBERT-base]
The length is fixed on purpose. A flexible `RangeDim` traced at one token
converts without error and is wrong at every other length — see the README.
Pin the toolchain. transformers 5.x emits `new_ones` in ModernBERT's attention
path and coremltools cannot convert it; the failure also hits BERT and
DistilBERT, so it is the toolchain and not this model.
torch==2.7.0 transformers==4.48.3 coremltools==9.0
"""
import argparse
import numpy as np
import torch
import coremltools as ct
from transformers import AutoModelForMaskedLM
parser = argparse.ArgumentParser()
parser.add_argument("--model", default="ModernBERT-base")
parser.add_argument("--length", type=int, default=128)
args = parser.parse_args()
class Wrapped(torch.nn.Module):
"""The mask stays `ones_like` inside the graph.
Taking `attention_mask` as a second input makes ModernBERT build it with
`new_ones`, which coremltools has no conversion for. The cost is that
padding is attended as if it were text — pick a length close to your
sentences, or convert several.
"""
def __init__(self, name):
super().__init__()
self.model = AutoModelForMaskedLM.from_pretrained(f"answerdotai/{name}")
def forward(self, input_ids):
return self.model(
input_ids=input_ids, attention_mask=torch.ones_like(input_ids)
).logits
model = Wrapped(args.model).eval()
example = (torch.ones((1, args.length), dtype=torch.int32),)
traced = torch.jit.trace(model, example, strict=False)
mlmodel = ct.convert(
traced,
inputs=[ct.TensorType(name="input_ids", shape=(1, args.length), dtype=np.int32)],
outputs=[ct.TensorType(name="logits")],
minimum_deployment_target=ct.target.macOS15,
)
mlmodel.short_description = (
f"{args.model}, masked-LM head, fixed sequence length {args.length}"
)
out = f"{args.model}-{args.length}.mlpackage"
mlmodel.save(out)
print("wrote", out)