Views
No views yet
gibberish detector for border, an embeddable library that inspects the text going into and coming out of an LLM and returns a structured decision plus an audit-grade evidence record.flowxai/gibberish on the hub. It is one detector of 28, and it is not a general purpose gibberish classifier: it was trained for this library's policy, is read at the operating point below, and reports through the evidence record rather than returning a bare score.noise, word_salad, repetitiononnx/model.int8.onnx, 535 MB, opset 17macro_f1 objective.pip install flowx-border1# policy.yaml
2policy_id: default
3version: 1
4
5detectors:
6 gibberish:
7 enabled: true
8 on_fail: flag
9 threshold: 0.921from flowx_border import load_policy, scan_input
2
3policy = load_policy("policy.yaml")
4
5decision = scan_input(user_text, policy)
6
7print(decision.verdict) # allow | flag | redact | block
8print([f.label for f in decision.findings if f.detector_id == "gibberish"])
9print(decision.evidence.record_id)scan_input is where it fires. It is T1, so it runs on the standard path. Its budget is 225 ms at 87 tokens on one CPU thread.onnxruntime directly. Two things you then own yourself, and they are the reason the library exists: the operating point above is not in the graph, and neither is the chunking. Inputs longer than the trained window have to be split and recombined, or the scores past it are extrapolation.1import onnxruntime as ort
2from huggingface_hub import hf_hub_download
3from tokenizers import Tokenizer
4
5repo = "flowxai/gibberish"
6session = ort.InferenceSession(hf_hub_download(repo, "onnx/model.int8.onnx"))
7tokenizer = Tokenizer.from_file(hf_hub_download(repo, "tokenizer.json"))| Label | Support | P | R | F1 |
|---|---|---|---|---|
noise | 245 | 0.996 | 0.984 | 0.990 |
repetition | 225 | 0.978 | 0.964 | 0.971 |
word_salad | 309 | 0.987 | 0.994 | 0.990 |
| Language | Support | P | R | F1 | Note |
|---|---|---|---|---|---|
az Azerbaijani | 29 | 1.000 | 1.000 | 1.000 | |
bg Bulgarian | 32 | 1.000 | 1.000 | 1.000 | |
cs Czech | 32 | 1.000 | 1.000 | 1.000 | |
da Danish | 32 | 1.000 | 1.000 | 1.000 | |
el Greek | 31 | 1.000 | 1.000 | 1.000 | |
en English | 30 | 1.000 | 1.000 | 1.000 | |
es Spanish | 29 | 1.000 | 1.000 | 1.000 | |
et Estonian | 31 | 1.000 | 1.000 | 1.000 | |
hu Hungarian | 30 | 1.000 | 1.000 | 1.000 | |
it Italian | 30 | 1.000 | 1.000 | 1.000 | |
lv Latvian | 30 | 1.000 | 1.000 | 1.000 | |
nl Dutch | 29 | 1.000 | 1.000 | 1.000 | |
pl Polish | 28 | 1.000 | 1.000 | 1.000 | |
ro Romanian | 28 | 1.000 | 1.000 | 1.000 | |
sk Slovak | 29 | 1.000 | 1.000 | 1.000 | |
sl Slovenian | 30 | 1.000 | 1.000 | 1.000 | |
sv Swedish | 30 | 1.000 | 1.000 | 1.000 | |
tr Turkish | 29 | 1.000 | 1.000 | 1.000 | |
fr French | 31 | 0.969 | 1.000 | 0.984 | |
pt Portuguese | 30 | 0.968 | 1.000 | 0.984 | |
ga Irish | 30 | 1.000 | 0.967 | 0.983 | |
lt Lithuanian | 30 | 1.000 | 0.967 | 0.983 | |
fi Finnish | 31 | 0.968 | 0.968 | 0.968 | |
de German | 30 | 1.000 | 0.933 | 0.966 | |
mt Maltese | 29 | 0.966 | 0.966 | 0.966 | not in base model pretraining |
hr Croatian | 29 | 1.000 | 0.897 | 0.946 |
hr Croatian: F1 0.946de German: F1 0.966mt Maltese: F1 0.966 (absent from XLM-R pretraining, which is a base-model limit)sigmoid_at_threshold. A quantised model that answers differently is a different detector, so this is measured rather than assumed.nsfw detector scored 0.000 in Maltese, was blamed on the base model, and went to 1.000 with perfect precision and recall when its corpus went from 2 positives per language to 10. Nothing about the model changed. So where a language scores badly here, read the support column first.