Skip to main content

Smart Spatial System

Ask a geospatial question in plain language and get map layers, tables, reports and files back.

Smart Spatial System is a plugin-based GeoAI backend with a React workbench. A question such as "rank these candidate properties by distance to metro stations, malls and main roads" is turned into a structured QuerySpec, planned as a DAG of spatial operations, executed by plugins against uploaded files or PostGIS, and returned as map-ready outputs with a full execution trace.

It is the application built on top of geochat-platform: plugins are written with geochat_sdk and executed through geochat_kernel.

Status: published and usable, still refactoring internally. Logic is moving out of orchestrator/ into the layered smart_spatial_system/ package (see docs/ARCHITECTURE_TARGET.md); the orchestrator/*_service.py modules are compatibility shims during that move. The public surface - the CLI, the HTTP API and the documented entry points below - is stable.


How a query runs

natural-language question
  → QuerySpec            LLM (OpenAI-compatible) or rule-based, with PostGIS semantic context
  → DeterministicPlanner + OP_CATALOG
  → DagPlan → DagExecutor
  → CapabilityRegistry   weighted router, learns from user feedback
  → geochat_sdk plugins  vector, raster, PostGIS, reporting, export
  → outputs              map layers · tables · documents (PDF/HTML) · files · trace

Design decisions are recorded as ADRs in docs/: single kernel pipeline, artifact-based responses, a multilingual semantic layer (English and Persian questions, language-neutral concepts inside), and a service-oriented modular backend.

What is in the box

  • 36 plugins registered by default: buffer, spatial join, intersection, predicates, dissolve, nearest neighbour, distance, area and perimeter, centroids, CRS transform, geometry validation, attribute statistics, zonal statistics, band math, NDVI and spectral indices, slope/aspect, raster clip/reclassify/threshold/statistics, raster-to-vector, WMS/WFS fetcher, PostGIS connector, feature scoring and enrichment, vector loader, report builder, PDF renderer and data export. Raster uploads load through local_raster_loader, and geocoding_resolver ships but is not registered by default.
  • Data sources: raster and vector uploads, CSV tables, WMS, WFS, PostGIS and remote URLs, grouped into projects.
  • Workflows: multi-amenity accessibility scoring (rule-based, reproducible), real-estate site ranking with a generated PDF report, and NDVI analysis.
  • Learning router: capability weights adjust from user feedback, with reviewable weight proposals.
  • Workbench: React + Leaflet UI for queries, step-by-step progress, map layers, inspection, plugin settings and outputs.

Repository layout

api/                     FastAPI app and routers
orchestrator/            query parsing, planning (QuerySpec, OP_CATALOG, DAG), routing, services
smart_spatial_system/    new layered package (application services; other layers being filled in)
plugins/                 geochat_sdk capability plugins
config/plugins/          per-plugin YAML config (*.example.yaml are the templates)
templates/reports/       report templates (real-estate report)
scripts/sql/             PostGIS views for the Tehran OSM demo
examples/                runnable examples and their sample data
frontend/                React + Vite workbench
tests/                   pytest suite (~150 modules)
docs/                    architecture, ADRs, API contracts, phase reports

Runtime data (outputs, uploads, projects) is written to var/ by default, or to SMART_SPATIAL_RUNTIME_DIR, and is not committed.

Install

Requires Python 3.11+.

pip install "smart-spatial-system[raster,pdf]"

Extras are optional and independent: raster (rasterio - NDVI, spectral indices, zonal statistics), pdf (weasyprint - PDF reports), postgis (psycopg), dev (pytest, ruff). Leaving one out does not break the install: the affected plugins are simply not registered, and the rest of the system runs normally.

Run the API:

smart-spatial-api serve --port 8000     # http://127.0.0.1:8000/docs

Set SMART_SPATIAL_API_KEY before exposing this beyond localhost. With it unset every endpoint except / and /health is open, and the server logs a warning saying so at startup. See docs/DEPLOYMENT.md.

Use it

Two ways in, both first-class: import the library, or call the HTTP API. Complete runnable versions of both are in examples/.

As a library

Score candidate sites by how close they are to the things that matter, with no server and no LLM involved:

from orchestrator.capability_registry import CapabilityRegistry
from orchestrator.planning.dag_executor import DagExecutor
from orchestrator.planning.planner import DeterministicPlanner
from smart_spatial_system.application.services.query_execution.accessibility_query_spec import (
    AmenitySpec, build_accessibility_initial_inputs, build_accessibility_query_spec,
)

amenities = [
    AmenitySpec(ref="metro", distance_field="distance_to_metro_m",
                max_distance_m=800.0, weight=3.0),
    AmenitySpec(ref="schools", distance_field="distance_to_school_m",
                max_distance_m=1200.0, weight=2.0),
]

query_spec = build_accessibility_query_spec(
    "Rank sites by access to metro and schools", amenities,
    target_crs="EPSG:31256",          # a projected CRS - see the note below
)

plan = DeterministicPlanner().build(query_spec)
registry = CapabilityRegistry.from_plugin_modules(tolerant=True)
result = DagExecutor(lambda name: registry.resolve(name).callable).execute(
    plan,
    initial_inputs=build_accessibility_initial_inputs(
        sites=sites_geojson,
        amenity_layers={"metro": metro_geojson, "schools": schools_geojson},
    ),
)

python examples/accessibility_analysis.py runs exactly this over five candidate sites in Vienna and prints the plan and the ranking:

Plan: 10 operations
  sites_metric      transform_vector_crs
  metro_metric      transform_vector_crs
  sites_with_metro  find_nearest_neighbors
  ...

Site accessibility ranking
  Rank  Name                  Accessibility score  Metro (m)  School (m)  Park (m)
  1     Site 3 - Praterstern  75.4                 23.0       407.0       711.0
  2     Site 4 - Ottakring    60.8                 56.0       684.0       4371.0
  3     Site 2 - Karlsplatz   59.8                 128.0      782.0       630.0

This path is rule-based, not LLM-backed: the operation chain follows mechanically from the amenity list, so identical inputs always produce an identical plan and identical numbers.

Distances need a projected CRS. The spatial operations measure planar distance in whatever units the input CRS uses and never reproject on your behalf, so EPSG:4326 input yields degrees. The generator reprojects every layer first; pass a local projected CRS for your study area (EPSG:31256 for Vienna, the relevant UTM zone elsewhere). EPSG:3857 is a safe global fallback but its metres are inflated by 1/cos(latitude) - about 1.5x at Vienna's latitude.

Over HTTP

import json, urllib.request

body = {"query": "Display the sites on the map", "inputs": {"vector": sites_geojson}}
req = urllib.request.Request("http://127.0.0.1:8000/query",
                             data=json.dumps(body).encode(), method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("X-API-Key", "...")          # when the server requires a key
response = json.loads(urllib.request.urlopen(req).read())

for layer in response["layers"]:
    print(layer["name"], layer["summary"]["feature_count"])

inputs is required and must be an object even when empty - it is where the data the question refers to is passed in, keyed by role (vector, raster, or a named layer). python examples/query_via_http.py runs this against a live server.

Questions are understood in English and Persian. A question is answered by the LLM-backed planner when an LLM key is configured, and by the rule-based paths otherwise.

Running from a checkout

For development on the system itself, or to use the React workbench:

git clone https://github.com/arazshah/smart_spatial_system.git
cd smart_spatial_system

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.lock      # pinned; requirements.txt for latest upstream

cp .env.example .env                  # add your LLM key
uvicorn api.main:app --reload         # http://127.0.0.1:8000/docs

Frontend:

cd frontend
cp .env.example .env
npm install && npm run dev            # http://localhost:5173

Docker Compose (backend + frontend, PostGIS optional):

docker compose up --build

PostGIS demo data (Tehran OpenStreetMap): see data/README.md. Full deployment guide - environment variables, authentication, CORS, PostGIS: docs/DEPLOYMENT.md.

API at a glance

Area Endpoints
Query POST /query · POST /planner/intent · POST /feedback
Requests & outputs GET /requests · GET /requests/{id} · …/map-layers · …/outputs · …/outputs/files/{name} · …/documents/{name}
Projects & data /projects · /uploads/raster · /uploads/vector · /data-sources/{csv-table,wms,wfs,postgis,url}
Plugins & settings /plugins · /plugins/{id}/config · /settings/runtime · /settings/llm/smoke-test
Router weights /weights · /weights/save · /weights/reload · /weights/proposals/apply
System GET /health

Full request and response contracts are in docs/phase5_query_api_contract.md and the other docs/phase5_* files.

Development

pytest                # full suite
ruff check .          # lint

Author

Araz Shahkarami · araz.me

Release files for smart-spatial-system 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for smart-spatial-system 0.2.0
File Size Uploaded
smart_spatial_system-0.2.0.tar.gz 587.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for smart-spatial-system 0.2.0
File Interpreter ABI Platform
smart_spatial_system-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / smart_spatial_system-0.2.0.tar.gz

Download URL smart_spatial_system-0.2.0.tar.gz
Size 587.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4af095531ff18dc91c27d5318e92d326dfaa8c2a5a94d2d20d1d037c935a7901
BLAKE2b-256 checksum
How to use checksums
b7f83dbb2b5d9fd155a132a5866f26e0f9baa5ae134560d3eadc4a1229d8ce14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / smart_spatial_system-0.2.0-py3-none-any.whl

Download URL smart_spatial_system-0.2.0-py3-none-any.whl
Size 524.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
41a174f288aecb8a62e9acb0593875b1fdd645856508a5dcf2e8aa35bff8ba83
BLAKE2b-256 checksum
How to use checksums
6615aedae62c8383e3376d9b1b36c9ede97a1b531a95bd80ee5b253ce14054b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.1

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page