nutonic-pro-materialization / README.package.md
Tonic's picture
ci: deploy pro_materialization (d17aaa4019b1)
71ceb12 verified
# PRO materialization service
This worker turns a place on the map into the evidence bundle that NU:TONIC's satellite intelligence stack can reason about. It fetches or prepares imagery, Sentinel-2 inputs, VLM-ready PNGs, and TiM-ready arrays so the app can move from "look at this area" to "explain what may be changing here."
For competition reviewers, this is the practical bridge between the public demo and the AI stack:
1. Pick an area.
2. Materialize the imagery and satellite context.
3. Feed the VLM and TiM paths.
4. Return a PRO-style bundle for human inspection.
HTTP worker for **`PRO_MATERIALIZATION_SERVICE_URL`** / **`NUTONIC_PRO_MATERIALIZATION_SERVICE_URL`** (`docs/SERVER-AND-INFERENCE-ARCHITECTURE.md` §5.3, `plans/2026-04-12-pro-materialization-fetch-and-downscale-service.md`). **Kotlin clients do not call this URL** (`rules/13-client-cache-and-data-plane.md`); the thin **`server/`** may orchestrate **`POST /api/v1/pro/jobs`** → **`POST …/internal/v1/materialize`**.
## Implemented
### P0–P1
- **`GET /health`**, **`GET /internal/v1/healthz`** (`s2_asset_mapping_version` from packaged YAML).
- **`POST /internal/v1/materialize`** with **`sentinel_fetch_mode": "MINIMAL_RGB"`** (default): Mapbox pin → **`vlm_contract_id`** PNG (`mapbox_rgb` inline base64) + optional **`RGB_mapbox`** TiM NPZ (`[1,3,224,224]` BGR **0–255**).
- **`vlm_contract_id`**: **`nutonic.pro.vlm.v1_512`** → roles **`mapbox_rgb`** only. **`nutonic.pro.vlm.v1_512_fc_scl`** (plan §6.4) adds **`sentinel_fc`** (SWIR2/NIR/red false-color PNG) + **`cloud_mask_thumb`** (SCL → semi-transparent RGBA PNG); requires **`TERRAMIND_SPECTRAL`** or **`FULL_STAC`** and optional **`[s2]`** deps. **`nutonic.pro.vlm.v1_512_s2_only`** ships the same Sentinel-derived PNGs **without** **`mapbox_rgb`**; spectral modes do **not** require a Mapbox token for this contract.
- **`POST /api/v1/materialize/stub`** — backward-compatible wrapper.
### P2 (Sentinel-2 + TerraMind spectral path)
- **`sentinel_fetch_mode`**: **`TERRAMIND_SPECTRAL`** or **`FULL_STAC`** runs **STAC** (Earth Search default) + **12-band** patch at **224×224** (same asset key order as `terramind_tim_local.s2_stac`), reflectance scaled like TerraMind, merged into **`run_manifest.stac`**.
- **`enable_tim` + `tim_branch": "S2L2A_full"`** → NPZ key **`S2L2A`** `[1,12,224,224]` float32.
- **`FULL_STAC`** + **`RGB_mapbox`** TiM still uses Mapbox-derived RGB NPZ while STAC stack is fetched for manifest/audit.
- **`TERRAMIND_SPECTRAL`** + **`enable_tim`** requires **`S2L2A_full`** (422 `TIM_BRANCH_REQUIRES_S2L2A_FULL` if **`RGB_mapbox`**).
- **`data/s2_asset_allowlist.yaml`**: **`version`** + ordered **`assets`** (12 keys); drives cache key + STAC reads.
- **Sentinel/STAC** (`pystac-client`, **`rasterio`**) are **core dependencies** (since **0.3.1**). Spectral modes still return **503** `S2_DEPENDENCIES_MISSING` only if imports fail at runtime (e.g. missing GDAL system libs — the service **Dockerfile** installs **`gdal-bin`** / **`libgdal-dev`**).
## Constraints
- **No `torch`** / **no `terratorch`** in this package (plan §3.2).
- **`MAPBOX_ACCESS_TOKEN`** required when the resolved VLM contract includes **`mapbox_rgb`** (including **`MINIMAL_RGB`** and **`nutonic.pro.vlm.v1_512_fc_scl`** on spectral modes). Sentinel-only contracts (**`nutonic.pro.vlm.v1_512_s2_only`**) skip Mapbox entirely.
## Competition-facing role
The service is deliberately separate from the app client and from GPU-heavy TiM/VLM inference. That separation makes the product story stronger:
- The app stays easy to install from CI artifacts.
- The materialization worker handles data preparation.
- TiM and VLM workers can scale independently.
- The same workflow can support conservation review, flood triage, wildfire monitoring, and climate adaptation use cases.
## Environment
| Variable | Purpose |
| --- | --- |
| **`MAPBOX_ACCESS_TOKEN`** | Mapbox Static Images token (omit only for Sentinel-only VLM contracts on **`TERRAMIND_SPECTRAL`** / **`FULL_STAC`**). |
| **`NUTONIC_INFERENCE_REQUIRE_INBOUND_HMAC`** | When `1`, require signed requests. |
| **`NUTONIC_INFERENCE_HMAC_SECRET`** | Shared HMAC secret. |
## Run locally
```bash
pip install -e "./inference/pro_materialization_service[dev]"
set MAPBOX_ACCESS_TOKEN=your_token
uvicorn pro_materialization_service.main:app --host 127.0.0.1 --port 7865
```
From the monorepo root, tests should pick up this package’s `src` first (or use an editable install). If imports resolve to an older site-packages copy, set `PYTHONPATH` to `inference/pro_materialization_service/src` before running `pytest`.
## Docker
```bash
docker build -t nutonic-pro-materialization inference/pro_materialization_service
```
The packaged **Dockerfile** installs **`gdal-bin`** and **`libgdal-dev`** (rasterio needs GDAL/PROJ/GEOS at runtime on Debian slim), then **`pip install .`**, and fails the build if **`import rasterio`** / **`pystac_client`** do not work.