Downloads · 30 days
61
24% of all-time downloads
3sk4p3/bastion
bastion is a text classification model from 3sk4p3. Use it when you need a label for a piece of text. It is set up for transformers. The card lists the license as apache-2.0.
Fine-tuned Gemma 4 E2B for on-device scam-call and SMS classification. Shipped inside Bastion, the on-device phone-scam shield for seniors built for the Gemma 4 Good Hackathon (Impact Track · Safety & Trust, and LiteR…
Downloads · 30 days
61
24% of all-time downloads
All-time downloads
253
Public
Repo size
6.2 GB
Likes
0
Public
Click a slice to open those files.
.gguf3.7 GB · 59%
From the Hugging Face model README
Fine-tuned Gemma 4 E2B for on-device scam-call and SMS classification. Shipped inside Bastion, the on-device phone-scam shield for seniors built for the Gemma 4 Good Hackathon (Impact Track · Safety & Trust, and LiteRT Special Technology Track).
A LoRA adapter that takes Gemma 4 E2B from F1 0.305 to F1 0.915 on a
100-sample stratified BothBosu test set (3-class scam / scam_partial / ham),
and ships in three formats for two on-device runtimes — llama.cpp
(Q4_K_M GGUF) and Google AI Edge LiteRT-LM (.litertlm, QAT-v2).
| Artefact | Format | Size | Runtime | Purpose |
|---|---|---|---|---|
bastion-text-lora-v1.Q4_K_M.gguf | GGUF (Gemma 4 E2B + LoRA, merged, Q4_K_M) | ~3.2 GB | llama.cpp | Reference deployment artefact, used by the shipped Samsung A54 demo |
bastion-qat-v2-gemma-4-E2B-it.litertlm | LiteRT-LM v2 (QAT) | ~2.4 GB | litertlm-android 0.10.2 / LiteRT-LM v0.11 | Google AI Edge runtime artefact (LiteRT Special Technology Track) |
bastion-mmproj.BF16.gguf | GGUF mm-projector | ~215 MB | llama.cpp (multimodal) | Optional: pairs with stock Gemma 4 E2B for the multimodal-direct experiment baseline (D11/D13) |
Live phone scams target older adults and cost USD ~3B/year in the US alone. Cloud assistants cannot intervene fast enough — by the time a transcript uploads, the senior has read out the code. Bastion runs the model on the phone that is ringing. This adapter is the part that decides whether the call gets ended.
The base model is good at spotting scam patterns (binary F1 ≈ 0.99 on
BothBosu/100) but ships its verdicts as the cautious scam_partial label,
which never triggers Bastion's interrupt — so it is, in practice, useless
for an intervention system. The LoRA fine-tune fixes exactly that gap.
google/gemma-4-E2B-itscripts/synth_scale_gemini.py + scripts/chunk_and_filter.py
in the Bastion repo). Source scripts come from
BothBosu/scam-dialogue
(Apache-2.0) plus Gemini-generated ham counterparts. Both sides are
spoken aloud via Gemini multi-speaker TTS, then degraded from
studio quality to phone-call audio (8 kHz, codec artefacts) so the
audio distribution matches what the host application sees on the
wire. Each WAV is chunked into 15-second windows, transcribed by
Gemma 4 E2B, and only the chunks whose transcript a Gemini
label-judge still agrees with the source dialog label are kept. The
result is a clean, on-distribution text training set without manual
transcription cost. We additionally hold out
UCI SMS Spam
(CC-BY 4.0) and the SMS phishing subset of
DIFrauD (MIT) as
evaluation references; they are not part of the v1 training mix.{
"verdict": "ham | scam_partial | scam_clear",
"reason": "<≤ 25 words>",
"intervene": true | false
}
verdict == "scam_clear" && intervene == true
triggers TelecomManager.endCall() on Android. Anything else is a banner
warning at most.This adapter is not a general assistant — it is single-purpose. Outside the scam / not-scam decision, behaviour falls back to base Gemma 4 E2B.
Evaluation set: BothBosu test, 100 samples, stratified 50 scam / 50 ham, 3-class schema. Full eval log in the Bastion repo.
| Setting | F1 (binary) | F1 (3-class) | Precision | Recall | scam_clear recall (k/50) | Parse rate |
|---|---|---|---|---|---|---|
| Gemma 4 E2B base (prompt only) | 0.667 | 0.305 | 1.000 | 0.180 | 9 / 50 | 100 / 100 |
Gemma 4 E2B + bastion_text_lora_v1 (Q4_K_M, merged) | 0.985 | 0.915 | 0.977 | 0.860 | 43 / 50 | 100 / 100 |
+61 absolute-point lift on the 3-class metric that controls intervention.
The one false positive at this threshold was a real bank-verification call
labelled scam_partial, which would not cross Bastion's interrupt gate
(scam_clear only, confidence ≥ 0.8).
Latency on the CPU reference build (Q4_K_M GGUF, llama.cpp, x86 CPU):
p50 5.8 s, p95 8.8 s per 15-second window.
InterventionController).llama.cpp (Q4_K_M, merged)huggingface-cli download 3sk4p3/bastion bastion-text-lora-v1.Q4_K_M.gguf --local-dir ./bastion
./llama-cli -m ./bastion/bastion-text-lora-v1.Q4_K_M.gguf \
--temp 0.0 --json-schema-file ml/prompts/tool_schema.json \
-p "$(cat ml/prompts/system_prompt.md)\n<transcript>$TRANSCRIPT</transcript>"
.litertlm, on Android)val runner = RealLiteRtGemmaRunner(
context = appContext,
modelPath = "/sdcard/Android/data/<pkg>/files/bastion-qat-v2-gemma-4-E2B-it.litertlm",
)
runner.warmUp()
val verdict = runner.classifyText(transcript) // JSON parsed into the schema above
The Kotlin runner is in
android/inference/
in the Bastion repo and ships with the APK.
ml/notebooks/train_text_lora_v1.ipynbml/prompts/scripts/eval_bothbosu_100.py, scripts/eval_litertlm.pyml/evals/RESULTS.mdbastion_text_lora_v1 follows the
Gemma variant naming guidelines
— variant name precedes Gemma identifier, no stand-alone "Gemma" branding.@misc{bastion2026,
title = {Bastion: On-Device Scam-Call Shield for Seniors},
author = {Szczepanik, Kamil and Arkik, Mohamed},
year = {2026},
howpublished = {\url{https://gitlab.com/3sk4p3/bastion}},
note = {Gemma 4 Good Hackathon submission, Impact Track / Safety \& Trust}
}