Prohori — Offline Emergency Intelligence When Every Second Counts
Inspiration
In Bangladesh, connectivity is often one of the first systems to fail during a flood, cyclone, road accident, or other disaster. A frightened bystander may not know what to do, the nearest hospital may not be ready for the patient, and contacting hospitals one by one can waste critical time.
Most AI health assistants assume ideal conditions: a stable internet connection, a cloud account, and a calm user who has time to read. We wanted to build the opposite—an emergency companion that remains useful with the radio turned off, protects private medical descriptions, and never invents an answer when it does not have reliable information.
That idea became Prohori: an offline-first Android emergency-support application combining deterministic safety rules, cited first-aid guidance, private on-device AI, route comparison, and explicit hospital readiness confirmation.
What it does
Prohori has three operating modes.
Offline Emergency Mode
The user describes what is happening in ordinary language.
Deterministic Rust red-flag rules run first, directly on the phone. They detect critical situations such as:
- Not breathing or cardiac arrest
- Severe bleeding
- Choking
- Stroke signs
- Breathing difficulty
- Seizures
- Burns
- Poisoning
- Head injuries
- Suspected fractures
- Severe allergic reactions
When an emergency is recognized, Prohori immediately displays the corresponding cited first-aid card. The language model is bypassed completely, so urgent guidance never waits for AI generation.
Each card contains:
- Who the instructions apply to
- Ordered first-aid steps
- Actions the user must not take
- Conditions requiring escalation
- Public medical sources
- Clinical-review status
The application also keeps a visible emergency-call action. It opens Android’s dialer but never secretly places a call.
If a description is not covered by a red-flag rule or first-aid template, Prohori can generate limited guidance using the bundled local model. This output passes through strict Rust validation. Guidance containing medication names, dosages, invented measurements, invasive procedures, or unsupported clinical language is rejected.
Offline routing can use the phone’s foreground GPS location with a signed city pack. Invalid signatures, stale road conditions, tampered files, blocked routes, and unsupported vehicle dimensions fail closed. The bundled Rajshahi route is clearly labelled as a non-field-checked demonstration.
Online Emergency Mode
When internet access is available, Prohori can:
- Request the phone’s foreground location.
- Use LocationIQ to discover nearby medical facilities.
- Remove pharmacies, laboratories, veterinary facilities, duplicates, unnamed places, and invalid results.
- Shortlist up to six hospitals.
- Compare their road distances and ETAs in parallel.
- Send readiness alerts to registered hospitals concurrently.
- Wait for explicit
YESorNOreplies. - Select the lowest-ETA hospital among those that explicitly confirmed.
- Fetch detailed directions for the selected hospital.
Silence is never interpreted as acceptance. Replies such as “maybe” or “ready” do not confirm a hospital. Only an explicit YES connected to the correct case ID changes the hospital’s status to confirmed.
Alerts contain only operational information:
- Case ID
- Hospital name
- Broad emergency service category
- Estimated arrival time
They never contain the patient’s name, symptom description, or coordinates.
Prohori can suggest a broad service category such as cardiac emergency, trauma emergency, respiratory emergency, burns, or neurological emergency. This is routing metadata—not a diagnosis.
Verified Telegram, hotline, and SMS contacts are encrypted locally for each facility. Phone calls and SMS messages always open Android’s dialer or composer, leaving the final action under the user’s control.
Private AI Chat Mode
Chat mode provides general suggestions using a Qwen3 1.7B Q4 model running entirely on the phone.
It supports:
- Bounded conversation history
- Contextual follow-up questions
- Streaming responses
- Real cancellation
- Retry without losing the conversation
- No cloud AI API
Before every response, deterministic emergency triage examines recent user context. If an emergency signal is detected, the free-form model is bypassed and the cited emergency protocol is shown instead.
The application then offers explicit actions to open first aid or begin hospital discovery.
Prohori clearly states that its small local model is less capable than a cloud model and must not be used as a doctor, diagnostic system, or replacement for emergency services.
How I built it
Prohori uses a layered architecture in which generated AI is the least trusted component.
Android Interface
The application interface is built with:
- Kotlin
- Jetpack Compose
- Material 3
- English and Bangla resources
- Android speech recognition
- Android text-to-speech
The UI displays decisions made by the safety core but does not determine medical urgency or hospital readiness itself.
Deterministic Rust Core
Rust handles the safety-critical logic:
- Emergency red-flag detection
- First-aid corpus loading
- Deterministic retrieval
- Generated-output verification
- Emergency-number selection
- Signed city-pack validation
- Offline route calculation
- Hospital confirmation state
- Fail-closed data validation
The first-aid corpus is compiled into the native library, ensuring the application uses the same protocol bytes that automated tests verify.
Kotlin communicates with Rust through a typed UniFFI boundary.
Local AI
Prohori bundles the base Qwen3 1.7B Q4_K_M GGUF model and runs it through llama.cpp using JNI.
The model is approximately 1.1 GB and is stored as an uncompressed APK asset. On first launch, Prohori copies it into private application storage and verifies:
- Exact file size
- GGUF header
- SHA-256 checksum
The model is not medically fine-tuned, and Prohori does not claim that it is clinically certified. It is used for general chat and tightly restricted unmatched-situation guidance.
Online Routing and Hospital Coordination
Prohori uses:
- LocationIQ Nearby for medical-facility discovery
- LocationIQ Matrix for up to six ETA and distance comparisons
- LocationIQ Directions for detailed winner navigation
- Telegram Bot API or an organization-hosted HTTPS relay
- Concurrent Kotlin coroutines for parallel hospital alerts
Hospital selection remains deterministic. AI cannot invent the winning hospital.
Privacy and Security
API keys, relay credentials, bot tokens, and hospital contacts are protected using Android Keystore-backed AES-GCM encryption.
Medical descriptions and chat history are not persisted by the application.
Prohori does not request restricted SMS or direct-call permissions. It uses permission-free Android intents so users remain in control.
Release validation checks:
- APK package identity
- Signing policy
- 16 KiB ZIP alignment
- ARM64 and ARMv7 native libraries
- Bundled-model size and SHA-256
- Accidental credential leakage
Challenges we ran into
Running a useful AI model on a mid-range Android phone
A private local model removes cloud dependency but introduces memory, speed, and packaging challenges. We optimized llama.cpp integration, maintained a warm model context where possible, added bounded generation, and implemented real native cancellation.
Making a one-gigabyte first launch understandable
The first launch must copy and verify more than one gigabyte before local AI becomes available. A normal spinner looked like a frozen application.
We replaced it with real byte progress, preparation stages, and a deliberately conservative time estimate.
Safe native streaming
Tokens may divide a Unicode character across multiple byte sequences. Sending an incomplete UTF-8 sequence through JNI can produce broken Bangla or undefined behaviour. Prohori buffers output and emits only complete UTF-8 prefixes.
Preventing model reasoning from appearing
Qwen’s no-thinking instruction was not always sufficient. We adjusted prompt formatting, special-token handling, and output cleanup so internal reasoning markers are not displayed as the answer.
Maintaining streaming in release builds
R8 can rename Kotlin callback methods that native C++ code accesses by name. This caused streaming to work in debug builds but fail in optimized releases. We added explicit keep rules and release-mapping verification.
Distinguishing delivery from confirmation
Sending a Telegram message does not mean a hospital is ready. We designed a strict state machine where delivery, waiting, confirmation, decline, failure, and timeout remain separate states.
Shipping the model
The bundled model makes the APK too large for a normal Git commit and larger than standard Play base-module limits. We distribute evaluation APKs as GitHub Release assets and plan to investigate Play Asset Delivery or controlled post-install model delivery.
Accomplishments that we are proud of
- The emergency path remains functional without internet or AI.
- Recognized emergencies bypass free-form generation.
- Up to six hospitals can be contacted concurrently.
- Silence is never treated as hospital confirmation.
- The fastest hospital is selected only from explicitly confirmed facilities.
- Patient names, symptom text, and coordinates are excluded from hospital alerts.
- The model cannot override deterministic urgency or verified first-aid cards.
- Unknown-situation AI output is constrained and validated before display.
- The application supports real cancellation instead of hiding a running inference task.
- Offline routes use signed, hash-verified city packs and fail closed.
- Credentials remain encrypted and are excluded from public artifacts.
- Debug and release builds, Rust safety tests, Android JVM tests, lint, and APK structural validation pass.
- Production signing is fail-closed rather than silently falling back to a debug certificate.
We are especially proud that honesty is part of the data model. A card with no recorded clinician reviewer says so visibly. A demo route says it is not field checked. An unresponsive hospital remains unconfirmed. A small local model is presented as a small local model.
What I learned
Measure before making a claim
We found problems that configuration files alone could not reveal: release-only callback failures, native optimization differences, real device latency, memory usage, and APK delivery limits.
Testing the actual artifact and actual phone was more valuable than assuming the intended configuration worked.
Privacy is easier to design in from the beginning
By deciding that hospital alerts would never contain symptom text and that conversations would not be persisted, we avoided creating sensitive data flows that would later need to be removed.
Trust is also a user-interface problem
A technically correct safety system is not enough if the user cannot understand whether the application is working, waiting, uncertain, or refusing an unsafe action.
Progress stages, explicit timestamps, route freshness, confirmation states, and honest limitations are part of the safety architecture.
Offline AI requires honest expectations
A 1.7B local model cannot match a large cloud model. Telling users this directly produces a safer and less confusing experience.
What’s next for Prohori
- Complete formal clinical review of every first-aid protocol.
- Enroll real hospitals and verify their Telegram, hotline, and SMS contacts.
- Build complete, field-checked city packs rather than a one-hospital demonstration.
- Add trustworthy traffic, flood, blockage, and road-condition sources without inventing missing data.
- Improve screen-reader semantics, large-text behavior, and accessibility testing.
- Translate first-aid content into Bangla, not only the interface.
- Evaluate a smaller or faster local model while preserving privacy and safety constraints.
- Move the model to Play Asset Delivery or another production-compatible distribution method.
- Complete controlled field testing with emergency professionals and hospital operators.
- Obtain production signing and complete a medically reviewed deployment process.
Log in or sign up for Devpost to join the conversation.