Posts

FELN Liquid: Fine-Tuning a GIS Model on a Mac

I have been experimenting with small language models that translate everyday questions into structured GIS queries. With FELN Liquid , I wanted to explore the training side on the Mac itself. Could I take a compact model, teach it the conventions of a North Sea catalog, and complete the experiment locally? The first complete run used LiquidAI's LFM2.5-1.2B-Instruct with LoRA through MLX on an Apple M4 Max. Training took 48 minutes and 37 seconds. Including checkpoint evaluation and the final test, the workflow finished in just under an hour. That is a practical turnaround for trying an idea and inspecting what it learned. The task is familiar from the other FELN projects: turn a request into a JSON plan containing layers , where , and relations . A compact Layers.json catalog accompanies each request, supplying the names, types, aliases, codes, and hints that make the data meaningful. For example, “Show all wells with water depth > 350 meters” should produce: { ...

FELN WebGPU: A Language Model, a Database, and a Map in One Browser Tab

Image
I have been exploring how small language models can turn a plain-English question into a useful GIS query. With FELN LoRA, that meant training a model on a GPU and running it locally on my Mac. For feln-webgpu , I wanted to bring the language model, the database, and the map into the web application itself. Type “Give me all oil discoveries,” and the browser generates a query plan, compiles it to SQL, executes it, and draws the results. The example in the repository finds 562 discoveries, with 200 displayed. We can inspect the plan and SQL beside the map. I like being able to see what the model actually asked the database! The question, query plan, SQL, and resulting features in one browser tab. The pieces are a fine-tuned LiquidAI LFM2-350M model, Transformers.js running on WebGPU, DuckDB-Wasm with its spatial extension, and the ArcGIS Maps SDK for JavaScript. Once the assets have loaded, query generation and database execution happen on the user's machine. There is ...

FELN LoRA: Teaching a Small Model to Query the North Sea

In the FELN RAG experiment , I used a few relevant examples to help a language model translate a question into a spatial query. That got me interested in taking the next step: teaching a small model to do this particular job, then running it locally. I believe small language models have a big role to play in GIS. We have plenty of tasks with a well-defined vocabulary, a known catalog, and a very specific output. Turning a North Sea question into a query over wells, pipelines, and discoveries is one of them. That is the experiment behind feln-lora . The model is NVIDIA's Nemotron-3-Nano-4B, fine-tuned using LoRA and QLoRA through NeMo AutoModel . Training happens on an NVIDIA GPU. The resulting model runs on my Mac through llama.cpp and Metal, with the question staying on the machine. Now the best part: the latest local models produce a query in about 1.2 seconds at the warm median. That is a useful place to start for an interactive GIS workflow :-) Consider this question fr...

FELN RAG: Five Examples and a Spatial Query

Image
Ask a GIS person to find oil wells within five kilometers of gas pipelines and they can start breaking the request into pieces. Which layer contains the wells? How is “oil” encoded? Which pipelines carry gas? What spatial operation connects the two? A language model needs those same details. “Oil” might be a numeric subtype. A country might be stored as a two-letter code. And choosing intersects when the question calls for contains can produce perfectly respectable JSON that asks the wrong question. That is the problem behind feln-rag : give the model a description of the data and a handful of relevant worked examples, then ask it to translate a new request into a structured spatial query. The interesting part is how little machinery the retrieval needs. Start with the query we want to produce The output is FELN, a JSON representation with three main pieces: layers : the primary layer to return, followed by any spatial filter layers. where : one SQL filter per layer, in the s...

FELN: Find Existing Location with N Layers

In the layers-json post, I argued that the model needs to know what our data means before it can write a useful query. A field called STATUS with a value of 3 is not self-explanatory, and the aliases, domains, and subtypes already sitting in an ArcGIS Pro project are the cheapest explanation we will ever get. That post ended with a catalog, a Layers.json file, and a promise to do something with it. This is the something. FELN stands for Find Existing Location with N layers , and it is a small Python library and CLI that turns a plain-language request into a structured spatial query, compiles that query to DuckDB SQL, and, the part I actually care about, measures how close one query is to another. The shape of a question Most of the spatial questions people ask me over the years have the same skeleton. Find the things in one layer, optionally filtered, that stand in some spatial relationship to the things in another layer, also optionally filter...

Layers JSON: Giving LLMs the GIS Context They Need

When I started writing about GenAI and geospatial analysis , the attraction was being able to ask questions in plain language and let the tools do the spatial work. There is a very practical detail behind that interaction, though: the model needs to know what our data means. Take a field called STATUS with a value of 3 . Is that an active well? An abandoned one? A record waiting for review? A model can write perfectly valid SQL around that number and still give us the wrong answer. The database will happily execute it, too :-) That is the problem I want to address with layers-json : give applications access to the knowledge already captured in an ArcGIS Pro project and its supporting data sources. The map already carries a lot of the explanation If you have spent time giving fields useful aliases, defining domains, and organizing layers in Pro, you have already done some of the hard work. A field alias turns a storage name into something a person recognizes. A coded-value doma...

Nano Face: A Mac Camera, a Jetson, and One USB Cable

Image
Let me get the obvious out of the way first. Face detection on a Jetson is not new. NVIDIA ships samples for it, half the tutorials on the internet do it, and I am fairly sure somebody has done it on a Raspberry Pi wearing a HAT. So no, this is not a post about discovering face detection. This is a post about my two Jetsons, an Orin Nano Super and an AGX Orin, that live headless on a shelf with no monitor, no keyboard, and no camera plugged into either of them. I had just finished moving the Nano to JetPack 7.2.1 and pruning both boards down to a lean server install (no desktop, no Docker, nothing starting at boot), and I wanted a small, honest, end-to-end test that they were alive and doing real work. A face detector is a good smoke test. It either draws a box on your nose or it does not. The twist, and the part I actually cared about, is where the camera lives. It is the one in my MacBook Pro. The Jetson never sees a camera device. Frames leave the Mac...