Blog
RSSThoughts on AI engineering, Python, career growth, and technical leadership — organized using the Diataxis framework.
- tutorial
- learn by doing, step by step
- how-to
- solve one specific problem
- explanation
- understand why something works
- reference
- look up the details
8 min read
I gave urgent receipts priority. The bulk import paid for it.
Giving urgent receipts priority and reserved slots recovered most five-second deadlines. The bulk import completed less work and took longer to drain.
6 min read
I sent my 4090 six receipts a second. The queue kept growing.
Five incoming receipts a second kept the queue short. Six filled it during a five-minute run. The lower rate still timed out on one troublesome receipt.
9 min read
I ran Nemotron Parse on a 4090. Then I checked the numbers.
All 48 measured requests completed on my RTX 4090. One receipt's 79,500 came back as 79,300. A small CORD experiment shows what completion, text overlap and numeric recall each leave out.
6 min read
Gemma 4 read a love note as a scam. A rewritten question brought it within two messages of Jev.
I asked Jev and Gemma 4 31B the same scam question about 158 public text messages. Jev got 151 right. Gemma, on my own card, got 131, because it flagged love notes and everyday chat as fraud. Then I let an optimizer rewrite the question once for each model. Gemma climbed to 153, and on calibration its percentages ended closer to reality than Jev's.
8 min read
My Gemma was 99.96 percent sure the total matched. It had not seen the receipt.
typevet is a small Python library, public today, that asks an open model typed questions and reads the answer as a probability. I asked Gemma 4 31B, on my own 24 GiB card, whether an expense claim matched a real receipt. Without the photo it said yes to every claim that showed a full number, almost certain every time. With the photo it caught all six wrong totals.
11 min read
Jev looked underconfident on Banking77. Two of my labels were the reason.
I asked TypeSafe's Jev one yes-or-no question about a thousand public messages and checked whether its percentages matched what actually happened. On scam text messages they did. On bank support messages they looked far too cautious, until I read the messages themselves. The problem was two of my labels, not Jev.
14 min read
The scan lost one letter, and a derivative was crowned the mother sauce
The 1907 scan reads entry 22 as BROWN SAUCE OR ESPAQNOLE, so no name in that witness held the word Espagnole except a derivative's, and saucier crowned LENTEN ESPAGNOLE as a mother with twelve preparations beneath it. The ticket blamed ranking. Measuring that fix is what found the real defect: the lookup checked that a base comes before its derivatives without ever checking that the base was there.
11 min read
Serve Gemma 4 31B on a 24 GiB card with the context it was packed for
Download the published fit24gib pack, install llama.cpp at the build the numbers were measured on, and serve it at 86,016 tokens of text context or 73,728 with an image aboard. Every flag comes from the model card or the vramfit repo's own serve how-to, and the section at the end says what to do when your card does not reach the boundary.
12 min read
The parent finally has a verb. The book still will not say how many minutes.
At v0.5.0 the saucier record for Mornay said it derives from Béchamel and stopped there, two lines above the sentence that says how. v0.6.0 records that sentence for one preparation, by hand, as six operations in the book's own words, with every number the text gives and every one it withholds left empty. The check that refuses a misquote also turned up the first confirmed difference between the 1907 and 1909 printings.
10 min read
I cut the last sauce off the file. Every line still parsed.
saucier now writes both copies of Escoffier as one stream, one record per line, so a shell can read the catalogue without importing my package. The first reader I wrote for it accepted an empty file, then a file missing its last sauce, with every remaining line valid JSON. Then a jq one-liner over the stream found a Périgueux the scan resolved and the text refused.
16 min read
The book spells it out at line 1437. Two of my posts said it never did.
Two earlier posts said Escoffier never spells out that half glaze is a reduction of Espagnole. Entry 23 does, in its first sentence. This is the clause of my own that hid it, the 27 entries that enter when it goes, and the ten derivations the release gives back on purpose.
13 min read
Google's 4-bit Gemma already fit my 24 GiB card. I wanted the 20,000 tokens it left on the table.
The official Q4_0 build of Gemma 4 31B is 16.44 GiB and fits a 24 GiB card with room to spare, so "it fits" was never the claim. The budget is. I measured the decoder layer by layer, solved a 14.92 GiB pack that ties Google's build on four held-out benchmarks and wins one, and let the freed bytes buy context — 86,016 served tokens against 65,536, and 73,728 against 49,152 with an image aboard.
14 min read
I added a second copy of the same book. It told me nothing about the book.
Post three of the saucier series puts a second witness of Escoffier into the corpus — the 1907 first printing, as a scan — and gets back no facts about cookery and four classes of fact about its own instruments. The number of sauces the revision supposedly added went twenty, then eight, then none. Along the way the project discovered it had been citing the wrong edition since its first commit.
13 min read
The 2-bit label was 4.5 bits inside. My 16 GiB card could tell.
The smallest 2-bit-labeled build of Nemotron 3.5 Lightning is 17.54 GiB — it doesn't fit a 16 GiB card, and its label names 12 of 417 tensors. I measured the model stack by stack instead, and got a 15.76 GiB pack that serves fully on-card at 16k context and beats the shelf's build on both damage metrics, while 1.78 GiB smaller.
13 min read
Marrow Sauce finally has a parent. The parser gave up three answers to earn it.
Post two of the saucier series lets a parent be any catalogued preparation, not only one of the five mothers. Derived rises from 29 to 50 and every new derivation quotes a name the source wrote. The same rule dissolves three derivations the old parser recorded, one of them caught by peer review — and Bordelaise stays unresolved on purpose, because a term that encodes a derivation is not a statement of one.
13 min read
There is no model in this parser. It still told me ice cream was a sauce.
Post one of the saucier series reads a century-old cookbook with a regular expression — 124 sauces, 29 lineages, 95 that name no base. The first version of that census said 166 and 64, and forty of those were soups, jam, and a vanilla ice cream. Determinism did not catch that. Line numbers did.
11 min read
Fit a model to the GPU you actually have
Measure a model's per-layer quantization damage, solve for a recipe that fits your card, and check the result before you trust it.
8 min read
A different ceiling is a different recipe. I finally checked.
I claimed a smaller card gives you a different quantization recipe, not the same one squeezed, and then didn't prove it. Here's that claim run against the published price list — including the ceiling where the honest answer is that there's no dish.
12 min read
I couldn't tell my quantized model from the baseline. The instruments could.
I shrank a 93 GB model onto a 24 GB card by measuring which layers survive being crushed, instead of guessing. Then I couldn't tell the result from the standard quant by talking to it — which turns out to be the whole point.
14 min read
"Two patterns that make production database changes boring"
"Two patterns that make production database changes safe, auditable, and boring. How SCD Type 2 and maker-checker work — and why config data belongs in a database, not your git repo."
5 min read
"From one model to seven: Making TurboQuant model-portable"
"turboquant-vllm started as a Molmo2-only proof of concept. v1.3.0 validates seven model families — but getting there meant rewriting Triton kernels for non-standard head dimensions and teaching the cache about sliding window attention."
4 min read
Serve compressed VLM inference from a container
"Build a container image with turboquant-vllm baked in, serve a vision-language model with 3.76x KV cache compression, and verify it works — in under five minutes."
5 min read
"Paper to PyPI in 72 hours: Building the first TurboQuant vLLM plugin"
"Google published TurboQuant at ICLR 2026 for text models. 72 hours later, turboquant-vllm was on PyPI — the first implementation validated on vision-language models and the first vLLM plugin. One flag to enable, 3.76x KV cache compression."
6 min read
I ran TurboQuant on a vision model. The first output was garbage.
I implemented Google's TurboQuant algorithm for KV cache compression and validated it on Molmo2 video inference on an RTX 4090 — 3.76x compression with near-identical output at 1.78x overhead.
6 min read
I asked an AI to explain boto3. Then I fixed the docstrings.
I cloned the most downloaded Python package twice, fixed the docstrings with docvet, and asked AI to generate architecture documentation from both. The results weren't even close.
6 min read
When docstrings lie, your AI tools pay the price
Wrong documentation hurts AI tools more than missing documentation. docvet 1.14 introduces bidirectional verification — checking both what your docstrings fail to mention and what they wrongly claim.
5 min read
Encrypt ADK Sessions in 5 Minutes
Install adk-secure-sessions, swap one import, and verify your agent's session data is encrypted at rest — start to finish in under 5 minutes.
8 min read
Stop Writing AI Agent Prompts by Hand
You write your agent's instructions, test them, tweak a word, test again, and hope the change helped. There's an algorithm that does this better than you do — evolutionary optimization finds prompts you'd never write yourself.
4 min read
Give Your AI Agent a Docstring Quality Tool
Wire docvet's MCP server into VS Code, Cursor, or Claude Code — your AI coding agent gets structured docstring quality checks without parsing CLI output.
7 min read
Your AI Agent's Memories Aren't Encrypted
Google ADK stores everything your agent knows — tool calls, user messages, conversation context — in plaintext SQLite. Here's why that matters and how to fix it.
6 min read
Your AI Reads Your Docstrings. Are They Right?
Stale docstrings poison your AI coding agent's understanding of your codebase. Research shows incorrect documentation is worse than no documentation at all.
7 min read
Entity Resolution is Recipe Matching
When exact matching fails, probabilistic record linkage weighs evidence like a chef recognizes a dish—not by a single ingredient, but by the whole picture.
8 min read
Lineage IDs in Multimodal AI Pipelines
The simplest way to keep images, videos, model calls, and outputs tied together across retries and fan-out.
6 min read
Task Queues, Idempotency, and AI Pipelines
Why at-least-once delivery means your AI pipeline will process duplicates, and why idempotency is the only reliable fix.
4 min read
Why I Chose Reflex for My Portfolio Site
A Python engineer's case for building a portfolio site without touching JavaScript.