<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><link href="https://richardcheam.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://richardcheam.github.io/" rel="alternate" type="text/html"/><updated>2026-11-11T00:00:00.000Z</updated><id>https://richardcheam.github.io/feed.xml</id><title type="html">RICHARD CHEAM</title><subtitle>My portfolio, technical blog, and paper review hub.</subtitle><author><name>Richard Cheam</name></author><entry><title>Data mixtures and repetition: deciding how often the model sees each source</title><link href="https://richardcheam.github.io/blog/model-development-data-mixtures/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-data-mixtures/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>A training corpus is not one dataset but several, and the sampling weights decide how many times the model sees each one. Turn weights into token exposure, see how temperature sampling and epoch caps protect small sources, and learn what is and is not known about repeating data.</summary></entry><entry><title>Tokenization: what a tokenizer decides before training starts</title><link href="https://richardcheam.github.io/blog/model-development-tokenization/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-tokenization/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>The tokenizer is trained before the model and fixed after it, and it quietly decides how much every sentence costs. Follow text through a real tokenizer, compare BPE with Unigram, measure what the same 1,012 sentences cost in English and Khmer under three tokenizers, and see what goes wrong when tokenizers and text disagree.</summary></entry><entry><title>The decoder architecture: the choices that matter and what they cost</title><link href="https://richardcheam.github.io/blog/model-development-decoder-architecture/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-decoder-architecture/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>A modern language model is still a stack of Transformer blocks, but a handful of choices decide how stably it trains, how much it costs to run and how long a context it handles. Count where Llama 3 8B's parameters go, see why grouped-query attention shrinks the KV cache fourfold, and learn what mixture-of-experts changes.</summary></entry><entry><title>A complete small training run: from raw text to a checkpoint you can trust</title><link href="https://richardcheam.github.io/blog/model-development-small-training-run/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-small-training-run/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Train a one-million-parameter language model on a laptop CPU, end to end: tokenizer, data splits, model, AdamW with warmup and cosine decay, gradient clipping, validation, checkpoints that resume exactly, and a precision check. Then break it on purpose and read the curves.</summary></entry><entry><title>Scaling laws: spending a compute budget on parameters and tokens</title><link href="https://richardcheam.github.io/blog/model-development-scaling-laws/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-scaling-laws/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Before a large run starts, someone has to decide how big the model should be and how many tokens it should see. Learn where the 6ND estimate of training compute comes from, what Chinchilla's experiments say about splitting a budget, why the answer changes once the model has to be served, and what small experiments can and cannot predict.</summary></entry><entry><title>GPU memory and compute: what training stores, computes and waits for</title><link href="https://richardcheam.github.io/blog/model-development-gpu-memory-compute/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-gpu-memory-compute/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Before splitting training across many GPUs, it helps to know exactly what one GPU holds and why it is slow. Count the bytes of weights, gradients, optimizer state and activations, estimate training time from FLOPs and utilization, and use arithmetic intensity to tell compute-bound work from memory-bound work.</summary></entry><entry><title>Data parallelism: one update computed on many GPUs</title><link href="https://richardcheam.github.io/blog/model-development-data-parallelism/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-data-parallelism/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>The simplest way to use many GPUs is to give each a copy of the model and a different slice of the batch, then average the gradients. Learn what has to stay identical for that to compute the same update as one big GPU, why averaging per-GPU losses quietly changes the objective, and what the gradient all-reduce costs.</summary></entry><entry><title>Sharding and recomputation: making a model fit</title><link href="https://richardcheam.github.io/blog/model-development-sharding-recomputation/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-sharding-recomputation/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Data parallelism gives every GPU a full copy of the training state, which stops working once that state outgrows a GPU. Learn how ZeRO and FSDP shard weights, gradients and optimizer state across data-parallel GPUs, what each stage saves and costs in communication, and how activation recomputation trades compute for memory.</summary></entry><entry><title>Model parallelism: splitting layers, sequences and experts across GPUs</title><link href="https://richardcheam.github.io/blog/model-development-model-parallelism/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-model-parallelism/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>When one layer's matrices, one sequence's activations or one model's experts no longer fit or run fast enough on a GPU, the model itself is split. Learn how tensor parallelism splits a matrix multiplication exactly, why pipelines have bubbles and how microbatches shrink them, and what sequence, context and expert parallelism add.</summary></entry><entry><title>Efficient execution: IO-aware attention, mixed precision and FP8</title><link href="https://richardcheam.github.io/blog/model-development-efficient-execution/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-efficient-execution/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Two ideas make modern training fast without changing what it computes: move less data, and use fewer bits. See how FlashAttention computes exact attention without ever storing the full score matrix, why BF16 replaced FP16, what loss scaling was for, and what FP8 training needs to work.</summary></entry><entry><title>Running at scale: throughput, failures and choosing a layout</title><link href="https://richardcheam.github.io/blog/model-development-running-at-scale/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-running-at-scale/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>A large run is a machine that fails. Learn to measure whether it is running well (MFU), find where time goes with a profiler, plan checkpoints around how often thousands of GPUs break, and choose a parallel layout by working through memory first and communication second, with Llama 3's real configuration as the example.</summary></entry><entry><title>Supervised fine-tuning: teaching a base model to answer</title><link href="https://richardcheam.github.io/blog/model-development-supervised-fine-tuning/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-supervised-fine-tuning/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>A pre-trained model continues text; it does not answer. Supervised fine-tuning teaches it to, with the same next-token loss on example conversations. See what a chat template really is, which tokens the loss is computed on and why, how averaging choices reweight examples, and what the open Tülu 3 recipe found about data.</summary></entry><entry><title>Post-training data: curated prompts, synthetic examples, rejection sampling and distillation</title><link href="https://richardcheam.github.io/blog/model-development-post-training-data/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-post-training-data/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Most post-training data is now generated, filtered or chosen by models. Learn where prompts come from, how synthetic data is kept diverse, why best-of-K rejection sampling quietly favours easy prompts, how distillation transfers a strong model's behaviour, and how decontamination works in an open recipe.</summary></entry><entry><title>Learning from preferences: reward models and DPO</title><link href="https://richardcheam.github.io/blog/model-development-preference-optimization/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-preference-optimization/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>People find it easier to say which of two answers is better than to write the perfect one. Learn how pairwise preferences become a training signal: the Bradley–Terry model behind reward models, the KL-regularized objective that keeps a policy close to where it started, and how DPO optimizes that objective without a separate reward model.</summary></entry><entry><title>Reinforcement learning for language models: policy gradients, PPO, GRPO and verifiable rewards</title><link href="https://richardcheam.github.io/blog/model-development-reinforcement-learning/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-reinforcement-learning/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Supervised fine-tuning and DPO learn from fixed examples. Reinforcement learning lets a model learn from its own attempts, scored by a reward. Derive the policy gradient on a four-answer toy, see why baselines matter, learn what PPO's clipping and value model do and what GRPO replaces them with, and why verifiable rewards changed reasoning training.</summary></entry><entry><title>When post-training goes wrong: reward hacking, length, shift and how to evaluate</title><link href="https://richardcheam.github.io/blog/model-development-post-training-failures/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-post-training-failures/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Every post-training method optimizes a proxy: a reward model, a verifier, a benchmark. Learn how optimizing a proxy too hard makes the real thing worse, why longer answers win judgements they should not, how a recipe can overfit its own development benchmarks, and how to evaluate post-training so these failures show up before users find them.</summary></entry><entry><title>Choosing a model: start from the task and build a baseline worth beating</title><link href="https://richardcheam.github.io/blog/model-development-choosing-a-model/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-choosing-a-model/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Before prompting, retrieval or fine-tuning, an application needs two things: a way to measure success on its own task, and a baseline. Learn which constraints narrow the choice of model, why leaderboards are a starting point rather than an answer, and how error costs can make the expensive model the cheap one.</summary></entry><entry><title>Prompting, context and structured outputs: controlling what a model does</title><link href="https://richardcheam.github.io/blog/model-development-prompting-context/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-prompting-context/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>A prompt is the cheapest way to change a model's behaviour, and the easiest to get subtly wrong. Learn what instructions, examples and reasoning steps actually do, how to budget and order a context window, why sampling several answers and voting helps, and how constrained decoding guarantees valid structured output.</summary></entry><entry><title>Retrieval, tools and agents: giving a model information and actions</title><link href="https://richardcheam.github.io/blog/model-development-retrieval-tools/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-retrieval-tools/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>A model only knows what it was trained on and can only produce text. Retrieval brings in information it never saw; tool calls let its text trigger actions. Build a tiny retriever and watch it fail on synonyms, see how a tool call works, and work out why multi-step agents fail more often than their individual steps.</summary></entry><entry><title>Prompt, retrieve or fine-tune: choosing how to adapt a model, and how LoRA works</title><link href="https://richardcheam.github.io/blog/model-development-adapt-or-prompt/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-adapt-or-prompt/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Prompting, retrieval and fine-tuning solve different problems: missing instructions, missing knowledge and missing behaviour. Learn to tell which one a task needs, then see how LoRA fine-tunes a large model by training a tiny low-rank update, why it starts from no change at all, and why it costs nothing extra at inference.</summary></entry><entry><title>Inference and serving: latency, throughput, KV cache and quantization</title><link href="https://richardcheam.github.io/blog/model-development-inference-serving/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-inference-serving/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Serving a model is a different problem from training it: generation is sequential and limited by memory bandwidth, not arithmetic. Work out why one sequence cannot exceed about 200 tokens per second on an H100, how batching trades latency for throughput, why the KV cache sets how many users fit, and what quantization, paged memory and speculative decoding change.</summary></entry><entry><title>Evaluating an application: test sets, judges, error bars, feedback and security</title><link href="https://richardcheam.github.io/blog/model-development-evaluating-applications/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-evaluating-applications/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>An application built on a model is never finished: prompts change, models are swapped, users ask new things. Learn to build an evaluation that tracks what matters, use a model as a judge without inheriting its biases, tell a real improvement from noise, learn from production, and recognize the privacy and security risks that arrive with retrieval and tools.</summary></entry><entry><title>How it fits together: tracing one requirement through data, training and serving</title><link href="https://richardcheam.github.io/blog/model-development-how-it-fits/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-how-it-fits/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Each post in this series took one decision at a time. Real systems are constrained end to end: a requirement at the application layer reaches back into the tokenizer, the data mix, the architecture and the training budget. Trace two requirements through the whole stack, and read Llama 3's design as a set of interlocking choices.</summary></entry><entry><title>Beyond text: what transfers to vision, speech and multimodal models</title><link href="https://richardcheam.github.io/blog/model-development-other-modalities/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-other-modalities/</id><published>2026-11-11T00:00:00.000Z</published><updated>2026-11-11T00:00:00.000Z</updated><summary>Almost everything in this series was taught with language models. Much of it transfers directly to images, speech and multimodal systems; some of it does not. Learn which principles carry over, how images and sound become tokens, where objectives and architectures differ, and why a minute of audio can cost thirty times more tokens than its transcript.</summary></entry><entry><title>Building a pre-training corpus: from a web crawl to training text</title><link href="https://richardcheam.github.io/blog/model-development-pretraining-corpus/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-pretraining-corpus/</id><published>2026-11-10T00:00:00.000Z</published><updated>2026-11-10T00:00:00.000Z</updated><summary>Most of the web is not text you want a model to learn from. Follow a crawl through the stages that turn it into a training corpus (extraction, language identification, quality filters, deduplication, contamination checks and personal-data removal) and learn to judge each one the way that matters: under a fixed training budget, did it improve the model, and what did it cost in coverage and data?</summary></entry><entry><title>One training update: from tokens to an AdamW step</title><link href="https://richardcheam.github.io/blog/model-development-one-update/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/model-development-one-update/</id><published>2026-11-09T00:00:00.000Z</published><updated>2026-11-09T00:00:00.000Z</updated><summary>Everything in pre-training, and everything a distributed system must preserve, starts from one update. Follow it from a batch of token IDs to a changed weight: shifted targets, attention masks, packing, how the loss is averaged, the backward pass, gradient clipping and one AdamW step, each on numbers small enough to check in your head.</summary></entry><entry><title>Neurons, layers and backpropagation</title><link href="https://richardcheam.github.io/blog/foundations-neurons-backprop/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-neurons-backprop/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A neural network is a pile of tiny calculators that multiply, add and bend. This post builds one with two inputs, two hidden neurons and one output, runs it forward, blames each weight for the error, and nudges every weight once, with every number small enough to check by hand.</summary></entry><entry><title>Loss functions and gradient descent</title><link href="https://richardcheam.github.io/blog/foundations-loss-gradient-descent/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-loss-gradient-descent/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>Training needs two things: one number that says how wrong the network is, and a rule for nudging every weight to make that number smaller. This post builds both, with every step small enough to check by hand.</summary></entry><entry><title>Optimisers: SGD, momentum, Adam and learning-rate schedules</title><link href="https://richardcheam.github.io/blog/foundations-optimisers/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-optimisers/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>Plain gradient descent zigzags in narrow valleys, crawls on flat ground and uses one step size for every weight. This post fixes each problem in turn, momentum, per-weight step sizes, Adam and schedules, on the same small bowl from the last post, with every step worked by hand.</summary></entry><entry><title>Overfitting and regularisation: dropout, weight decay and early stopping</title><link href="https://richardcheam.github.io/blog/foundations-regularisation/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-regularisation/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A network can learn its training data perfectly and still be useless on anything new. This post shows that failure on eight noisy points, then works through the standard cures, weight decay, early stopping and dropout, with every number small enough to check by hand.</summary></entry><entry><title>Normalisation: batch norm, layer norm and RMSNorm</title><link href="https://richardcheam.github.io/blog/foundations-normalisation/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-normalisation/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>Numbers on wildly different scales make training slow and fragile. Normalisation rescales them to a common size, inside the network as well as at the input. This post works batch norm, layer norm and RMSNorm by hand on the same four-by-three table.</summary></entry><entry><title>Embeddings: turning words and sounds into vectors</title><link href="https://richardcheam.github.io/blog/foundations-embeddings/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-embeddings/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A network only understands numbers, but language and codec audio arrive as symbols. An embedding gives every symbol a learned list of numbers, so that similar symbols end up close together. This post builds one by hand, trains one, and follows it into speech models.</summary></entry><entry><title>Convolutions: sliding filters over images and audio</title><link href="https://richardcheam.github.io/blog/foundations-convolutions/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-convolutions/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A fully connected layer gives every pixel and every audio sample its own private weights, which is hopelessly wasteful. A convolution slides one small filter along the input instead. This post computes every output by hand: in one dimension, in two, across channels, with padding, stride and dilation, and backwards through the gradient.</summary></entry><entry><title>Recurrent networks and vanishing gradients</title><link href="https://richardcheam.github.io/blog/foundations-recurrent-networks/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-recurrent-networks/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>Sentences, waveforms and speech frames arrive in order, and their length changes. A recurrent network reads them one step at a time and carries a small memory forward. This post runs one by hand, then follows the gradient backwards through time and watches it shrink to nothing or blow up.</summary></entry><entry><title>LSTM and GRU: gates that decide what to keep</title><link href="https://richardcheam.github.io/blog/foundations-lstm-gru/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-lstm-gru/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A plain recurrent network forgets its first input because the gradient is multiplied by a small number at every step. The LSTM adds a second memory lane that is updated by adding, with small dimmer switches called gates deciding what to keep, what to write and what to show. This post runs one by hand, then a GRU, and trains both kinds on the remember-the-first-input task.</summary></entry><entry><title>Attention: looking back at everything at once</title><link href="https://richardcheam.github.io/blog/foundations-attention/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-attention/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A recurrent network has to squeeze a whole sentence into one small state. Attention lets every position look back at every other position directly, choosing how much to take from each. This post builds it from a soft library lookup up to multi-head, masked, scaled dot-product attention, with every number worked by hand.</summary></entry><entry><title>The Transformer: attention, residuals and positions</title><link href="https://richardcheam.github.io/blog/foundations-transformer/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-transformer/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>Attention on its own is one clever layer. The Transformer stacks it with a small feed-forward network, wraps each in a residual connection and a normalisation, and adds a sense of position. This post builds every part from scratch and runs a whole block on three tokens by hand.</summary></entry><entry><title>Autoencoders and VAEs</title><link href="https://richardcheam.github.io/blog/foundations-autoencoders-vae/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-autoencoders-vae/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>An autoencoder squeezes data through a narrow code and rebuilds it. A variational autoencoder makes that code a little cloud instead of a point, so the space of codes has no holes and you can pick a random point and decode something real. Every step worked on tiny numbers.</summary></entry><entry><title>GANs: a generator and a judge training each other</title><link href="https://richardcheam.github.io/blog/foundations-gans/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-gans/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A generative adversarial network trains two networks against each other: a forger that turns random noise into samples and a detective that scores how real they look. Every loss worked by hand, a one-number GAN trained live, and the ways the game goes wrong.</summary></entry><entry><title>Diffusion and flow models: generating from noise</title><link href="https://richardcheam.github.io/blog/foundations-diffusion-flow/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-diffusion-flow/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>Blur data into noise on purpose, then train a network to undo one small blur at a time. Diffusion models and flow models both generate by walking from noise back to data. Every step worked by hand on a toy whose data is just two points, +1 and −1.</summary></entry><entry><title>Language models and tokenizers: predicting the next token</title><link href="https://richardcheam.github.io/blog/foundations-language-models/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/foundations-language-models/</id><published>2026-10-15T00:00:00.000Z</published><updated>2026-10-15T00:00:00.000Z</updated><summary>A language model does one small thing: it gives a probability to every possible next token. Chain those guesses together and you can score a sentence, train on raw text, and write new text one piece at a time. Counting, tokenizing, training and sampling, each worked on tiny numbers, and how the same machine speaks.</summary></entry><entry><title>What a computer hears: samples, frames and mel spectrograms</title><link href="https://richardcheam.github.io/blog/audio-basics/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/audio-basics/</id><published>2026-10-14T00:00:00.000Z</published><updated>2026-10-14T00:00:00.000Z</updated><summary>A microphone turns air into a long list of numbers. This post follows those numbers from a single sample to the mel spectrogram that speech models read, with every number small enough to check by hand.</summary></entry><entry><title>Residual vector quantization: turning sound into a few small numbers</title><link href="https://richardcheam.github.io/blog/residual-vector-quantization/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/residual-vector-quantization/</id><published>2026-10-14T00:00:00.000Z</published><updated>2026-10-14T00:00:00.000Z</updated><summary>Neural audio codecs turn every slice of sound into a handful of whole numbers. This post builds the trick behind that, residual vector quantization, from a box of paint colours up to EnCodec, DAC and Mimi, with every example small enough to check by hand.</summary></entry><entry><title>How Khmer writing looks to a text-to-speech model</title><link href="https://richardcheam.github.io/blog/khmer-script-for-tts/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/khmer-script-for-tts/</id><published>2026-10-14T00:00:00.000Z</published><updated>2026-10-14T00:00:00.000Z</updated><summary>Khmer letters stack, vowels sit on every side of a consonant, and words have no spaces. This post follows one syllable from the screen to code points, bytes and tokens, and shows what each step means for a text-to-speech model.</summary></entry><entry><title>Same model, new language: fine-tuning Pocket TTS to speak Khmer</title><link href="https://richardcheam.github.io/blog/khmer-tts-fine-tuning/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/khmer-tts-fine-tuning/</id><published>2026-10-13T00:00:00.000Z</published><updated>2026-10-13T00:00:00.000Z</updated><summary>How an English text-to-speech model learned to read Khmer: the data, the cleaning, the cut into prompt and target, the new tokenizer, what was trained and what stayed frozen, and why the best checkpoint was not the one with the lowest loss.</summary></entry><entry><title>Walkie-talkie or conversation: cascaded vs full-duplex speech</title><link href="https://richardcheam.github.io/blog/cascade-vs-full-duplex/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/cascade-vs-full-duplex/</id><published>2026-10-12T00:00:00.000Z</published><updated>2026-10-12T00:00:00.000Z</updated><summary>A cascaded voice assistant passes the turn between three models and waits at every handoff. A full-duplex model listens and speaks at once, 80 ms at a time. Where the latency goes, what the transcript throws away, and how interruptions actually work.</summary></entry><entry><title>How do we know a TTS is good? Speech evaluation, metric by metric</title><link href="https://richardcheam.github.io/blog/speech-evaluation-metrics/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/speech-evaluation-metrics/</id><published>2026-10-12T00:00:00.000Z</published><updated>2026-10-12T00:00:00.000Z</updated><summary>WER, CER, speaker similarity, MCD, F0 RMSE, Fréchet distances, TTSDS, MOS, CMOS, MUSHRA and learned MOS predictors: what each one measures, the math, and where it stops agreeing with people.</summary></entry><entry><title>Speech without tokens: how Pocket TTS works</title><link href="https://richardcheam.github.io/blog/pocket-tts-calm-explained/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/pocket-tts-calm-explained/</id><published>2026-10-11T00:00:00.000Z</published><updated>2026-10-11T00:00:00.000Z</updated><summary>Kyutai's Pocket TTS generates speech as continuous vectors, not codec tokens, and turns noise into each audio frame in a single network call. The full path from text to waveform, with the shapes and the math.</summary></entry><entry><title>Mimi: 24,000 samples in, 400 numbers out</title><link href="https://richardcheam.github.io/blog/mimi-codec-explained/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/mimi-codec-explained/</id><published>2026-10-11T00:00:00.000Z</published><updated>2026-10-11T00:00:00.000Z</updated><summary>The codec under Pocket TTS turns each second of speech into 12.5 frames of 32 numbers and back. Every layer, stride and tensor shape on the way down and up, and why the latent is continuous.</summary></entry><entry><title>Zero loss, empty representation</title><link href="https://richardcheam.github.io/blog/representation-collapse-explained/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/representation-collapse-explained/</id><published>2026-10-07T00:00:00.000Z</published><updated>2026-10-07T00:00:00.000Z</updated><summary>Joint-embedding training has a shortcut that always works: produce the same vector for everything. The geometry of that failure, and the linear algebra needed to read it.</summary></entry><entry><title>When Linux file cache occupies GPU memory</title><link href="https://richardcheam.github.io/blog/grace-hopper-file-cache/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/grace-hopper-file-cache/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>I traced a failed GH200 model startup to checkpoint file pages occupying HBM and measured the KV capacity recovered after targeted cache advice.</summary></entry><entry><title>Benchmark numbers that misled me and how I corrected them</title><link href="https://richardcheam.github.io/blog/benchmark-denominators/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/benchmark-denominators/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>I reconciled token counts, prompt lengths, cache reuse, and unfinished requests before comparing GH200 serving runs.</summary></entry><entry><title>NUMA locality: configuration versus proof</title><link href="https://richardcheam.github.io/blog/gh200-locality-evidence/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/gh200-locality-evidence/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>I mapped the two Grace Hopper locality domains, checked worker placement, and tested NUMA restrictions while leaving KV-buffer locality for direct measurement.</summary></entry><entry><title>Making KV offload correct</title><link href="https://richardcheam.github.io/blog/kv-offload-correctness/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/kv-offload-correctness/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>I adapted a CPU-KV path, checked reload output and actual movement, and investigated allocator rollback and transfer drain under pressure.</summary></entry><entry><title>Why model startup needs a fitting backend and complete artifacts</title><link href="https://richardcheam.github.io/blog/startup-artifacts-runtime-contract/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/startup-artifacts-runtime-contract/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>I compared weight-backend footprints and fixed a rank-incomplete autotune cache so a historical serving profile could start with validated artifacts.</summary></entry><entry><title>High throughput, minutes of waiting</title><link href="https://richardcheam.github.io/blog/throughput-versus-usable-latency/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/throughput-versus-usable-latency/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>A long-context soak kept producing output while first-token latency made interactive use difficult.</summary></entry><entry><title>When the container stays alive but inference stops</title><link href="https://richardcheam.github.io/blog/inference-workload-lifecycle/" rel="alternate" type="text/html"/><id>https://richardcheam.github.io/blog/inference-workload-lifecycle/</id><published>2026-10-03T00:00:00.000Z</published><updated>2026-10-03T00:00:00.000Z</updated><summary>I investigated why workers stopped while their container stayed alive, then separated process ownership, model readiness, and workload admission.</summary></entry></feed>