Upload folder using huggingface_hub
Browse files- config.json +1 -0
- fast.pkl +3 -0
- knn.npz +3 -0
- rep_G2b.json +43 -0
- rep_G2b.md +14 -0
- strat_infer.py +66 -0
- student_int8.onnx +3 -0
- tokenizer.json +0 -0
- tokenizer_config.json +24 -0
config.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"labels": ["Refund_not_showing_up", "activate_my_card", "age_limit", "apple_pay_or_google_pay", "atm_support", "automatic_top_up", "balance_not_updated_after_bank_transfer", "balance_not_updated_after_cheque_or_cash_deposit", "beneficiary_not_allowed", "cancel_transfer", "card_about_to_expire", "card_acceptance", "card_arrival", "card_delivery_estimate", "card_linking", "card_not_working", "card_payment_fee_charged", "card_payment_not_recognised", "card_payment_wrong_exchange_rate", "card_swallowed", "cash_withdrawal_charge", "cash_withdrawal_not_recognised", "change_pin", "compromised_card", "contactless_not_working", "country_support", "declined_card_payment", "declined_cash_withdrawal", "declined_transfer", "direct_debit_payment_not_recognised", "disposable_card_limits", "edit_personal_details", "exchange_charge", "exchange_rate", "exchange_via_app", "extra_charge_on_statement", "failed_transfer", "fiat_currency_support", "get_disposable_virtual_card", "get_physical_card", "getting_spare_card", "getting_virtual_card", "lost_or_stolen_card", "lost_or_stolen_phone", "order_physical_card", "passcode_forgotten", "pending_card_payment", "pending_cash_withdrawal", "pending_top_up", "pending_transfer", "pin_blocked", "receiving_money", "request_refund", "reverted_card_payment?", "supported_cards_and_currencies", "terminate_account", "top_up_by_bank_transfer_charge", "top_up_by_card_charge", "top_up_by_cash_or_cheque", "top_up_failed", "top_up_limits", "top_up_reverted", "topping_up_by_card", "transaction_charged_twice", "transfer_fee_charged", "transfer_into_account", "transfer_not_received_by_recipient", "transfer_timing", "unable_to_verify_identity", "verify_my_identity", "verify_source_of_funds", "verify_top_up", "virtual_card_not_working", "visa_or_mastercard", "why_verify_identity", "wrong_amount_of_cash_received", "wrong_exchange_rate_for_cash_withdrawal"], "tau": 0.813436990751346, "lam": 0.5, "mu": 0.0, "maxlen": 48, "knn_classes": 20}
|
fast.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3d693741676eac690a9036f1036dd4ccd2ebace44e486669872bbd2152eb7933
|
| 3 |
+
size 12300983
|
knn.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6015cdfabf08b32d822d2e8639d5afed68976a40fe2f009111706693e9070769
|
| 3 |
+
size 15445122
|
rep_G2b.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"accuracy_pct": 94.54545454545455,
|
| 3 |
+
"wilson95_pct": [
|
| 4 |
+
93.68653351222973,
|
| 5 |
+
95.29339334263855
|
| 6 |
+
],
|
| 7 |
+
"n_test": 3080,
|
| 8 |
+
"coverage_pct": 100.0,
|
| 9 |
+
"latency_ms": {
|
| 10 |
+
"mean": 1.4180174440259738,
|
| 11 |
+
"p50": 0.24948399999999998,
|
| 12 |
+
"p95": 6.259047299999999,
|
| 13 |
+
"p99": 10.405148300000006,
|
| 14 |
+
"per_pass_mean_min": 1.3956335178571428,
|
| 15 |
+
"per_pass_mean_median": 1.4149175311688313,
|
| 16 |
+
"per_pass_mean_max": 1.438470613961039
|
| 17 |
+
},
|
| 18 |
+
"tiers": {
|
| 19 |
+
"fast": {
|
| 20 |
+
"share_pct": 77.30519480519482,
|
| 21 |
+
"mean_ms": 0.2452698942461151,
|
| 22 |
+
"p95_ms": 0.4368241999999999
|
| 23 |
+
},
|
| 24 |
+
"student": {
|
| 25 |
+
"share_pct": 22.694805194805195,
|
| 26 |
+
"mean_ms": 5.412741215164521,
|
| 27 |
+
"p95_ms": 10.006944799999998
|
| 28 |
+
}
|
| 29 |
+
},
|
| 30 |
+
"env": {
|
| 31 |
+
"cpu": "Intel(R) Xeon(R) CPU @ 2.00GHz",
|
| 32 |
+
"logical_cpus": 4,
|
| 33 |
+
"threads": 1,
|
| 34 |
+
"python": "3.13.15",
|
| 35 |
+
"numpy": "2.1.3",
|
| 36 |
+
"onnxruntime": "1.31.1"
|
| 37 |
+
},
|
| 38 |
+
"package_mb": 51.451753,
|
| 39 |
+
"load_s": 0.22228096300023026,
|
| 40 |
+
"reps": 5,
|
| 41 |
+
"seed": 0,
|
| 42 |
+
"gc_paused_in_timed_loop": true
|
| 43 |
+
}
|
rep_G2b.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| Metric | Value |
|
| 2 |
+
|---|---|
|
| 3 |
+
| Test set | Banking77 official test split, 3080 queries, all answered (coverage 100.0%) |
|
| 4 |
+
| Accuracy | 94.55% (Wilson 95% interval 93.69-95.29) |
|
| 5 |
+
| Mean latency | 1.42 ms (per-pass means 1.40-1.44, 5 passes) |
|
| 6 |
+
| p50 / p95 / p99 | 0.25 / 6.26 / 10.41 ms |
|
| 7 |
+
| Tier 1 (tf-idf) | 77.3% of queries, mean 0.25 ms |
|
| 8 |
+
| Tier 2 (int8 MiniLM-L6 + kNN) | 22.7% of queries, mean 5.41 ms |
|
| 9 |
+
| Hardware | Intel(R) Xeon(R) CPU @ 2.00GHz, 4 logical CPUs visible, 1 thread used |
|
| 10 |
+
| Software | Python 3.13.15, onnxruntime 1.31.1, numpy 2.1.3 |
|
| 11 |
+
| Package | 51 MB, loads in 0.2 s |
|
| 12 |
+
|
| 13 |
+
Latency is wall-clock per single query (tokenizer, tf-idf, gate, ONNX int8 student, kNN, label lookup), one query at a time, 1 thread, warm process,
|
| 14 |
+
GC paused in the timed loop; 5 passes over the test set in different random orders. Excludes process start-up. Shared cloud CPUs vary by session; compare runs from the same session.
|
strat_infer.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json, os, pickle, re, numpy as np, onnxruntime as ort
|
| 2 |
+
from tokenizers import Tokenizer
|
| 3 |
+
_TP = re.compile(r"(?u)\b\w\w+\b")
|
| 4 |
+
class Strat:
|
| 5 |
+
"""strat (fast kNN): tier-1 tf-idf, escalating to tier-2 int8 student + class-restricted kNN memory. CPU, 1 thread."""
|
| 6 |
+
def __init__(s, path, threads=1):
|
| 7 |
+
c = json.load(open(os.path.join(path, "config.json"))); s.c = c; s.labels = c["labels"]; C = len(s.labels)
|
| 8 |
+
s.wv, s.wi, s.cv, s.ci, s.cT, s.b = pickle.load(open(os.path.join(path, "fast.pkl"), "rb")); s.off = len(s.wv)
|
| 9 |
+
so = ort.SessionOptions(); so.intra_op_num_threads = threads; so.inter_op_num_threads = 1
|
| 10 |
+
s.sess = ort.InferenceSession(os.path.join(path, "student_int8.onnx"), so, providers=["CPUExecutionProvider"])
|
| 11 |
+
s.bt = Tokenizer.from_file(os.path.join(path, "tokenizer.json")); s.bt.enable_truncation(c["maxlen"]); s.bt.no_padding()
|
| 12 |
+
k = np.load(os.path.join(path, "knn.npz")); E, y = k["E"], k["y"]
|
| 13 |
+
o = np.argsort(y, kind="stable"); s.Ei = np.ascontiguousarray(E[o]); s.yi = y[o].astype(np.int64) # sorted by class
|
| 14 |
+
s.coff = np.concatenate([[0], np.cumsum(np.bincount(s.yi, minlength=C))]).astype(np.int64)
|
| 15 |
+
s.M = int(c.get("knn_classes", 20)); s.nl = C
|
| 16 |
+
def _tf(s, terms, vocab, idf, off):
|
| 17 |
+
cnt = {}
|
| 18 |
+
for t in terms:
|
| 19 |
+
j = vocab.get(t)
|
| 20 |
+
if j is not None: cnt[j] = cnt.get(j, 0) + 1
|
| 21 |
+
if not cnt: return None
|
| 22 |
+
idx = np.fromiter(cnt.keys(), dtype=np.int64, count=len(cnt)); tf = np.fromiter(cnt.values(), dtype=np.float32, count=len(cnt))
|
| 23 |
+
v = (1.0 + np.log(tf)) * idf[idx]; n = np.sqrt((v * v).sum())
|
| 24 |
+
return idx + off, (v / n if n > 0 else v)
|
| 25 |
+
def feat(s, text):
|
| 26 |
+
t = text.lower(); w = _TP.findall(t)
|
| 27 |
+
a = s._tf(w + [w[i] + " " + w[i + 1] for i in range(len(w) - 1)], s.wv, s.wi, 0)
|
| 28 |
+
cg = []
|
| 29 |
+
for wd in t.split():
|
| 30 |
+
wd = " " + wd + " "; L = len(wd)
|
| 31 |
+
for n in range(2, 6):
|
| 32 |
+
o = 0; cg.append(wd[o:o + n])
|
| 33 |
+
while o + n < L:
|
| 34 |
+
o += 1; cg.append(wd[o:o + n])
|
| 35 |
+
if o == 0: break
|
| 36 |
+
b = s._tf(cg, s.cv, s.ci, s.off)
|
| 37 |
+
ps = [x for x in (a, b) if x is not None]
|
| 38 |
+
if not ps: return np.zeros(0, np.int64), np.zeros(0, np.float32)
|
| 39 |
+
return np.concatenate([p[0] for p in ps]), np.concatenate([p[1] for p in ps]).astype(np.float32)
|
| 40 |
+
def fast_p(s, text):
|
| 41 |
+
idx, val = s.feat(text)
|
| 42 |
+
z = val @ s.cT[idx] + s.b
|
| 43 |
+
z = z - z.max(); p = np.exp(z); return p / p.sum()
|
| 44 |
+
def _knn(s, e, p, p_tf):
|
| 45 |
+
if s.M <= 0 or s.M >= s.nl:
|
| 46 |
+
sim = s.Ei @ e; lab = s.yi
|
| 47 |
+
else:
|
| 48 |
+
cand = np.argpartition(-p, s.M)[:s.M]
|
| 49 |
+
if p_tf is not None: cand = np.union1d(cand, np.argpartition(-p_tf, 4)[:4])
|
| 50 |
+
co = s.coff; sims = [s.Ei[co[c]:co[c + 1]] @ e for c in cand]
|
| 51 |
+
sim = np.concatenate(sims); lab = np.concatenate([s.yi[co[c]:co[c + 1]] for c in cand])
|
| 52 |
+
top = np.argpartition(-sim, 10)[:10]; w = np.exp((sim[top] - sim[top].max()) / 0.05)
|
| 53 |
+
pk = np.bincount(lab[top], weights=w, minlength=s.nl); return pk / pk.sum()
|
| 54 |
+
def student_p(s, text, p_tf=None):
|
| 55 |
+
ids = np.array([s.bt.encode(text).ids], dtype=np.int64)
|
| 56 |
+
lg, e = s.sess.run(None, {"input_ids": ids, "attention_mask": np.ones_like(ids)})
|
| 57 |
+
z = lg[0] - lg[0].max(); p = np.exp(z); p /= p.sum()
|
| 58 |
+
lam = s.c["lam"]
|
| 59 |
+
if lam > 0: p = (1 - lam) * p + lam * s._knn(e[0], p, p_tf)
|
| 60 |
+
mu = s.c.get("mu", 0.0)
|
| 61 |
+
if mu > 0 and p_tf is not None: p = (1 - mu) * p + mu * p_tf
|
| 62 |
+
return p
|
| 63 |
+
def predict_one(s, text):
|
| 64 |
+
p = s.fast_p(text)
|
| 65 |
+
if p.max() >= s.c["tau"]: return s.labels[int(p.argmax())], "fast"
|
| 66 |
+
return s.labels[int(s.student_p(text, p).argmax())], "student"
|
student_int8.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:724ff63982904dbfc6e763e8643d7f575d63c1343bbb8f91550667aa79ce338f
|
| 3 |
+
size 22983507
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backend": "tokenizers",
|
| 3 |
+
"cls_token": "[CLS]",
|
| 4 |
+
"do_basic_tokenize": true,
|
| 5 |
+
"do_lower_case": true,
|
| 6 |
+
"is_local": false,
|
| 7 |
+
"local_files_only": false,
|
| 8 |
+
"mask_token": "[MASK]",
|
| 9 |
+
"max_length": 128,
|
| 10 |
+
"model_max_length": 512,
|
| 11 |
+
"never_split": null,
|
| 12 |
+
"pad_to_multiple_of": null,
|
| 13 |
+
"pad_token": "[PAD]",
|
| 14 |
+
"pad_token_type_id": 0,
|
| 15 |
+
"padding_side": "right",
|
| 16 |
+
"sep_token": "[SEP]",
|
| 17 |
+
"stride": 0,
|
| 18 |
+
"strip_accents": null,
|
| 19 |
+
"tokenize_chinese_chars": true,
|
| 20 |
+
"tokenizer_class": "BertTokenizer",
|
| 21 |
+
"truncation_side": "right",
|
| 22 |
+
"truncation_strategy": "longest_first",
|
| 23 |
+
"unk_token": "[UNK]"
|
| 24 |
+
}
|