Text Classification
Transformers
ONNX
Safetensors
English
roberta
editlens
ai-detection
quantization
local-inference
text-embeddings-inference
Instructions to use CoderBak/editlens_roberta_modelkit with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use CoderBak/editlens_roberta_modelkit with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="CoderBak/editlens_roberta_modelkit")# Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("CoderBak/editlens_roberta_modelkit") model = AutoModelForSequenceClassification.from_pretrained("CoderBak/editlens_roberta_modelkit", device_map="auto") - Notebooks
- Google Colab
- Kaggle
| """Reproducible conversions of the pinned Pangram EditLens checkpoint. | |
| License: CC-BY-NC-SA-4.0. See LICENSE and NOTICE in the repository root. | |
| Run each stage in a separate process to bound peak conversion memory. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| from pathlib import Path | |
| UPSTREAM = "pangram/editlens_roberta-large" | |
| REVISION = "f93e1ace74528cfb48f337ab2fe946fb71a728cb" | |
| def digest(path: Path) -> str: | |
| with path.open("rb") as f: | |
| return hashlib.file_digest(f, "sha256").hexdigest() | |
| def verify_source(source: Path, output: Path) -> None: | |
| metadata = json.loads((output / "upstream/metadata.json").read_text()) | |
| if metadata["repo_id"] != UPSTREAM or metadata["revision"] != REVISION: | |
| raise RuntimeError("Unexpected upstream identity") | |
| for info in metadata["files"]: | |
| if info["name"] in {"README.md", ".gitattributes"}: | |
| continue | |
| if digest(source / info["name"]) != info["sha256"]: | |
| raise RuntimeError("Source differs from pinned upstream: " + info["name"]) | |
| def export(source: Path, output: Path) -> None: | |
| import torch | |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer | |
| torch.set_num_threads(4) | |
| model = AutoModelForSequenceClassification.from_pretrained( | |
| source, local_files_only=True, dtype=torch.float32, | |
| attn_implementation="eager", | |
| ).eval() | |
| tokenizer = AutoTokenizer.from_pretrained(source, local_files_only=True) | |
| class Classifier(torch.nn.Module): | |
| def __init__(self, wrapped): | |
| super().__init__() | |
| self.wrapped = wrapped | |
| def forward(self, input_ids, attention_mask): | |
| return self.wrapped(input_ids=input_ids, attention_mask=attention_mask).logits | |
| sample = tokenizer("A short example used only to trace the classifier graph.", return_tensors="pt") | |
| with torch.inference_mode(): | |
| torch.onnx.export( | |
| Classifier(model), (sample["input_ids"], sample["attention_mask"]), | |
| str(output / "onnx/model.onnx"), | |
| input_names=["input_ids", "attention_mask"], output_names=["logits"], | |
| dynamic_axes={"input_ids": {0: "batch", 1: "sequence"}, | |
| "attention_mask": {0: "batch", 1: "sequence"}, | |
| "logits": {0: "batch"}}, | |
| opset_version=17, dynamo=False, external_data=False, | |
| ) | |
| print("FP32 export complete", flush=True) | |
| def fp16(output: Path) -> None: | |
| import onnx | |
| from onnxconverter_common import float16 | |
| graph = onnx.load(output / "onnx/model.onnx") | |
| graph = float16.convert_float_to_float16(graph, keep_io_types=True) | |
| onnx.save(graph, output / "onnx/model_fp16.onnx") | |
| print("FP16 conversion complete (integer inputs and FP32 logits retained)", flush=True) | |
| def int8(output: Path) -> None: | |
| from onnxruntime.quantization import QuantType, quantize_dynamic | |
| quantize_dynamic( | |
| str(output / "onnx/model.onnx"), str(output / "onnx/model_int8.onnx"), | |
| weight_type=QuantType.QInt8, per_channel=True, reduce_range=False, | |
| op_types_to_quantize=["MatMul"], | |
| extra_options={"MatMulConstBOnly": True}, | |
| ) | |
| print("INT8 dynamic MatMul conversion complete (embeddings retained in FP32)", flush=True) | |
| def reference(source: Path, output: Path) -> None: | |
| import numpy as np | |
| import torch | |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer | |
| torch.set_num_threads(4) | |
| tokenizer = AutoTokenizer.from_pretrained(source, local_files_only=True) | |
| model = AutoModelForSequenceClassification.from_pretrained( | |
| source, local_files_only=True, dtype=torch.float32, | |
| attn_implementation="eager", | |
| ).eval() | |
| cases = json.loads((output / "validation/fixtures.json").read_text()) | |
| arrays, metadata = {}, [] | |
| with torch.inference_mode(): | |
| for case in cases: | |
| inputs = tokenizer(case["texts"], padding=True, truncation=True, | |
| max_length=512, return_tensors="pt") | |
| logits = model(**inputs).logits.cpu().numpy() | |
| key = case["id"] | |
| arrays[key + "_input_ids"] = inputs["input_ids"].numpy() | |
| arrays[key + "_attention_mask"] = inputs["attention_mask"].numpy() | |
| arrays[key + "_logits"] = logits | |
| metadata.append({"id": key, "shape": list(inputs["input_ids"].shape)}) | |
| print("Reference", key, metadata[-1]["shape"], flush=True) | |
| np.savez_compressed(output / "validation/reference.npz", **arrays) | |
| (output / "validation/reference.json").write_text(json.dumps({ | |
| "upstream": UPSTREAM, "revision": REVISION, "precision": "float32", | |
| "attention_implementation": "eager", "provider": "PyTorch CPU", | |
| "cases": metadata, "purpose": "Numerical conversion checks; not a labeled accuracy benchmark.", | |
| "source_weights_sha256": digest(source / "model.safetensors"), | |
| "fixtures_sha256": digest(output / "validation/fixtures.json"), | |
| "reference_npz_sha256": digest(output / "validation/reference.npz"), | |
| }, indent=2) + "\n") | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("stage", choices=["export", "fp16", "int8", "reference"]) | |
| parser.add_argument("--source", type=Path, required=True) | |
| parser.add_argument("--output", type=Path, default=Path(__file__).resolve().parents[1]) | |
| args = parser.parse_args() | |
| (args.output / "onnx").mkdir(parents=True, exist_ok=True) | |
| if args.stage in {"export", "reference"}: | |
| verify_source(args.source, args.output) | |
| if args.stage == "export": | |
| export(args.source, args.output) | |
| elif args.stage == "fp16": | |
| fp16(args.output) | |
| elif args.stage == "int8": | |
| int8(args.output) | |
| else: | |
| reference(args.source, args.output) | |