| import csv |
| import json |
| import time |
| from pathlib import Path |
| import numpy as np |
| import onnxruntime as ort |
| from tokenizers import Tokenizer |
|
|
| |
| TESTS_DIR = Path(__file__).resolve().parent |
| PROJECT_ROOT = TESTS_DIR.parent |
|
|
| MODEL_PATH = PROJECT_ROOT / "model.onnx" |
| TOK_PATH = PROJECT_ROOT / "tokenizer.json" |
| DATASET_PATH = TESTS_DIR / "test_dataset.csv" |
|
|
| LABEL_MAP = {"0": "low", "1": "medium", "2": "hard"} |
|
|
| def main(): |
| if not MODEL_PATH.exists() or not TOK_PATH.exists(): |
| raise FileNotFoundError(f"Model artifacts not found in {PROJECT_ROOT}") |
| if not DATASET_PATH.exists(): |
| raise FileNotFoundError(f"Test dataset not found at {DATASET_PATH}") |
| |
| print(f"Loading tokenizer from {TOK_PATH}...") |
| tokenizer = Tokenizer.from_file(str(TOK_PATH)) |
| |
| print(f"Loading ONNX session from {MODEL_PATH}...") |
| session = ort.InferenceSession(str(MODEL_PATH), providers=["CPUExecutionProvider"]) |
| |
| |
| queries = [] |
| targets = [] |
| with open(DATASET_PATH, "r", encoding="utf-8") as f: |
| reader = csv.DictReader(f) |
| for row in reader: |
| queries.append(row["query"]) |
| targets.append(row["label"]) |
| |
| print(f"Loaded {len(queries)} test queries from {DATASET_PATH.name}.") |
| |
| predictions = [] |
| latencies = [] |
| |
| |
| encoded_warmup = tokenizer.encode("Warmup query") |
| w_ids = np.array([[encoded_warmup.ids[0]]], dtype=np.int64) |
| w_mask = np.array([[1]], dtype=np.int64) |
| _ = session.run(None, {"input_ids": w_ids, "attention_mask": w_mask}) |
| |
| for q in queries: |
| t0 = time.perf_counter() |
| encoded = tokenizer.encode(q) |
| input_ids = np.array([encoded.ids], dtype=np.int64) |
| attention_mask = np.array([encoded.attention_mask], dtype=np.int64) |
| |
| outputs = session.run(None, {"input_ids": input_ids, "attention_mask": attention_mask}) |
| logits = outputs[0][0] |
| |
| exp_l = np.exp(logits - np.max(logits)) |
| probs = exp_l / np.sum(exp_l) |
| pred_idx = int(np.argmax(probs)) |
| t1 = time.perf_counter() |
| |
| latencies.append((t1 - t0) * 1000.0) |
| predictions.append(LABEL_MAP[str(pred_idx)]) |
|
|
| |
| labels = ["low", "medium", "hard"] |
| conf_matrix = {t: {p: 0 for p in labels} for t in labels} |
| |
| correct = 0 |
| for target, pred in zip(targets, predictions): |
| conf_matrix[target][pred] += 1 |
| if target == pred: |
| correct += 1 |
| |
| accuracy = correct / len(targets) |
| |
| metrics = {} |
| f1_scores = [] |
| for label in labels: |
| tp = conf_matrix[label][label] |
| fp = sum(conf_matrix[other][label] for other in labels if other != label) |
| fn = sum(conf_matrix[label][other] for other in labels if other != label) |
| support = sum(conf_matrix[label].values()) |
| |
| precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0 |
| recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0 |
| f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0.0 |
| |
| f1_scores.append(f1) |
| metrics[label] = { |
| "precision": precision, |
| "recall": recall, |
| "f1_score": f1, |
| "support": support |
| } |
| |
| macro_f1 = float(np.mean(f1_scores)) |
| |
| p50_lat = float(np.percentile(latencies, 50)) |
| mean_lat = float(np.mean(latencies)) |
| p90_lat = float(np.percentile(latencies, 90)) |
| p99_lat = float(np.percentile(latencies, 99)) |
| qps = 1000.0 / mean_lat if mean_lat > 0 else 0.0 |
| |
| print("\n" + "="*55) |
| print("HELD-OUT EVALUATION RESULTS (301 SAMPLES)") |
| print("="*55) |
| print(f"Overall Accuracy: {accuracy*100:.2f}%") |
| print(f"Macro F1-Score: {macro_f1:.4f}") |
| print("\nPer-Class Breakdown:") |
| for label in labels: |
| m = metrics[label] |
| print(f" [{label.upper():<6}] Precision: {m['precision']*100:6.2f}% | Recall: {m['recall']*100:6.2f}% | F1: {m['f1_score']:.4f} | Support: {m['support']}") |
| |
| print("\nConfusion Matrix (Rows=Actual, Cols=Predicted):") |
| print(f"{'Actual \\ Pred':<15} {'low':<8} {'medium':<8} {'hard':<8}") |
| for t in labels: |
| row_str = f"{t:<15} " + " ".join(f"{conf_matrix[t][p]:<8}" for p in labels) |
| print(row_str) |
| |
| print("\nLatency Profile (CPU):") |
| print(f" p50: {p50_lat:.2f} ms") |
| print(f" Mean: {mean_lat:.2f} ms") |
| print(f" p90: {p90_lat:.2f} ms") |
| print(f" p99: {p99_lat:.2f} ms") |
| print(f" Throughput: {qps:.1f} queries/sec") |
|
|
| if __name__ == "__main__": |
| main() |
|
|