The Problem
SpatialLLM attempts to bridge Large Language Models with urban spatial intelligence through point cloud processing, OSM data integration, and scene graph generation. However, the codebase shows significant structural fragility: no test coverage, no CI/CD gate, and critical/high severity vulnerabilities in pinned dependencies that are reachable without credentials or user interaction. A consultant would flag the dependency hygiene issues as the highest priority remediation, as they represent immediate exploitable risk.
What This Does
SpatialLLM is a 24-file framework (Python/pip) that processes urban spatial data through a three-step pipeline: OSM extraction (process/osm_process.py), point cloud annotation (process/auto_annotate.py), and scene graph generation (process/generate_scene_graph.py). The inference layer (infer/inference.py) then exposes a chat interface over a model client. The repository contains no test files, no CI configuration, and a 10.8MB overview.png checked into version control — each clone and CI checkout incurs that data transfer cost. Four internal modules exist with zero import edges between them, and the two entry points (run and main) each reach 11-12 functions but are called from only a single place in the repo, indicating low internal connectivity and high external dependency.
How It Is Wired
Execution starts at two entry points:
runinprocess/generate_scene_graph.py:188— reaches 11 function(s), called by nothing else in the repo. This is the primary end-to-end orchestrator.mainininfer/inference.py:146— reaches 12 function(s), itself called from 1 place(s). This is the CLI/chat entry point.
The internal call graph has 28 resolved call edges. Key hubs:
register_pc(inprocess/auto_annotate.py) is called from 5 places:load_pc,grid_pc,load_control_points,calculate_height_scale. It chains tohaversine,load_pc, andgrid_pc._simplify_coordsis called from 2 places (inprocess/osm_process.pyandprocess/generate_scene_graph.py).grid_pcis called from 2 places.
Paths leaving the process:
run→ filesystem viaself.output_path.parent.mkdirmain → chat→ model viaself.client.chat.completions.create
process/generate_scene_graph.py defines 9 functions/1 class including __init__, load_shapefiles, points_to_polygon, get_height, query_nearby_features. It reads/writes files and is the only file called from run.
process/auto_annotate.py defines 9 functions/1 class including __init__, load_pc, load_control_points, grid_pc, calculate_height_scale. It reads/writes files and carries the medium-severity findings of broad exception handling and x4 deep nesting.
infer/inference.py defines 5 functions/1 class including json_to_compact_text, __init__, _init_client, chat, main. It calls into 2 modules and a model for inference (self.client.chat.completions.create).
process/osm_process.py defines 8 functions/1 class including __init__, _get_geometry_type, _simplify_coords, load_shapefiles, process_polygons. It is the entry point for OSM data extraction.
The module graph shows four isolated components with no import edges between them — each runs in isolation without shared abstractions. This means changes to one pipeline step (e.g., switching the point cloud format) require coordination across all files rather than a single fix.
How To Use It
Setup: Create a conda environment and install dependencies as documented in README.md:
conda create -n spatialllm python=3.8
conda activate spatialllm
conda install -c conda-forge geopandas
conda install -c conda-forge geopy
conda install -c conda-forge gdal
pip install -r requirements.txt
Configuration: The inference layer reads infer/config.yaml for client setup. No environment variables are documented beyond the conda install steps.
Running the pipeline:
- OSM extraction:
python process/osm_process.py --shp_path <dir> --output <json> - Point cloud annotation:
python process/auto_annotate.py --work_dir <path> --shp_dir <dir> --pc_file <filename> --control_txt <file> --res <resolution> - Scene graph generation:
python process/generate_scene_graph.py --pc_file <annotated> --shp_dir <dir> --osm_map_file <file> --osm_json_file <input> --output_json <output> - Inference:
python infer/inference.py
Real-World Use
A city planning team could extract OSM building footprints via Step 1, annotate a LiDAR point cloud with semantic labels via Steps 2–3, then feed the resulting scene graph into infer/inference.py to enable natural-language queries like "which buildings in this district exceed 10 stories and have underground parking?" The structured text output could further power a web-based LLM interface for interactive spatial reasoning across stakeholders.
Code Health & Issues
The static analysis produced the following findings:
- [CRITICAL] Upgrade the pinned dependency carrying a critical advisory:
pillow@10.0.0CVE-2023-50447. The manifest pins the exact vulnerable version, so the risk is active. Fix: upgrade and commit the lockfile. - [HIGH] Upgrade the pinned dependency carrying a published advisory:
gdal@3.7.0CVE-2026-49014. The pinned version is the one that installs. Fix: upgrade and commit the lockfile. - [MEDIUM] Enable Dependabot or Renovate: 1 manifest, no update bot configured. Without a bot, published advisories sit unpatched.
- [MEDIUM] Move large binaries to Git LFS or out of the repository:
overview.pngis 10.8MB. Every clone pays for undiffed data. - [MEDIUM] Pin the resolution so a vulnerable version cannot install: no lockfile, and declared ranges reach
geopandas@0.10.0CVE-2025-69662 (high). Fix: commit the lockfile.
Beyond these measured findings: no test files, no CI/CD pipeline, no Dockerfile, and a 10.8MB binary committed directly to the repo.
The Bottom Line
SpatialLLM has a clear, functional pipeline for urban spatial reasoning, but the codebase is held back by critical dependency vulnerabilities, absent tooling (tests, CI, lockfile), and a large binary checked into version control. The four isolated modules work but lack internal cohesion — changing one step requires touching multiple files with no shared abstractions. Teams needing quick prototyping with urban spatial data could benefit from the pipeline structure, but they should pin dependency upgrades and address the hygiene gaps before production use.