CANINE-S Sentence Intent v1

blue-machines/Canine-S-sentence-intent-v1 is a sentence-level intent classifier.

  • Base model: google/canine-s (~133M)
  • Task: 7-class utterance intent
  • Runtime: TorchScript INT8 for fast CPU — ONNX Runtime is not supported for CANINE
  • Input format: a single bare sentence / utterance (no dialogue tags like [assistant] / [user])
  • Output: intent class label + confidence (softmax max probability)

Intent labels

id label
0 provide_info
1 affirm
2 deny
3 correction
4 question
5 clarify_request
6 unclear

Files

File Role
model.pt Deploy (fast CPU) — TorchScript dynamic INT8
model_int8.pt Same INT8 TorchScript (explicit name)
model_fp32.pt TorchScript FP32 reference
model.safetensors Original PyTorch weights
cpu_bench.json Local CPU latency numbers
label_map.json Label id ↔ name map
tokenizer_config.json CANINE char tokenizer config
config.json Transformer config

Why not ONNX / ORT INT8? CANINE’s local-attention + molecule path still yields illegal MatMul shapes in ONNX Runtime. For very fast CPU use TorchScript INT8.

CPU latency (batch=1, pad to 192, 8 threads)

Runtime p50 latency Approx QPS
TorchScript INT8 (model.pt) 24.7 ms 40.5
TorchScript FP32 (model_fp32.pt) 40.3 ms 24.8

INT8 is ~1.63× faster on CPU and ~2.3× smaller on disk (221 MB vs 508 MB).

Recommended confidence threshold

Optimal threshold (selected for performance + coverage): 0.55

Serving rule:

probs = softmax(intent_logits)
pred  = argmax(probs)
conf  = max(probs)
if conf < 0.55:
    pred = unclear   # safe abstain

Selection rule: among thresholds with coverage ≥ 0.97, maximize selective accuracy (tie-break: lower false-intent rate). This keeps most examples committed while cutting false specific intents.

Test-set metrics (sentence-direct test)

Variant Accuracy Macro-F1 False-intent Coverage Selective acc
FP32 raw (no gate) 0.9379 0.9365 0.0547 1.0000 0.9379
Deploy raw (no gate) 0.9379 0.9365 0.0547 1.0000 0.9379
Deploy @ thr=0.55 0.9329 0.9333 0.0410 0.9715 0.9528

Input / output contract

Input: pass one individual sentence (or a batch of independent sentences). Do not wrap with dialogue markers.

Valid examples:

  • Haan, ye sahi hai. Proceed karo.
  • What is the minimum balance required?
  • Nahi, maine ye payment nahi kiya.
  • Sorry I meant March not April.

Tensors

Name Type Shape Notes
input_ids int64 [batch, seq] pad/truncate to 192
attention_mask int64 [batch, seq] 1 = real, 0 = pad
logits / intent_logits float [batch, 7] apply softmax for confidence

Inference snippet

import json
from pathlib import Path

import numpy as np
from transformers import AutoTokenizer, CanineTokenizer

MODEL_DIR = Path(".")  # or huggingface_hub.snapshot_download(...)
MAX_LEN = 192
CONF_THRESHOLD = 0.55  # optimal gate (coverage>=0.97, max selective acc)
UNCLEAR_ID = 6

# tokenizer — Character-level CANINE tokenizer (no WordPiece vocab).
tokenizer = CanineTokenizer.from_pretrained(MODEL_DIR)

with open(MODEL_DIR / "label_map.json", encoding="utf-8") as f:
    maps = json.load(f)
id2intent = {int(k): v for k, v in maps["head4_intent"]["id2label"].items()}

import torch

# Fast CPU path: INT8 TorchScript (model.pt == model_int8.pt)
session = torch.jit.load(str(MODEL_DIR / "model.pt"), map_location="cpu")
session.eval()
torch.set_num_threads(8)  # tune; too many threads can hurt

def predict_intent(sentence: str) -> dict:
    """Pass a single bare sentence; returns label + confidence."""
    enc = tokenizer(
        sentence,
        return_tensors="pt",
        truncation=True,
        max_length=MAX_LEN,
        padding="max_length",
    )
    with torch.inference_mode():
        logits = session(
            enc["input_ids"].to(torch.int64),
            enc["attention_mask"].to(torch.int64),
        )[0].cpu().numpy()

    x = logits.astype(np.float64)
    x = x - x.max()
    probs = np.exp(x)
    probs = probs / probs.sum()
    pred_id = int(probs.argmax())
    conf = float(probs.max())
    abstained = conf < CONF_THRESHOLD
    if abstained:
        pred_id = UNCLEAR_ID
    return {
        "text": sentence,
        "intent": id2intent[pred_id],
        "confidence": conf,
        "abstained": abstained,
        "threshold": CONF_THRESHOLD,
        "probs": {id2intent[i]: float(probs[i]) for i in range(7)},
    }

for s in [
    "Haan, ye sahi hai. Proceed karo.",
    "What is the minimum balance required?",
    "Nahi, maine ye payment nahi kiya.",
]:
    print(predict_intent(s))

Notes

  • Intent-only model (no LID / LSD heads).
  • Trained on sentence-direct data (Gemini synth + Muthoot user turns + noisy unclear), without [assistant]/[user] packing.
Downloads last month
20
Safetensors
Model size
0.1B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support