<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Building Mila on Mila</title><link>https://mila.toddt.me/blog/</link><description>Recent content in Building Mila on Mila</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 18 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mila.toddt.me/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>Running Gemma 4 12B in Docker Behind an OpenAI-Compatible API</title><link>https://mila.toddt.me/blog/gemma-4-docker-openai-api/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/gemma-4-docker-openai-api/</guid><description>&lt;p&gt;This week Mila added a feature I think is really cool! Mila now &lt;strong&gt;builds and runs the same way&lt;/strong&gt; on three surfaces — Windows/MSVC (where I develop), Clang on WSL/Linux, and a single Docker container — and from that container you can &lt;strong&gt;drive Mila as the &amp;ldquo;brain&amp;rdquo; behind any OpenAI- or Anthropic-compatible harness&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="one-container-one-command-a-gemma-4-12b-model-as-a-brain"&gt;One container, one command, a Gemma 4 12B model as a brain&lt;/h2&gt;
&lt;p&gt;The dev container is a completely known build environment — clone, one step, a running Mila. Beyond the interactive Chat CLI, it now stands up the &lt;strong&gt;Mila Inference Server (MIS)&lt;/strong&gt;: a small FastAPI wire adaptor that serves the runtime over an OpenAI / Anthropic / Mila-native HTTP API.&lt;/p&gt;</description></item><item><title>Flash-Decoding for MQA in CUDA: One KV Head, Split-K, and an FP4 Matvec at 90% of DRAM Peak</title><link>https://mila.toddt.me/blog/flash-decoding-mqa-cuda/</link><pubDate>Thu, 16 Jul 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/flash-decoding-mqa-cuda/</guid><description>&lt;p&gt;&lt;em&gt;Part 1 — &lt;a href="https://github.com/ToddThomson/Mila/discussions/16"&gt;Hand-Writing Gemma 4 FlashAttention + an FP8 GEMM Bonus&lt;/a&gt; —
took ten sessions to drag prefill from 1.95x behind llama.cpp to 1.14x. This part took &lt;strong&gt;one
session&lt;/strong&gt; to drag decode from 1.30x behind to &lt;strong&gt;1.03x&lt;/strong&gt;: Gemma 4 12B FP4 on the same RTX 4070,
38.65 → 49.09 tok/s at a 32K context, against llama.cpp&amp;rsquo;s measured 50.3–50.7.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It didn&amp;rsquo;t take one session because decode is easier. It took one session because Part 1 paid
the tuition — the parity-oracle ladder, the compute-sanitizer discipline, the online-softmax
kernel DNA, and above all the reflex of profiling before believing — and this campaign got to
spend the education.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Writing a FlashAttention Prefill Kernel for Gemma 4: Head Dim 512, Tensor Cores and an FP8 GEMM</title><link>https://mila.toddt.me/blog/flashattention-prefill-kernel/</link><pubDate>Wed, 15 Jul 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/flashattention-prefill-kernel/</guid><description>&lt;p&gt;Adding FlashAttention to Mila&amp;rsquo;s GQA started as a &lt;strong&gt;memory&lt;/strong&gt; project. It was the last big lever in optimizing memory utilization across the Gemma 4 pipeline — with weight tying, FP8 KV, and bounded sliding-window KV already in place, the attention path was the last thing still materializing large intermediates. A classical attention writes a &lt;code&gt;[chunk × attended_len]&lt;/code&gt; score matrix to global memory, and its workspace has to be sized to the &lt;em&gt;full&lt;/em&gt; context width; at 64K that&amp;rsquo;s ~1 GB per buffer of pure throwaway. FlashAttention&amp;rsquo;s online softmax removes it entirely, and that reclaim — &lt;strong&gt;~1-2 GB at long context&lt;/strong&gt; — is what took Gemma 4 12B from a VRAM cliff at 32K to &lt;strong&gt;running 64K on a 12 GB RTX 4070&lt;/strong&gt;. Speed was the second prize, and it&amp;rsquo;s the one that turned into a ten-session campaign.&lt;/p&gt;</description></item><item><title>Bringing Up Gemma 4 in C++: Sliding-Window Attention, Dual RoPE and Token-for-Token Parity</title><link>https://mila.toddt.me/blog/bringing-up-gemma-4/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/bringing-up-gemma-4/</guid><description>&lt;h2 id="where-we-left-off"&gt;Where We Left Off&lt;/h2&gt;
&lt;p&gt;Alpha.2 ended with Mila producing token-for-token matches against HuggingFace for Llama 3.2 1B, and the alphas pushed that to Llama 3.1 8B with FP8 and FP4 weight quantization. The framework had a working Grouped-Query Attention op, a two-phase prefill/decode KV cache, and a clean &lt;code&gt;OperationTraits&lt;/code&gt; dispatch path. The Llama family was, by then, a &lt;em&gt;homogeneous&lt;/em&gt; machine: every layer looked like every other layer.&lt;/p&gt;
&lt;p&gt;Gemma 4 broke that assumption on contact.&lt;/p&gt;</description></item><item><title>Closing a Local Agentic Loop: Mila Inference Server and Codex CLI</title><link>https://mila.toddt.me/blog/local-agentic-loop/</link><pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/local-agentic-loop/</guid><description>&lt;p&gt;&lt;strong&gt;Date:&lt;/strong&gt; 2026-05-15
&lt;strong&gt;Status:&lt;/strong&gt; Proven / Experimental
&lt;strong&gt;Component:&lt;/strong&gt; &lt;code&gt;Mila/Inference/Server&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;This document describes the design and implementation of a protocol translation layer that
enables &lt;a href="https://github.com/openai/codex"&gt;Codex CLI&lt;/a&gt; to drive an agentic coding loop against a locally-hosted Llama 3.2 3B Instruct model served by the Mila Inference Server (MIS).&lt;/p&gt;
&lt;p&gt;The result is a fully local, self-hosted agentic coding assistant: no OpenAI API key, no cloud dependency, no model modification required.&lt;/p&gt;
&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Codex CLI &amp;lt;--&amp;gt; MIS /v1/responses &amp;lt;--&amp;gt; Llama 3.2 3B Instruct
 (OpenAI (protocol bridge) (local GPU)
 Responses API)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Three parties interact; none required modification:&lt;/p&gt;</description></item><item><title>Driving a Local C++ Inference Server from Claude Code and Codex CLI</title><link>https://mila.toddt.me/blog/mis-with-claude-code-and-codex/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/mis-with-claude-code-and-codex/</guid><description>&lt;p&gt;&lt;em&gt;Mila Discussions — Inference Server Series&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;One of the goals of the Mila Inference Server (MIS) is to make a locally-running Llama model feel, from the outside, indistinguishable from a cloud API. If MIS does its job correctly, you should be able to point Claude Code or Codex CLI at &lt;code&gt;http://localhost:8000&lt;/code&gt; and have them work as if they were talking to Anthropic or OpenAI&amp;rsquo;s servers — except your data never leaves your machine and your GPU is doing the work.&lt;/p&gt;</description></item><item><title>The Eight-Headed Bug That Hid Behind a System Prompt</title><link>https://mila.toddt.me/blog/eight-headed-bug-system-prompt/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/eight-headed-bug-system-prompt/</guid><description>&lt;p&gt;When I added system prompt support to Mila&amp;rsquo;s chat CLI, something unexpected happened. Prompts that had previously produced perfect responses started generating fluent, coherent, and completely context-oblivious text. Ask for a story about rabbits living on the moon eating green carrots — get a charming tale about Hungarian meadow rabbits instead. The model wasn&amp;rsquo;t broken. It was just ignoring everything I said.&lt;/p&gt;
&lt;p&gt;This is the story of how a single innocent constant — &lt;code&gt;kPrefillChunkSize&lt;/code&gt; — quietly corrupted eight different stages of the GQA prefill pipeline, and why it took a system prompt to wake the beast.&lt;/p&gt;</description></item><item><title>From GPT-2 to Llama 3.2 in C++: RMSNorm, SwiGLU, Grouped Query Attention and RoPE</title><link>https://mila.toddt.me/blog/gpt2-to-llama-32/</link><pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/gpt2-to-llama-32/</guid><description>&lt;p&gt;&lt;em&gt;A show-and-tell of what it actually takes to build a modern transformer from scratch in C++23 and CUDA.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="where-we-left-off"&gt;Where We Left Off&lt;/h2&gt;
&lt;p&gt;Alpha.1 ended cleanly. GPT-2 inference validated token-for-token against HuggingFace using greedy decoding. The full stack — BPE tokenizer, embeddings, multi-head attention, MLP, KV cache, two-phase prefill/decode — all confirmed correct. The methodology was established: if Mila&amp;rsquo;s greedy output matches HuggingFace&amp;rsquo;s greedy output exactly, the implementation is correct.&lt;/p&gt;
&lt;p&gt;Alpha.2 began with a deceptively simple goal: do the same thing for Llama 3.2 1B.&lt;/p&gt;</description></item><item><title>The Lobotomized Attention Head Bug: One Head Does All the Work, the Others Stare Into the Void</title><link>https://mila.toddt.me/blog/lobotomized-attention-head-bug/</link><pubDate>Thu, 26 Feb 2026 00:00:00 +0000</pubDate><guid>https://mila.toddt.me/blog/lobotomized-attention-head-bug/</guid><description>&lt;p&gt;🧠 The Lobotomized Attention Head Bug — A Transformer Debugging Rite of Passage&lt;/p&gt;
&lt;p&gt;I just finished building the fast prefill → decode inference path in my Mila DNN library.
Everything seemed fine — the model produced coherent text, KV caching worked, and decode mode looked solid.&lt;/p&gt;
&lt;p&gt;But… my transformer’s residuals were way off compared to 🤗 HF GPT-2, and the hidden states just felt wrong.
Not exploding, not NaN’ing — just wrong.&lt;/p&gt;</description></item></channel></rss>