Turn your Android phone into a private, local AI server.
Run quantized LLMs on-device and expose an OpenAI-compatible REST API over Wi-Fi β no cloud, no fees, no data leaving your phone.
- What is NeuralLite?
- Key Features
- Architecture
- The Local AI Server
- On-Device LLM Engine
- Hardware Detection & Tier System
- Model Catalog
- App Screens
- Installation
- Security
- Requirements
- Build from Source
- Tech Stack
NeuralLite is an Android app that hosts a full HTTP inference server directly on your phone. It runs quantized large language models (GGUF format via llama.cpp) entirely on-device and exposes them through an OpenAI-compatible REST API on your local Wi-Fi network.
This means any tool, script, or application that already speaks the OpenAI API protocol β from curl to Open WebUI to LangChain β can use your phone as its AI backend, with zero cloud dependency.
| Feature | Description |
|---|---|
| π‘ Phone as AI Server | Runs a full HTTP server on port 8080, reachable from any device on your Wi-Fi LAN |
| π€ OpenAI-Compatible API | /v1/chat/completions, /v1/completions, /v1/models β drop-in compatible with standard SDKs |
| β‘ Streaming Responses (SSE) | Real-time token streaming via Server-Sent Events, just like ChatGPT |
| π§ llama.cpp Native Engine | JNI-powered C++ inference through libllama_android.so β maximum performance |
| π Auto-Generated Bearer Token | Encrypted per-device API key stored with EncryptedSharedPreferences (AES-256) |
| πΆ mDNS / Bonjour Discovery | Automatically broadcasts as _neurallite._tcp so other LAN devices can discover it |
| π Foreground Service + Wake/Wi-Fi Locks | Server stays alive with screen off; no battery or Wi-Fi suspension |
| π― Hardware Tier Detection | Scans RAM, CPU cores, and ABI β recommends the right model for your device |
| π¦ Built-in Model Catalog | One-tap download of TinyLlama, Phi-2, Gemma, Mistral-7B, Llama-3-8B from HuggingFace |
| π Dark Neon UI (Jetpack Compose) | Material 3 with cyan/green accents, animated pulse indicators, live request log |
NeuralLite's architecture has three layers:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Android App β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββ β
β β Jetpack β β NeuralliteVM β β Hardware β β
β β Compose UI ββββΆβ (ViewModel) ββββΆβ Scanner β β
β ββββββββββββββββ ββββββββ¬ββββββββ ββββββββββββββ β
β β β
β βββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ β
β β NeuralliteServerService (Foreground) β β
β β Wi-Fi Lock Β· Wake Lock Β· mDNS Β· Notification β β
β βββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ β
β β NeuralliteServer (NanoHTTPD on :8080) β β
β β GET /health Β· GET /v1/models Β· POST /v1/chat/... β β
β βββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ β
β β LlamaEngine (Kotlin singleton) β β
β β loadModelSafe() Β· runInferenceSafe() (JNI) β β
β βββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ β
β β libllama_android.so (llama.cpp C++) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP over Wi-Fi LAN (:8080)
βΌ
ββββββββββββββββββββββ ββββββββββββββββββββ ββββββββββ
β Python / curl β β Open WebUI β β Any β
β scripts β β LangChain β β SDK β
ββββββββββββββββββββββ ββββββββββββββββββββ ββββββββββ
When you tap Start on the Server screen:
NeuralliteServerServicestarts as a foreground service β it stays alive even with the screen off.- A Wi-Fi lock (
WIFI_MODE_FULL_HIGH_PERF) prevents the radio from sleeping. - A partial wake lock keeps the CPU awake for inference.
NeuralliteServer(built on NanoHTTPD) binds to0.0.0.0:8080.- The service registers itself via mDNS (
_neurallite._tcp) so LAN devices can discover it automatically. - A persistent notification appears with the server's IP and a "Stop Server" action button.
The server shuts down cleanly when you tap Stop or dismiss the notification action β all locks are released and mDNS is unregistered.
curl http://192.168.1.42:8080/health{
"status": "ok",
"model": "TinyLlama 1.1B Β· Q8_0 Β· ctx=2048",
"uptime_seconds": 142
}curl http://192.168.1.42:8080/v1/models \
-H "Authorization: Bearer <your-token>"{
"object": "list",
"data": [
{
"id": "neurallite-local",
"object": "model",
"owned_by": "neurallite"
}
]
}Supports both streaming ("stream": true) and non-streaming modes.
curl http://192.168.1.42:8080/v1/chat/completions \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" \
-d '{
"model": "neurallite-local",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
],
"max_tokens": 256,
"temperature": 0.7,
"stream": false
}'Response:
{
"id": "chatcmpl-a3f1b2c4",
"object": "chat.completion",
"model": "neurallite-local",
"choices": [{
"index": 0,
"message": { "role": "assistant", "content": "The capital of France is Paris." },
"finish_reason": "stop"
}]
}Streaming ("stream": true) β Server-Sent Events:
data: {"id":"chatcmpl-a3f1b2c4","choices":[{"delta":{"content":"The"},...}]}
data: {"id":"chatcmpl-a3f1b2c4","choices":[{"delta":{"content":" capital"},...}]}
data: [DONE]
curl http://192.168.1.42:8080/v1/completions \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" \
-d '{"prompt": "Once upon a time", "max_tokens": 128}'Because the API is OpenAI-compatible, you can point any existing OpenAI client at your phone with zero code changes β just change the base_url and api_key.
from openai import OpenAI
client = OpenAI(
base_url="http://192.168.1.42:8080/v1",
api_key="paste-your-token-here"
)
response = client.chat.completions.create(
model="neurallite-local",
messages=[{"role": "user", "content": "Explain quantum entanglement simply."}],
stream=True
)
for chunk in response:
print(chunk.choices[0].delta.content or "", end="", flush=True)- Install Open WebUI on your PC.
- Go to Settings β Connections β OpenAI API.
- Set API URL to
http://<phone-ip>:8080/v1. - Set API Key to your NeuralLite token.
- Select
neurallite-localfrom the model dropdown.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="http://192.168.1.42:8080/v1",
api_key="paste-your-token-here",
model="neurallite-local"
)
print(llm.invoke("Write a haiku about Android."))LlamaEngine is a Kotlin singleton that wraps the native llama.cpp library via JNI (libllama_android.so).
loadModelSafe(modelPath, nThreads, nCtx)
β
ββ Unloads any existing model first (AtomicLong handle)
ββ Calls JNI loadModel() β returns native handle
ββ Fetches model metadata via getModelInfo()
runInferenceSafe(prompt, maxTokens, temperature, onToken)
β
ββ Runs entirely on Dispatchers.IO (never blocks UI)
ββ onToken callback β each generated token streamed live
ββ Full response returned as String when complete
Key design decisions:
- The native handle is stored in an
AtomicLongβ safe for concurrent access without locks. - Thread count defaults to
availableProcessors() / 2(capped at minimum 2) to avoid thermal throttling. - Context window (
nCtx) defaults to 2048 β configurable per model. - Errors surface via a
StateFlow<LlamaError?>so the UI reacts reactively.
Before choosing a model, NeuralLite scans your device and assigns it a performance tier:
| Tier | Label | RAM | CPU Cores | Recommended Models |
|---|---|---|---|---|
| 1 | π’ Flagship | β₯ 8 GB | β₯ 8 | Llama 3 8B, Mistral 7B |
| 2 | π΅ Mid-range | β₯ 4 GB | β₯ 6 | Mistral 7B, Phi-2, Gemma 2B |
| 3 | π‘ Entry | β₯ 3 GB | β₯ 4 | Phi-2, Gemma 2B, TinyLlama |
| 4 | π΄ Minimal | < 3 GB | < 4 | TinyLlama 1.1B only |
The scan reads: total RAM, available RAM, CPU core count, CPU ABI (arm64-v8a, etc.), free storage, and Android API level. Results are cached in SharedPreferences so subsequent launches are instant.
The Capability Bar in the Detect screen visually shows exactly which models are reachable on your current hardware.
All models are downloaded from HuggingFace in GGUF format. Storage usage is tracked live with a progress bar.
| Model | Size | RAM | Tok/s (est.) | Tiers | Tags |
|---|---|---|---|---|---|
| TinyLlama 1.1B Q8_0 | 1.1 GB | 1.5 GB | ~25 | 3, 4 | ultra-light, chat |
| Phi-2 2.7B Q4_K_M | 1.6 GB | 3.0 GB | ~12 | 2, 3 | chat, code, instruct |
| Gemma 2B IT Q4_K_S | 1.3 GB | 2.5 GB | ~15 | 2, 3 | instruct, chat |
| Mistral 7B Instruct Q3_K_M | 3.1 GB | 5.5 GB | ~6 | 1, 2 | instruct, chat, powerful |
| Llama 3 8B Instruct Q4_K_M | 4.9 GB | 7.0 GB | ~5 | 1 | instruct, chat, powerful |
Each model card shows:
- Download / Load / Delete actions
- Live download progress bar
β οΈ RAM warning if device RAM is insufficient- β "Recommended" badge if the model matches your tier
The app has 4 screens accessible via the bottom navigation bar:
Tap the radar button to scan your device. Your hardware tier is displayed with a color-coded badge and a capability bar showing which models are accessible.
Browse the model catalog, download models directly from HuggingFace, load/unload them into the inference engine, and monitor storage usage.
- Start / Stop the HTTP server with a single tap (animated pulse when running).
- View Local (
localhost:8080/v1) and LAN (192.168.x.x:8080/v1) endpoint URLs (tap to copy). - View / Copy / Regenerate the Bearer API token.
- Live metrics: total request count, average tokens per second.
- Request log: scrollable list of the last 50 API calls with status codes and latency.
App-level configuration options.
Download the latest APK directly and sideload it:
Note: You will need to enable "Install from unknown sources" in your Android settings. Go to Settings β Apps β Special app access β Install unknown apps and allow your file manager or browser.
Steps:
- Download
NeuralLite.apkto your phone. - Open it with your file manager and tap Install.
- Grant the requested permissions (storage, notifications).
- Open the app β Detect tab β tap Run Hardware Scan.
- Go to Models β download a model suited to your tier.
- Go to Server β tap the power button to Start.
- Copy the LAN URL and API token, then connect from any device on your Wi-Fi.
| Concern | How NeuralLite handles it |
|---|---|
| API Authentication | Every /v1/... route requires a Authorization: Bearer <token> header |
| Token Generation | UUID v4 token generated on first server start |
| Token Storage | Stored in EncryptedSharedPreferences with AES-256-GCM encryption |
| Token Rotation | Tap "Regenerate" in the Server screen to invalidate and replace |
| CORS | All responses include Access-Control-Allow-Origin: * for browser clients |
| Network Scope | Server binds to 0.0.0.0 β accessible on LAN only (no internet exposure) |
β οΈ Do not run NeuralLite on public Wi-Fi networks. The server is accessible to anyone on the same network who has the token.
- Android 8.0 (API 26) or higher
- ARM64 device (
arm64-v8aABI) - Wi-Fi connection for LAN API access
- Storage space for GGUF models (1.1 GB β 5 GB per model)
- RAM β₯ 2 GB (more is better β see tier table above)
# Clone the repository
git clone https://github.com/bitxwolf/NeuralLite.git
cd NeuralLite
# Open in Android Studio (Hedgehog or newer recommended)
# Or build via Gradle:
./gradlew assembleReleaseThe native libllama_android.so is pre-compiled and included in the APK. If you need to recompile llama.cpp for Android, see the llama.cpp Android build guide.
| Layer | Technology |
|---|---|
| UI | Jetpack Compose Β· Material 3 |
| Architecture | MVVM Β· StateFlow Β· Coroutines |
| HTTP Server | NanoHTTPD (embedded, zero-dependency) |
| Inference | llama.cpp via JNI (libllama_android.so) |
| Encryption | AndroidX Security Β· EncryptedSharedPreferences (AES-256) |
| Network Discovery | Android NSD (mDNS / DNS-SD) |
| Model Downloads | Android DownloadManager |
| Language | Kotlin 100% |
Made with β€οΈ by bitxwolf
Your phone. Your model. Your API.


