Nearby Mood Map turns a user's mood and location into nearby place and event recommendations, then displays them on an interactive Three.js map. Each live result receives a clearly labeled PixArt-Sigma representative image generated on an AMD ROCm GPU; it is not presented as a factual photograph of the venue or event.
The application is designed for the Radeon Cloud ROCm environment. PixArt inference deliberately refuses to fall back to CPU or any other non-ROCm GPU runtime, so a successful end-to-end image-generation run is an AMD ROCm run.
| Path | Purpose |
|---|---|
api.py |
FastAPI server, background recommendation jobs, health endpoint, and benchmark endpoint |
discovery.py |
Geoapify Places, Ticketmaster, and static-map integration |
pixart.py |
ROCm-only PixArt-Sigma loading and image generation |
benchmark_pixart.py |
Reproducible, synchronized PyTorch latency and memory benchmark |
threejs-poi-map-demo/ |
Interactive browser map and an offline-safe initial map demo |
artifacts/ |
Runtime benchmark reports; generated reports are ignored by Git |
.env.example |
Required API-key configuration template |
There is no Map3D pipeline, database, Node.js install, or Docker dependency in this repository.
- A Radeon Cloud notebook/instance with an AMD GPU, ROCm 7.2.1, 64-bit Linux, and CPython 3.12.
- Internet access to download the PixArt model on first use and to call Geoapify and Ticketmaster.
- A Geoapify API key and a Ticketmaster API key.
The AMD ROCm PyTorch, TorchVision, TorchAudio, and Triton wheels in requirements.txt target precisely this Linux/Python combination. The host image must provide the AMD driver and device access; installing a Python wheel cannot add those host capabilities.
requirements.txt is the complete direct Python dependency list:
- ROCm runtime: PyTorch, TorchVision, TorchAudio, and Triton
- API: FastAPI, Uvicorn, Pydantic, Requests, and Windows
tzdatasupport - PixArt: Diffusers, Transformers, Accelerate, Safetensors, SentencePiece,
ftfy, Beautiful Soup, and Pillow
Pip installs their transitive dependencies automatically. No packages need to be installed manually after the requirements command succeeds.
Create a Radeon Cloud notebook from the ROCm 7.2.1 / Python 3.12 template. In its Jupyter terminal, clone or open this repository and run all Python commands through /opt/venv/bin/python. Do not create a second virtual environment or mix in bare pip3, python, or uvicorn commands.
git clone <your-submission-repository-url> nearby-mood-map
cd nearby-mood-map
cp .env.example .env
nano .envSet both values in .env:
GEOAPIFY_API_KEY=your_geoapify_key
TICKETMASTER_API_KEY=your_ticketmaster_keyInstall the application and ROCm wheels. This is needed once per fresh environment, not after every code change.
/opt/venv/bin/python -m pip install --no-cache-dir -r requirements.txtBefore loading the model, confirm that this same interpreter can see ROCm and Diffusers:
rocm-smi
/opt/venv/bin/python - <<'PY'
import diffusers
import torch
print("PyTorch:", torch.__version__)
print("ROCm/HIP:", torch.version.hip)
print("GPU available:", torch.cuda.is_available())
print("Diffusers:", diffusers.__version__)
PYGPU available must be True and ROCm/HIP must have a version. rocm-smi by itself only proves that the host sees the GPU; the Python check proves that the application interpreter has the right PyTorch build.
In the first Jupyter terminal:
/opt/venv/bin/python -m uvicorn api:app --host 127.0.0.1 --port 8000The 127.0.0.1 binding is intentional: Radeon Cloud's HTTP tunnel connects to that loopback address. Verify the service from the same terminal or a second terminal:
curl --fail http://127.0.0.1:8000/api/healthThe JSON response should show both API keys as configured and pixart.ready: true with pixart.rocm: true.
In a second Jupyter terminal, install the Radeon Cloud tunnel tool once for a newly created notebook, then expose the already-running server:
/var/run/secrets/frp-self-service/install
"$HOME/.local/bin/rc-tunnel" expose --port 8000The command prints a public https://... URL. Open that URL in your local browser; it redirects to /map/. This is an HTTP tunnel, not an SSH tunnel. Do not use the notebook's internal IP address, 0.0.0.0, or port 8000 directly from your computer.
After restarting only Uvicorn, the existing tunnel normally remains usable. Check it before creating another one:
"$HOME/.local/bin/rc-tunnel" statusThe tunnel URL is public and the demo has no authentication, so share it only for testing and stop it when finished.
- Open the tunnel URL and confirm that the offline demo map displays its three checked-in sample images.
- Choose a destination (or use browser geolocation), enter a mood, and select Find nearby places.
- The browser starts a background job, polls for progress, and reloads the map after discovery, PixArt generation, and ground-map creation finish.
The normal UI may request up to eight 1024×1024 images at 20 denoising steps, so this can take a few minutes and use substantial GPU memory even at FP16.
For a fast smoke test, open <tunnel-url>/docs, expand POST /api/recommendations, choose Try it out, and submit one result and one short generation:
{
"mood": "I need a boost in energy",
"latitude": 34.4208,
"longitude": -119.6982,
"radius_m": 3000,
"max_results": 1,
"image_limit": 1,
"inference_steps": 4,
"guidance_scale": 4.5,
"seed": 42,
"timezone_name": "America/Los_Angeles"
}The response returns a job_id. Use GET /api/recommendations/{job_id} in the same API page until its status is done, then open the returned map_url. A live request overwrites threejs-poi-map-demo/config.js, writes generated images under threejs-poi-map-demo/images/, and may write ground-map.png; those live image files are intentionally ignored by Git.
Do not run the benchmark concurrently with an interactive recommendation job. On the Radeon Cloud terminal, with the GPU otherwise idle:
/opt/venv/bin/python benchmark_pixart.py --warmups 1 --runs 5 --steps 20The command prints a JSON report and writes it to artifacts/benchmarks/pixart-rocm.json. The report includes the loaded parameter count, ROCm/PyTorch and GPU information, pipeline-load time, synchronized latency samples, p50/p95/mean latency, throughput, peak memory, and a rocm-smi snapshot. Benchmark reports are intentionally untracked so repeated runs do not dirty the submission repository.
Alternatively, the running API exposes POST /api/benchmarks/pixart; it returns the report and saves a timestamped JSON file under artifacts/benchmarks/.
pixart.py loads PixArt-Sigma in torch.float16, matching the PixArt-Sigma model card. The Radeon Cloud image's preinstalled Apex previously caused an expected scalar type Float but found Half failure by auto-swapping in a fused T5 normalization kernel that assumes float32; pixart.py now blocks that Apex patch before transformers loads (see Radeon Cloud operations notes) so the pipeline can run FP16 without it.
diffusers is not installed: packages were installed into a different interpreter. Re-run the requirements command and Uvicorn command using/opt/venv/bin/python.GPU available: FalseorROCm/HIP: None: the Python environment does not have the matching ROCm PyTorch wheel, even ifrocm-smiworks.- Tunnel does not open: confirm
/api/healthsucceeds locally, confirm Uvicorn is bound to127.0.0.1:8000, then checkrc-tunnel statusrather than repeatedly creating new tunnels. - A local non-AMD computer can view the static map but cannot run PixArt inference or the submission benchmark. The server rejects non-ROCm image generation by design.
See Radeon Cloud operations notes for the cloud-specific details. PixArt-Sigma is distributed under the CreativeML Open RAIL++-M license.