Skip to content

msradam/dream-meridian

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

54 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ’  DreamMeridian

Offline AI-Powered Spatial Intelligence for ARM Devices

DreamMeridian is a fully offline spatial query system that runs entirely on ARM-based devices like Raspberry Pi 5. It combines a quantized LLM (xLAM-2-1B) with high-performance graph routing and spatial databases to answer natural language questions about geographic dataโ€”without any cloud connectivity.

Built for humanitarian scenarios where internet access is unreliable: refugee camp navigation, disaster response coordination, and field operations planning.

Author: Adam Munawar Rahman

ARM Offline License Status


๐ŸŽฌ Watch the Demo (3 min) โ€” See DreamMeridian running on a Raspberry Pi 5

๐Ÿ“– Full Project Writeup โ€” Technical deep-dive, ARM optimization rationale, benchmarks, and humanitarian context for the ARM AI Developer Challenge 2025


DreamMeridian Dashboard Web dashboard showing isochrone analysis in Cox's Bazar refugee camps


๐Ÿ“‘ Table of Contents


๐ŸŽฏ Key Features

  • 100% Offline: All AI inference runs locally on ARM CPUโ€”no cloud, no API keys
  • Natural Language Queries: Ask questions like "Find hospitals near Camp 6" or "Show 15 minute walkable area from Condado"
  • Real Routing: Actual walking routes calculated on road network graphs (not straight-line distances)
  • Three Disaster Response Scenarios: Pre-built datasets for Cox's Bazar, San Juan, and Jakarta
  • Sub-15 Second Response: Optimized for Raspberry Pi 5 with ARM NEON/dotprod instructions

๐Ÿ—๏ธ Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        Natural Language Query                   โ”‚
โ”‚                "Find nearest hospital to Camp 6"                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                  โ”‚
                                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Geocoding Layer                                                โ”‚
โ”‚  Place name โ†’ lat/lon: "Camp 6" โ†’ (21.20, 92.16)                โ”‚
โ”‚  Modified query: "Find nearest hospital to (21.20, 92.16)"      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                  โ”‚
                                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  xLAM-2-1B (Q5_K_M)  โ”‚  Tool-calling LLM optimized for ARM      โ”‚
โ”‚  via llama.cpp       โ”‚  NEON + dotprod + GBNF grammar           โ”‚
โ”‚  Selects tool + generates arguments with resolved coordinates   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                  โ”‚
                                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Spatial Tools                                                  โ”‚
โ”‚  list_pois โ”‚ find_nearest_poi_with_route โ”‚ calculate_route      โ”‚
โ”‚  find_along_route โ”‚ generate_isochrone โ”‚ geocode_place          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                  โ”‚
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ–ผ                           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DuckDB + Spatial        โ”‚    โ”‚  NetworKit Graph Engine          โ”‚
โ”‚  POI queries, geocoding  โ”‚    โ”‚  Dijkstra routing on road networkโ”‚
โ”‚  ~6K-41K POIs per city   โ”‚    โ”‚  ~25K-208K nodes per city        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ Pre-Built Datasets

Three disaster response scenarios with pre-built offline data:

Location Context Nodes Edges POIs Place Names
coxs_bazar Rohingya refugee camps, Bangladesh 27,551 71,530 6,509 464
san_juan Hurricane response, Puerto Rico 24,602 61,055 11,351 405
jakarta Urban flood response, Indonesia 208,281 508,954 41,028 331

Data sourced from OpenStreetMap via OSMnx. Includes hospitals, clinics, pharmacies, schools, shelters, banks, markets, fuel stations, police stations, and places of worship.


๐Ÿ“‹ Requirements

Hardware

  • Raspberry Pi 5 (8GB+ RAM recommended) or any ARM64 device
  • ~4GB storage for models and data
  • Tested on: Pi 5 16GB running DietPi, M3 MacBook Air

Software Prerequisites

# System packages (Debian/Ubuntu/DietPi/Raspberry Pi OS)
sudo apt update
sudo apt install -y build-essential cmake git python3 python3-venv libopenblas-dev

# uv (fast Python package manager)
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.bashrc  # or restart shell

๐Ÿš€ Installation

Full instructions including Apple Silicon (macOS) setup are available in INSTALL.md.

1. Clone the Repository

git clone https://github.com/msradam/dream-meridian.git
cd dream-meridian

2. Install Python Dependencies

uv sync

3. Build llama.cpp (ARM-Optimized)

git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp && mkdir build && cd build

# Configure for Cortex-A76 (Pi 5)
cmake .. \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_C_FLAGS="-mcpu=cortex-a76 -O3 -ffast-math -fno-finite-math-only" \
    -DCMAKE_CXX_FLAGS="-mcpu=cortex-a76 -O3 -ffast-math -fno-finite-math-only" \
    -DGGML_NATIVE=ON \
    -DGGML_LTO=ON \
    -DLLAMA_CURL=OFF

cmake --build . -j4 --config Release
cd ../..

4. Download the LLM

mkdir -p models

uv run --with huggingface-hub hf download \
    Salesforce/xLAM-2-1b-fc-r-gguf \
    xLAM-2-1B-fc-r-Q5_K_M.gguf \
    --local-dir ./models

5. Verify Installation

ls -la llama.cpp/build/bin/llama-server  # Should exist
ls -la models/*.gguf                      # Should show ~1.1GB file
ls -la data/                              # Should show coxs_bazar, san_juan, jakarta

๐ŸŽฎ Running DreamMeridian

Start the LLM Server (Terminal 1)

./llama.cpp/build/bin/llama-server \
    -m ./models/xLAM-2-1B-fc-r-Q5_K_M.gguf \
    --grammar-file tool_grammar.gbnf \
    -c 2048 -t 4 --mlock \
    --host 0.0.0.0 --port 8080

Wait for "server is listening on http://0.0.0.0:8080".

Command Line Interface (Terminal 2)

uv run python dream-meridian.py -l <location> "<query>"

Streamlit Dashboard (Terminal 2)

uv run streamlit run app.py --server.port 8501

Open http://[pi-ip-address]:8501 in your browser.


๐Ÿ’ฌ Recommended Queries

Cox's Bazar, Bangladesh (Rohingya Refugee Camps)

uv run python dream-meridian.py -l coxs_bazar "I need to find the nearest hospital to Camp 6"
uv run python dream-meridian.py -l coxs_bazar "How do I walk from Camp 3 to Camp 8W"
uv run python dream-meridian.py -l coxs_bazar "Show me everywhere I can walk to in 15 minutes from Camp 8W"

San Juan, Puerto Rico (Hurricane Response)

uv run python dream-meridian.py -l san_juan "Where is the closest hospital to Condado"
uv run python dream-meridian.py -l san_juan "How do I get from Condado to Santurce on foot"
uv run python dream-meridian.py -l san_juan "Show me a 20 minute walking radius from Condado"

Jakarta, Indonesia (Urban Flood Response)

uv run python dream-meridian.py -l jakarta "Is there a bank near Gelora"
uv run python dream-meridian.py -l jakarta "What is the distance on foot from Pinangsia to Kalianyar"
uv run python dream-meridian.py -l jakarta "What can I reach in 15 minutes walking from Serdang"

โšก Benchmark Results

Full benchmark suite of 57 natural language queries across all three locations.

./benchmark_full.sh
Metric Value
Total queries 57
Success rate 94.7% (54/57)
Avg response time 10.87s
LLM inference 8.9 tok/s
Location Queries Correct Success Rate
Cox's Bazar 19 19 100%
San Juan 19 18 94.7%
Jakarta 19 17 89.5%

See BENCHMARK_RESULTS.md for detailed examples, failure analysis, and improvement pathways.


๐Ÿ”ง Spatial Tools

Tool Description Example
list_pois List POIs of a type within radius "List hospitals within 2km of Camp 6"
find_nearest_poi_with_route Find nearest POI with walking route "Find nearest clinic to Condado"
calculate_route Walking route between two points "Route from Camp 6 to Camp 9"
find_along_route Find POIs along a walking path "Hospitals along route from A to B"
generate_isochrone Walkable area from a point "15 minute walking radius from Camp 6"
geocode_place Convert place name to coordinates "Where is Camp 6 located"

๐Ÿ“ Project Structure

dream-meridian/
โ”œโ”€โ”€ dream-meridian.py      # Main query engine
โ”œโ”€โ”€ spatial_tools.py       # Spatial query functions
โ”œโ”€โ”€ geocode_layer.py       # Place name resolution
โ”œโ”€โ”€ app.py                 # Streamlit dashboard
โ”œโ”€โ”€ build_location.py      # Dataset builder
โ”œโ”€โ”€ tool_grammar.gbnf      # GBNF grammar for tool calls
โ”œโ”€โ”€ benchmark_full.sh      # Benchmark suite
โ”œโ”€โ”€ BENCHMARK_RESULTS.md   # Detailed benchmark analysis
โ”œโ”€โ”€ INSTALL.md             # Full installation instructions
โ”œโ”€โ”€ WRITEUP.md             # Full project writeup
โ”œโ”€โ”€ pyproject.toml         # Python dependencies
โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ images/            # Screenshots and diagrams
โ”œโ”€โ”€ static/                # Fonts for Streamlit dashboard
โ”œโ”€โ”€ data/
โ”‚   โ”œโ”€โ”€ coxs_bazar/        # Cox's Bazar dataset (27K nodes, 6K POIs)
โ”‚   โ”œโ”€โ”€ san_juan/          # San Juan dataset (24K nodes, 11K POIs)
โ”‚   โ””โ”€โ”€ jakarta/           # Jakarta dataset (208K nodes, 41K POIs)
โ”œโ”€โ”€ models/                # LLM models (gitignored)
โ””โ”€โ”€ llama.cpp/             # Built llama.cpp (gitignored)

๐Ÿ› ๏ธ Troubleshooting

LLM server won't start

lsof -i :8080              # Check if port is in use
pkill -f llama-server      # Kill existing process

Out of memory

# Reduce context size to 1024
./llama.cpp/build/bin/llama-server \
    -m ./models/xLAM-2-1B-fc-r-Q5_K_M.gguf \
    -c 1024 -t 4 --host 0.0.0.0 --port 8080

Slow queries

# Ensure CPU governor is set to performance
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# Should be "performance" not "powersave"

๐Ÿค Contributing

Contributions are welcome! Please open an issue first to discuss proposed changes.

If you'd like to add support for a new location, see build_location.py for the dataset generation pipeline.


๐Ÿ™ Acknowledgments

  • xLAM-2 by Salesforce AI Research - Tool-calling LLM
  • llama.cpp by Georgi Gerganov - Efficient inference engine
  • NetworKit - High-performance graph algorithms
  • DuckDB - Embedded analytical database
  • OSMnx by Geoff Boeing - Street network retrieval and analysis
  • OpenStreetMap - Geographic data

๐Ÿ“„ License

MIT License - See LICENSE for details.


๐Ÿ† ARM AI Developer Challenge 2025

This project was built for the ARM AI Developer Challenge, demonstrating on-device AI inference for humanitarian applications on ARM-powered devices.

Key Innovation: Natural language spatial queries running entirely offline on a ~$210 single-board computer, enabling field workers in connectivity-constrained environments to access critical geographic intelligence.

About

๐Ÿ’  Geospatial intelligence at the Edge.

Topics

Resources

License

Stars

Watchers

Forks

Contributors