Posts

Apollo Spatial VLM: From One Photo and One Sentence to 3D

Image
One photo, one sentence. “Locate the Sydney Opera House”, and a few seconds later the scene is in 3D, as Gaussian splats you can tilt around. Recently I came across a small project called Odyseus Spatial VLM by Mercurius Technologies. Two things grabbed me right away. The first was the name. I grew up on Greek mythology, and seeing Odysseus on a GitHub page brought back a lot of childhood memories. The second was the idea: take a vision language model (VLM), the kind of model that can look at a picture and answer questions about it, and ask it not just what is in the photo, but where it is, in 3D, in meters. I liked it so much that I forked it, played with it for a while, and kept adding things. It grew into its own project, which I named Apollo Spatial VLM . (Why Apollo? Mercury and Apollo have a lovely story together. I tell it at the end of the README.) How it works You upload a photo and type what you are looking for, someth...

FELN Decisions: Teaching a Small Model Which Layers a Question Needs

Image
When Unsloth published its guide on how to train your own decision model , I immediately thought of the North Sea. In Lunar Laya , I argued that a model should take a state and some text, and return a structured, measurable answer. Here was a way to turn any small LLM into exactly that kind of model, with a probability attached to every answer. So I had to try it on FELN. A quick recap for new readers. FELN (Find Existing Location with N layers) is the little query language behind my RAG , LoRA , Liquid and WebGPU experiments. A question such as “Find gas wells within 5 km of oil pipelines” becomes a plan with three parallel lists: layers , where and relations . The first layer is the one returned; any other layer only filters it through a spatial relation. All those projects generate the whole plan in one go. This time, I wanted to pull out the very first decision and give it to a model that does nothing else: which layers does this question need, and which one is primary? One...

arcpi: Not Everything Needs an MCP to Be Agentic

Image
Every time I open my feed these days, somebody has wrapped an API in an MCP server. Weather? MCP. Calendar? MCP. I fully expect my toaster to ship one next week. Don't get me wrong, I like MCP and I use it. But I kept staring at the ArcGIS REST API, with years of well-documented endpoints for search, geocoding, routing, demographics and maps, and asking myself a simple question: does an agent really need another server in front of all of that to be agentic? So I built arcpi to find out. The old way and the new way, in one script arcpi runs on pi , a minimalist agent harness that lives in the terminal. I gave it four small Markdown skills, written from the Esri REST documentation, that tell the model which endpoint to call and with which parameters. And one TypeScript extension that makes the HTTP call as the signed-in user. That's it. No ArcGIS MCP server, no build step, no dependencies. The magic is code mode. Instead of calling one tool, waiting, thinking, and call...

ProCowork: Letting Claude Drive ArcGIS Pro

Image
This past July, I had the pleasure of presenting ProCowork at the Esri User Conference in San Diego. For those who could not make it (or were busy chasing the next session across the convention center), here is the short version of what I showed, and why I built it. I have been playing with GenAI and GIS for a while now. Asking a language model to write ArcPy is old news. What I really wanted was a model that could do the work, on my open project, inside my running ArcGIS Pro session, while I watch. ProCowork is an experimental ArcGIS Pro add-in that puts the Claude Code engine in a dockable chat panel. You type a request, Claude writes the Python, the add-in runs it against the live map, and the code and the results come back into the same panel. So I can type things like: “List the layers in the current map.” “Add a DOUBLE field POP_DEN to Parcels and set it to POP / AREASQMI.” “Select parcels where POP_DEN > 5000 and zoom to...

Lunar CLM: From 869 ms to 20 ms per Decision on a Mac

Image
In my last lander post I spent a few paragraphs on Jev , the System One decision model TypeSafe AI opened to early access this month. You hand it a block of state and typed questions, and it returns a probability for every choice. No text to parse. I also made a claim I had not tested: my lander talks to its model through one call, agent.predict(prompt, QUESTIONS) , so swapping in a different decision model should be an adapter, not a redesign. Then I read about Contrastive Language Models (CLM). It takes the same contract and builds it in the open: a block of state in, typed questions, a probability per choice out, with source code and released 8B heads you can run yourself. Its server even answers on an endpoint called /v1/systemone . Jev I can only read about. CLM I could actually test. I had to find out. The adapter part turned out to be true. It was everything after that which kept me busy. The small CLM I trained on my Mac, with no overrides. The lander starts upside do...

The Trainee Got Better. It Still Cannot Fly Alone.

Image
I ended The Engineer and the Trainee with a plan: roll out the shielded pilot, relabel every visited state with MPC, retrain, and see whether the trainee could finally fly on its own. That is still the plan. But before getting there I did something lazier, and the result was more interesting than I expected. I also fixed something that had been bothering me every time I watched a flight. The same recorded flight as last time, re-run with a smoother controller and a retrained model. The engine loses 60% of its thrust at ten seconds, the estimate falls to 40%, and the shield now steps in on about one command in eight instead of one in three. The lander had the shakes Watching a descent, the ship twitched. Not a rendering artifact — the controller really was changing its mind. I measured it: over 30 flights the beam search picked a different command on 77.7% of decisions. Every fifth of a second it re-derived the whole plan from scratch, and when two commands were nearly tie...

The Engineer and the Trainee: Adaptive MPC Guiding and Shielding Laya

Image
Two of my recent lander experiments kept nagging at me. In One Lander, Three Controllers , an adaptive MPC learned its engine during the flight and landed through a power loss with no training data at all. In Lunar Laya , a small decision model on Apple MLX turned a text description of the flight into structured choices, but the text carried hints from a fixed feedback law that assumed a healthy engine. Cut the engine power and that model crashed every time, faithfully following bad advice. So I asked the obvious question: what happens if the engineer writes the hints for the trainee? The result is Lunar MPC + Laya . An actual recorded flight. Laya proposes every command from telemetry alone; adaptive MPC vetoes about one in three. The engine loses 60% of its thrust at ten seconds, the estimate drops to 40%, and the lander touches down at seventy. The engineer and the trainee The game is the same arcade-style lander from Lunar Laya: three pads on bumpy terrain, a tilt control, a...