Text Classification
Transformers
Safetensors
English
cev
multi-label-classification
intent-detection
hr
calibration
deberta
Instructions to use Nehaa/cev-141m with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Nehaa/cev-141m with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Nehaa/cev-141m")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Nehaa/cev-141m", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download modeling_cev.py from Nehaa/cev-141m: direct link, hf CLI and curl.
- Browser
- Download file 5.32 kB
-
https://huggingface.co/Nehaa/cev-141m/resolve/main/modeling_cev.py
- Command line
-
hf download hf://Nehaa/cev-141m/modeling_cev.py
-
curl -L -o modeling_cev.py https://huggingface.co/Nehaa/cev-141m/resolve/main/modeling_cev.py
5.32 kB
| """ | |
| Cev — Calibrated multi-label intent classifier for HR query routing. | |
| Architecture: | |
| - Backbone: microsoft/deberta-v3-small (frozen, 141M params) | |
| - Head: 2-layer MLP with GELU + Dropout → sigmoid output | |
| - Training loss: Brier score (proper scoring rule — intrinsic calibration) | |
| - Labels: 4 HR capability buckets (multi-label, non-exclusive) | |
| Usage: | |
| from transformers import AutoTokenizer | |
| from modeling_cev import CevModel | |
| model = CevModel.load("Nehaa/cev-141m") | |
| tokenizer = AutoTokenizer.from_pretrained("microsoft/deberta-v3-small") | |
| results = model.predict("What skill gaps does Janet Wise have?", tokenizer) | |
| """ | |
| from __future__ import annotations | |
| from typing import Optional | |
| import torch | |
| import torch.nn as nn | |
| from transformers import AutoModel, AutoTokenizer, PretrainedConfig | |
| CAPABILITIES = ["person_lookup", "skill_assessment", "learning_discovery", "assignment"] | |
| class CevConfig(PretrainedConfig): | |
| model_type = "cev" | |
| def __init__( | |
| self, | |
| backbone: str = "microsoft/deberta-v3-small", | |
| hidden_size: int = 768, | |
| mlp_hidden: int = 384, | |
| dropout: float = 0.1, | |
| capabilities: list[str] | None = None, | |
| **kwargs, | |
| ): | |
| super().__init__(**kwargs) | |
| self.backbone = backbone | |
| self.hidden_size = hidden_size | |
| self.mlp_hidden = mlp_hidden | |
| self.dropout = dropout | |
| self.capabilities = capabilities or CAPABILITIES | |
| class CevModel(nn.Module): | |
| """ | |
| DeBERTa-v3-small backbone (frozen) + 2-layer MLP head trained with Brier loss. | |
| Load via CevModel.load("Nehaa/cev-141m"). | |
| """ | |
| def __init__(self, config: CevConfig): | |
| super().__init__() | |
| self.config = config | |
| self.encoder = AutoModel.from_pretrained(config.backbone) | |
| for param in self.encoder.parameters(): | |
| param.requires_grad = False | |
| self.head = nn.Sequential( | |
| nn.Linear(config.hidden_size, config.mlp_hidden), | |
| nn.GELU(), | |
| nn.Dropout(config.dropout), | |
| nn.Linear(config.mlp_hidden, len(config.capabilities)), | |
| ) | |
| def load(cls, repo_id: str = "Nehaa/cev-141m") -> "CevModel": | |
| """ | |
| Load Cev from Hugging Face Hub. | |
| Args: | |
| repo_id: HF repo ID, default "Nehaa/cev-141m". | |
| Returns: | |
| CevModel ready for inference. | |
| """ | |
| from huggingface_hub import hf_hub_download | |
| import json | |
| # Load config | |
| config_path = hf_hub_download(repo_id, "config.json") | |
| with open(config_path) as f: | |
| cfg_dict = json.load(f) | |
| config = CevConfig(**{ | |
| k: v for k, v in cfg_dict.items() | |
| if k in ("backbone", "hidden_size", "mlp_hidden", "dropout", "capabilities") | |
| }) | |
| model = cls(config) | |
| # Load head weights from safetensors | |
| weights_path = hf_hub_download(repo_id, "model.safetensors") | |
| from safetensors.torch import load_file | |
| state = load_file(weights_path) | |
| # Extract only head weights (ignore encoder keys) | |
| head_state = { | |
| k.replace("head.", ""): v | |
| for k, v in state.items() | |
| if k.startswith("head.") | |
| } | |
| model.head.load_state_dict(head_state) | |
| model.eval() | |
| return model | |
| def forward( | |
| self, | |
| input_ids: torch.Tensor, | |
| attention_mask: torch.Tensor, | |
| token_type_ids: Optional[torch.Tensor] = None, | |
| ) -> dict[str, torch.Tensor]: | |
| kwargs = {"input_ids": input_ids, "attention_mask": attention_mask} | |
| if token_type_ids is not None: | |
| kwargs["token_type_ids"] = token_type_ids | |
| with torch.no_grad(): | |
| enc_out = self.encoder(**kwargs) | |
| cls = enc_out.last_hidden_state[:, 0, :].float() | |
| logits = self.head(cls) | |
| probs = torch.sigmoid(logits) | |
| return {"logits": logits, "probs": probs} | |
| def predict( | |
| self, | |
| text: str | list[str], | |
| tokenizer: AutoTokenizer, | |
| threshold: float = 0.5, | |
| max_length: int = 128, | |
| ) -> list[dict]: | |
| """ | |
| Classify one or more queries. | |
| Args: | |
| text: String or list of strings. | |
| tokenizer: AutoTokenizer for microsoft/deberta-v3-small. | |
| threshold: Decision boundary (default 0.5). | |
| max_length: Max token length (default 128). | |
| Returns: | |
| List of {"probabilities": {cap: float}, "predicted": {cap: 0|1}} | |
| """ | |
| if isinstance(text, str): | |
| text = [text] | |
| device = next(self.parameters()).device | |
| enc = tokenizer( | |
| text, | |
| max_length=max_length, | |
| padding=True, | |
| truncation=True, | |
| return_tensors="pt", | |
| ) | |
| enc = {k: v.to(device) for k, v in enc.items()} | |
| self.eval() | |
| with torch.no_grad(): | |
| out = self.forward(**enc) | |
| probs = out["probs"].cpu() | |
| results = [] | |
| for row in probs: | |
| cap_probs = {c: round(p.item(), 4) for c, p in zip(self.config.capabilities, row)} | |
| predicted = {c: int(p >= threshold) for c, p in cap_probs.items()} | |
| results.append({"probabilities": cap_probs, "predicted": predicted}) | |
| return results | |