# FortressNudge

- **Event:** [Google DeepMind Bangalore Hackathon](https://cerebralvalley.ai/e/google-deepmind-bangalore-hackathon)
- **When:** Sat, Jul 11 at 9:00 AM – 10:00 PM (GMT+5:30)
- **Where:** Marathahalli, Marathahalli Main Road
- **Team:** [Animesh singh](https://cerebralvalley.ai/u/AnimeshSingh), [Sanskar Aggarwal](https://cerebralvalley.ai/u/sanskar3084), [Shivam Kumar](https://cerebralvalley.ai/u/shivamk), [Revanth Vermareddy](https://cerebralvalley.ai/u/revanthv)
- **GitHub:** https://github.com/animeshs34/FortressNudge
- **Demo video:** https://youtu.be/6bnZXyvykbI
- **Gallery:** https://cerebralvalley.ai/e/google-deepmind-bangalore-hackathon/hackathon/gallery
- **Page:** https://cerebralvalley.ai/e/google-deepmind-bangalore-hackathon/hackathon/gallery/105

🏰 Fortress Nudge

A privacy-first personal finance agent that turns your bank SMS into smart, contextual money nudges — powered by Gemma 4 running fully on-device.

No cloud. No data leaving your phone. No account. Just your SMS inbox and a 2B-parameter model living in your pocket.

![Kotlin](https://img.shields.io/badge/Kotlin-2.4.0-7F52FF?logo=kotlin&logoColor=white)  
![Jetpack Compose](https://img.shields.io/badge/Jetpack%20Compose-2026.06-4285F4?logo=jetpackcompose&logoColor=white)  
![Gemma 4](https://img.shields.io/badge/Gemma%204%20E2B-on--device-FF6F00)  
![LiteRT-LM](https://img.shields.io/badge/LiteRT--LM-0.14.0-0F9D58)  
![License](https://img.shields.io/badge/License-MIT-blue)

---

The problem

Every UPI payment, salary credit, and EMI hits your phone as an SMS — and then does nothing. Budgeting apps want you to link your bank, upload statements, and ship your transaction history to someone else's server. For most people in India that trade-off (privacy for insight) just isn't worth it, so the SMS pile up and the spending patterns stay invisible.

The idea

What if the insight came to the data, instead of the data going to the cloud?

Fortress Nudge reads the financial SMS that are already on your device, understands them locally, and — when it spots a moment worth acting on — writes you a short, human nudge in Hinglish. The language model that writes those nudges (Gemma 4 E2B) runs entirely on the phone via Google's [LiteRT-LM](https://github.com/google-ai-edge/LiteRT-LM). Nothing is uploaded. Turn on airplane mode and it still works.

![Fortress Nudge showing food-overspend, EMI, and salary nudges](docs/screenshots/nudges.png)

---

What it does

-   📩 Reads financial SMS (salary, UPI debits, EMI, food delivery) with a resilient regex parser
-   🧠 Detects spending patterns — salary credit, EMI cleared, food overspend, micro-spend drift, and large unknown debits
-   ✍️ Writes nudges with Gemma 4 in natural Hindi-English, e.g. "Salary aa gayi — pehle 10% bachao, phir kharch karo."
-   🛡️ Defers to you on risk — a large unfamiliar debit becomes a "was this you?" check-in instead of a silent nudge
-   🔌 Works 100% offline — the model is a local file; there is no server, no API key, no login

---

How it works — an agent, not a chatbot

Fortress Nudge runs a small SENSE → DECIDE → ACT → OBSERVE loop per transaction:

   SMS inbox ──▶ TransactionParser ──▶ PatternDetector ──▶ PaisaAgent ──▶ Nudge UI
   (regex)         (amount/type/         (salary / EMI /     (decide +      (Compose)
                    merchant)             food / micro /       generate)
                                          large-debit)
                                              │
                                              ▼
                                        AdaptiveLlmClient
                                        ┌───────────────┐
                                        │ on-device     │  Gemma 4 E2B  ← primary
                                        │ LiteRT-LM     │  (offline)
                                        └───────────────┘
                                        rule-based fallback ← always available

AI + regex, deliberately hybrid

The detection layer is a hybrid by design — each half does what it is good at:

| Layer | Job | Why |
| --- | --- | --- |
| Regex | Extract amount/type/merchant, catch safety-critical events (large debit), and act as an always-on fallback | Deterministic, instant, never hallucinates a number |
| Gemma 4 | Write the actual nudge — tone, phrasing, Hinglish, the concrete call-to-action | LLMs are great at language, not at parsing rupee amounts |

The historical inbox is classified instantly with the rule engine on first open; live incoming SMS get the premium Gemma-generated nudge. If the model isn't present, the app degrades gracefully to rule-based nudges — it never breaks.

---

Tech stack

| Area | Choice |
| --- | --- |
| Language | Kotlin 2.4 |
| UI | Jetpack Compose (Material 3, dark theme) · Compose BOM 2026.06 |
| On-device LLM | Gemma 4 E2B via LiteRT-LM 0.14 (CPU/GPU/NPU backends) |
| Async | Kotlin Coroutines + Flow |
| Architecture | MVVM · StateFlow · agent loop |
| Min / Target SDK | 26 / 37 |

---

Getting started

Prerequisites

-   Android Studio (JDK 17+), an emulator or device with ≥ 6 GB RAM free (the model needs room)
-   2.6 GB free storage for the model

1. Build & install

bash
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

2. Get the model (one-time, 2.6 GB)

The model is not bundled in the repo (it's 2.6 GB). Download it from the LiteRT community on Hugging Face:

bash
hf download litert-community/gemma-4-E2B-it-litert-lm \
  gemma-4-E2B-it.litertlm --local-dir /gemma4

3. Push the model into the app

bash
adb push /gemma4/gemma-4-E2B-it.litertlm \
  /sdcard/Android/data/com.fortressnudge.app/files/gemma-4-e2b.litertlm

No model? The app still runs — it uses the built-in rule-based nudges and activates Gemma automatically the moment the file is present.

4. Run it

bash
adb shell am start -n com.fortressnudge.app/.ui.MainActivity
grant SMS access when prompted, then send a test transaction:
adb emu sms send 9876543210 "HDFC Bank: INR 50000 credited towards SALARY"

See [DEMO.md](DEMO.md) for a full guided walkthrough and [scripts/sendtestsms.sh](scripts/sendtestsms.sh) to seed a realistic inbox.

---

Project structure

app/src/main/java/com/fortressnudge/app/
├── agent/
│   ├── PaisaAgent.kt          # SENSE→DECIDE→ACT→OBSERVE loop
│   ├── AdaptiveLlmClient.kt   # routes to on-device Gemma, with fallback
│   ├── LocalGemmaClient.kt    # LiteRT-LM engine + streaming inference
│   └── OllamaClient.kt        # optional dev-time server backend
├── domain/
│   ├── TransactionParser.kt   # SMS → structured transaction (regex)
│   └── PatternDetector.kt     # spending-pattern rules
├── data/
│   ├── Models.kt              # Transaction, Nudge, AgentState, actions
│   └── AgentStateStore.kt     # local persistence + rolling windows
├── sms/                       # SMS reader + broadcast receiver
└── ui/                        # Compose screen + MainViewModel

---

Privacy

Fortress Nudge is built so that your financial data never leaves your device:

-   SMS are read locally and never uploaded
-   The language model is a local file; inference runs on the CPU/GPU/NPU of your phone
-   There is no analytics SDK, no account, and no network call required for the core experience

---

Roadmap

-   [ ]  Fully AI-driven detection (Gemma classifies the pattern, not just the wording)
-   [ ]  Streaming nudges token-by-token in the UI
-   [ ]  Notification-channel nudges (act without opening the app)
-   [ ]  Voice nudges (TTS) for accessibility
-   [ ]  Weekly spending digest generated on-device

---

License

Released under the [MIT License](LICENSE).

Gemma is provided by Google under the [Gemma Terms of Use](https://ai.google.dev/gemma/terms). This project does not redistribute model weights — you download them yourself from Hugging Face.

---

Markdown version of https://cerebralvalley.ai/e/google-deepmind-bangalore-hackathon/hackathon/gallery/105. Site index for agents: https://cerebralvalley.ai/llms.txt · full text: https://cerebralvalley.ai/llms-full.txt
