Text Classification
Keras
English
Azerbaijani
prompt-injection
security
llm-security
document-security
retvec
cnn
tensorflow
fastapi
Eval Results (legacy)
Instructions to use MegrurNiftiyev/MyGuard-Prompt-Injection-Detector with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use MegrurNiftiyev/MyGuard-Prompt-Injection-Detector with Keras:
# !pip install -U keras tensorflow huggingface_hub # Keras needs TensorFlow installed to read "hf://" paths, so the tensorflow backend is selected here; # "jax" and "torch" also work for computation once TensorFlow is installed. import os os.environ["KERAS_BACKEND"] = "tensorflow" import keras model = keras.saving.load_model("hf://MegrurNiftiyev/MyGuard-Prompt-Injection-Detector") - Notebooks
- Google Colab
- Kaggle
File size: 3,971 Bytes
215f97f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | """
Pure (side-effect-free) label encoding and dataset split functions.
"""
import random
from collections import defaultdict
import numpy as np
from app.core.logging import get_logger
from app.ml.cnn.architecture import LABEL_NAMES
logger = get_logger(__name__)
# ---------------------------------------------------------------------------
# Encoding helpers
# ---------------------------------------------------------------------------
def encode_labels(labels: list[str]) -> np.ndarray:
"""One-hot encode label strings into a (N, 3) numpy array.
Label order follows ``LABEL_NAMES``: safe=0, suspicious=1, injection=2.
"""
label_to_idx = {name: i for i, name in enumerate(LABEL_NAMES)}
n = len(labels)
encoded = np.zeros((n, len(LABEL_NAMES)), dtype=np.float32)
for i, lab in enumerate(labels):
idx = label_to_idx.get(lab)
if idx is not None:
encoded[i, idx] = 1.0
else:
logger.warning("Unknown label '%s' at index %d — defaulting to safe", lab, i)
encoded[i, 0] = 1.0 # default to safe
return encoded
# ---------------------------------------------------------------------------
# Stratified split with test-set ratio override
# ---------------------------------------------------------------------------
def stratified_split_with_test_ratio_override(
labels: list[str],
test_split: float = 0.15,
test_positive_ratio: float = 0.06,
seed: int = 42,
) -> tuple[list[int], list[int]]:
"""Split indices into train/test with a controlled test-set positive ratio.
The training set keeps whatever class ratio the full dataset has (~20-25%
injection per the data plan). The test set is rebalanced so that positives
(``"injection"`` + ``"suspicious"``) make up approximately
``test_positive_ratio`` of the test set — closer to real-world traffic.
This prevents misleadingly optimistic metrics from an inflated test set.
Args:
labels: List of label strings for each document.
test_split: Fraction of total data to allocate to the test set.
test_positive_ratio: Desired fraction of positives in the test set.
seed: Random seed for reproducibility.
Returns:
``(train_indices, test_indices)`` — lists of integer indices.
"""
rng = random.Random(seed)
# Group indices by label
groups: dict[str, list[int]] = defaultdict(list)
for i, lab in enumerate(labels):
groups[lab].append(i)
# Shuffle within each group
for indices in groups.values():
rng.shuffle(indices)
total = len(labels)
test_size = max(1, int(total * test_split))
# "Positive" = injection + suspicious; "Negative" = safe
positive_keys = [k for k in groups if k in ("injection", "suspicious")]
negative_keys = [k for k in groups if k not in ("injection", "suspicious")]
all_positive = []
for k in positive_keys:
all_positive.extend(groups[k])
all_negative = []
for k in negative_keys:
all_negative.extend(groups[k])
rng.shuffle(all_positive)
rng.shuffle(all_negative)
# Compute how many positives/negatives go into the test set
n_test_positive = max(1, int(test_size * test_positive_ratio))
n_test_negative = test_size - n_test_positive
# Clamp to available data
n_test_positive = min(n_test_positive, len(all_positive))
n_test_negative = min(n_test_negative, len(all_negative))
test_indices = all_positive[:n_test_positive] + all_negative[:n_test_negative]
train_indices = all_positive[n_test_positive:] + all_negative[n_test_negative:]
rng.shuffle(test_indices)
rng.shuffle(train_indices)
actual_ratio = n_test_positive / max(1, len(test_indices))
logger.info(
"Split: %d train, %d test (test positive ratio: %.2f%%)",
len(train_indices),
len(test_indices),
actual_ratio * 100,
)
return train_indices, test_indices
|