CoolFace
Modelpublic

convaiinnovations/shoeguard-safety-slm-q4_k_m

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes16downloads
Model Card

ShoeGuard Safety SLM (SmolLM2-135M Q4KM)

This is the fine-tuned SmolLM2-135M model for the ShoeGuard edge AI chip, quantized to Q4KM GGUF format.

Overview

ShoeGuard is the smallest edge AI chip embedded in a tiny custom PCB designed for women's safety. It fires a panic alarm and sends location alerts (via GPS) to relatives when the wearer performs a deliberate repeated kick pattern.

The model takes a 14-dimensional summary feature vector extracted from a two-second window of 50 Hz MPU6050 IMU data and classifies the leg action into one of 10 classes: standing, sitting, walking, running, jumping, stomp, shake_leg, soft_kick, hard_kick, repeated_kick.

Hardware Deployment

The model is quantized to Q4KM (approx. 88 MB) to run efficiently on an RP2040/RP2350 microcontroller with external PSRAM using llama.cpp.

Inference Prompt

The on-chip firmware constructs a short prompt containing the 14 extracted features:

text
You are an on chip safety monitor for a shoe mounted MPU6050. Given the IMU window features below classify the leg action into one of: standing, sitting, walking, running, jumping, stomp, shake_leg, soft_kick, hard_kick, repeated_kick. Reply with the label only.
acc_mean_g=... acc_std_g=...

Intended Use

This model is intended strictly for the physical trigger engine aboard the ShoeGuard PCB to determine whether an emergency impact sequence has occurred. It acts as an embedded classifier running locally, fully preserving wearer privacy.

Python Inference Example

You can test the model logic locally using llama-cpp-python and the provided test dataset.

python
from llama_cpp import Llama
import json, time

llm = Llama(model_path='safety-q4_k_m.gguf', n_gpu_layers=0, n_ctx=512, n_threads=4, verbose=False)

from collections import deque
KICKS = {'hard_kick', 'repeated_kick'}
history = deque(maxlen=3)

# Chat template (SmolLM2 Instruct format)
input_prompt = "<|im_start|>user\n{}<|im_end|>\n<|im_start|>assistant\n{}"

def classify(user_msg):
    p = input_prompt.format(user_msg, '')
    out = llm(p, max_tokens=8, temperature=0.0, top_p=1.0, stop=['###', '\n\n', '<|im_end|>'])
    return out['choices'][0]['text'].strip().lower()

def trigger(label):
    history.append(label)
    if label == 'repeated_kick':
        return True
    return sum(1 for x in history if x in KICKS) >= 2

# Load dataset and demo trigger
rows = [json.loads(l) for l in open('imu_actions_1000.jsonl', encoding='utf-8')]
demo = [r for r in rows if r['label'] in ('walking','hard_kick','hard_kick','repeated_kick')][:6]

for r in demo:
    user = next(m['content'] for m in r['messages'] if m['role'] == 'user')
    t0 = time.time()
    pred = classify(user)
    fire = trigger(pred)
    print(f"true={r['label']:14s} pred={pred:14s} fire={fire}  ({(time.time()-t0)*1000:.0f} ms)")