An explainable, multimodal routing system that decides whether an incoming
WhatsApp message should interrupt a user now (notify), wait for a digest
(digest), or be suppressed (mute). It combines message content, user and
sender history, group or business context, media extraction, safety checks, and
confidence calibration to reduce notification overload without hiding urgent
messages.
Built for the solo HackerRank Orchestrate 24-hour hackathon challenge, August 1–2, 2026. The submission ranked 38th out of 1,983 participants.
A single inbox can mix family requests, school and society notices, order updates, promotions, forwards, voice notes, image posters, and scams. Static keyword rules miss the recipient's context; forwarding everything creates alert fatigue. This router produces one auditable action, type, reason, confidence, and historical-evidence reference for every incoming message.
- Routes text, images, and voice notes into
notify,digest, ormute. - Personalizes decisions using prior opens, replies, dismissals, opt-outs, group settings, quiet hours, and sender relationships.
- Retrieves only same-recipient historical messages that predate the target.
- Treats message text and extracted media as untrusted input and gives scam and prompt-injection signals a deterministic safety veto.
- Uses schema-constrained Gemini extraction for images and audio, with ffmpeg normalization, content-hash caching, bounded retries, and a second-pass critic for uncertain or conflicting results.
- Validates output shape, coverage, evidence ownership, chronology, and allowed taxonomy values before writing the submission.
- Includes 251 automated tests plus evaluation, evidence-quality, robustness, leakage, paraphrase, and counterfactual audit commands.
This is a single orchestration pipeline with three specialist assessments. It does not use independent autonomous agents or majority voting.
CSV dataset + media
|
v
Dataset validation --> Gemini media extraction --> SHA-256 cache
| |
+-----------------------+
v
Context builder --> historical retrieval
|
+--> safety assessment
+--> personalization assessment
+--> content assessment
|
v
Deterministic arbiter --> confidence calibration --> reason/evidence selection
|
v
Output validation --> dataset/output.csv
The cloud model extracts typed media facts; it does not choose the final route. The deterministic arbiter applies safety, opt-out, urgency, quiet-hour, and engagement precedence. There is no conversational memory service: the provided CSV history is the retrieval store, and the local media cache only avoids repeated extraction calls. See SOLUTION.md for the detailed contracts, rules, guardrails, and tradeoffs.
- Python 3.10+ and the standard library for routing, retrieval, validation, and evaluation
- Google Gemini via
google-genaifor structured image/audio extraction - Pillow for image decoding and normalization
- ffmpeg/ffprobe for audio normalization and duration checks
- pytest for automated tests
.
├── code/
│ ├── main.py # routing CLI
│ ├── extract_media.py # extraction/cache CLI
│ ├── audit.py # adversarial audits
│ ├── reports.py # media and evidence reports
│ ├── evaluation/ # visible-sample metrics
│ ├── prompts/ # extraction prompts
│ ├── router/ # pipeline implementation
│ └── tests/ # automated tests
├── dataset/ # challenge inputs, media, and canonical output
├── .env.example # safe configuration template
├── requirements.txt # direct dependencies
├── requirements-lock.txt # fully resolved CPython 3.13 environment
├── problem_statement.md # organizer-provided task statement
└── SOLUTION.md # detailed technical report
- Python 3.10 or newer
- ffmpeg and ffprobe on
PATHfor voice-note preprocessing - A Gemini API key only when extracting media that is not already cached
# From the repository root:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install -r requirements.txt
cp .env.example .envInstall ffmpeg separately when media extraction is needed:
sudo apt-get install ffmpeg # Debian/Ubuntu
# brew install ffmpeg # macOSSet GEMINI_API_KEY in .env before the first uncached extraction. Never
commit .env. If no key or cache is available, the router still completes
using captions and structured context, reports missing extraction explicitly,
and lowers confidence for affected rows.
| Variable | Required | Default | Purpose |
|---|---|---|---|
GEMINI_API_KEY |
For uncached media | — | Gemini credential |
GEMINI_MODEL |
No | gemini-3.6-flash |
Structured multimodal extraction model |
ROUTER_REPO_ROOT |
No | repository root | Base path for other defaults |
ROUTER_DATASET_DIR |
No | dataset |
Challenge dataset directory |
ROUTER_OUTPUT_PATH |
No | dataset/output.csv |
Canonical prediction output |
ROUTER_CACHE_DIR |
No | .router_cache |
Local extraction cache |
ROUTER_MEDIA_ENABLED |
No | 1 |
Set to 0 to disable media |
ROUTER_MEDIA_WORKERS |
No | 2 |
Maximum parallel extraction calls |
ROUTER_MEDIA_TIMEOUT_SECONDS |
No | 600 |
Per-request/preprocessing timeout |
ROUTER_ASR_CHUNK_SECONDS |
No | 60 |
Long-audio window length |
ROUTER_ASR_CHUNK_OVERLAP_SECONDS |
No | 5 |
Long-audio overlap |
# Extract and cache referenced media. This may call Gemini.
python code/extract_media.py --verbose
# Route all 110 target messages. Normal runs are cache-only by default.
python code/main.py
# Validate an existing output without changing it.
python code/main.py --validate-only
# Inspect one decision trace.
python code/main.py --explain msg_023Useful fallback and diagnostics:
python code/main.py --no-media
python code/extract_media.py --report-only
python code/evaluation/main.py --errors --ablations
python code/reports.py all
python code/audit.py all
python -m pytest code/tests -qThe canonical output has exactly these columns:
message_id,action,message_type,reason,confidence,evidence_message_ids
Validated locally on Python 3.13:
- 251 tests passed.
- All 110 target messages produced schema-valid decisions.
- All emitted evidence belongs to the recipient and predates the target.
- Shuffle, message-ID rename, and repeated-run audits were deterministic.
- The 30 visible solved examples reached 1.000 action and type accuracy.
The last result is training-set fit, not a held-out benchmark: rules and thresholds were iterated with those examples visible. It must not be interpreted as expected hidden-set performance. Run the commands above to reproduce the current local reports.
- Rules over a second routing model: deterministic precedence makes safety and notification decisions inspectable, but hand-built multilingual concepts do not generalize like a large trained classifier.
- Model extraction, not model routing: Gemini handles multimodal perception; trusted dataset fields and local checks retain control of the route.
- Grounded evidence or abstention: unrelated history is emitted as
noneinstead of being cited for appearance's sake. - Cache by content hash: repeated runs avoid API calls, while a fresh model or prompt version can change extraction results.
There is no hosted demo or application UI. The --explain command is the
project's inspectable CLI demo. No decorative screenshots were added; the
repository's images are challenge inputs, not product screenshots.
- The visible sample is not a held-out evaluation set.
- Cross-lingual matching uses an auditable, hand-written concept map rather than general multilingual embeddings.
- Media quality and reproducibility depend on the selected Gemini model unless the matching local cache is present.
- Evaluate on a genuinely held-out, licensed dataset.
- Replace the small cross-lingual map with a measured multilingual retriever.
- Add privacy-preserving user feedback and longitudinal calibration.
- Package a synthetic fixture dataset so the public code can run without redistributing challenge assets.
The original solution code is released under the MIT License. HackerRank's challenge statement, starter files, dataset, and media remain HackerRank competition materials and are included with redistribution permission; see THIRD_PARTY_NOTICES.md.
Built by abhinavgulisetty for HackerRank Orchestrate. HackerRank and WhatsApp are acknowledged solely for competition and problem context; no affiliation or endorsement is implied.