<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Maayan Roth's Blog</title>
    <link>https://www.maayanroth.com/blog/index.html</link>
    <description>Engineer, potter, e-bike enthusiast, mom of two.</description>
    <language>en-us</language>
    <lastBuildDate>Fri, 31 Jul 2026 20:24:53 +0000</lastBuildDate>
    <item>
      <title>In Which I Lose My Mind Over Embeddings (HPLM Chapter 2)</title>
      <link>https://www.maayanroth.com/blog/posts/hundred-page-lm-book-chapter-2.html</link>
      <guid>https://www.maayanroth.com/blog/posts/hundred-page-lm-book-chapter-2.html</guid>
      <pubDate>Fri, 31 Jul 2026 00:00:00 +0000</pubDate>
      <description><![CDATA[<p>
      Chapter 2 of
      <a href="https://thelmbook.com/" target="_blank" rel="noopener">The Hundred-Page Language Models Book</a>
      is when things started to get really exciting for me.
    </p>

    <h3>Chapter 2 &ndash; Language Modeling Basics</h3>
    <p>
      Chapter 2 introduces the fundamental building blocks of machine learning with natural language
      input and outputs: tokenization, embeddings, and model evaluation frameworks. Tokenization is the
      process of converting input words into &ldquo;tokens&rdquo; that are recognizable by language
      models, and embeddings convert those tokens into dense numerical representations. Together, they
      tackle the problem of efficiently representing arbitrarily large vocabularies in machine-readable
      formats.
    </p>
    <p>
      I had heard the word &ldquo;embeddings&rdquo;, of course, and I understood, at a high level, that
      embedding models are something important for LLMs, and are used to capture semantic similarity
      between words. More than that, I could not have told you. HPLM explains the concepts beautifully:
    </p>
    <p>
      Imagine that you have a language with a vocabulary of 10000 words. (Note that this is a very small
      language. The <a href="https://www.oed.com/" target="_blank" rel="noopener">Oxford English
      Dictionary</a> contains over 500,000 words, and modern LLMs model multiple languages
      simultaneously.) The most straightforward way to represent a word in this vocabulary is with a
      <strong><em>one-hot vector</em></strong>, an array of 10000 bits, with each index in the array
      corresponding to a word in the vocabulary.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img1.png"
      alt="Two hand-drawn one-hot vectors: one with a 1 at index 5 labeled &quot;Fish (Index 5)&quot; and another with a 1 at index N-2 labeled &quot;Carrot (Index N-2)&quot;, every other cell 0.">

    <p>
      One-hot vectors are easy to understand and perfectly machine-readable, but they have two major
      drawbacks: they are incredibly memory inefficient, wasting most of their space storing useless 0s,
      and they fail to encode any useful relationships between words. Indices are assigned to words
      arbitrarily, and words that are very similar (e.g. &ldquo;happy&rdquo; and &ldquo;glad&rdquo;) may
      end up far away from each other, whereas words with adjacent indices may have no meaningful
      semantic relationship.
    </p>

    <h3>Word2vec</h3>
    <p>
      The primary insight of embeddings is that it is possible to generate an alternative representation
      of tokens which is both more dense than one-hot encoding and represents semantic relationships
      between words. HPLM goes into detail on Word2vec, a family of algorithms used to generate word
      embeddings. Word2vec comes in several flavors, but they all share the same core conceptual idea.
      Imagine a snippet of text containing a target word (in this case &ldquo;cat&rdquo;) and several
      surrounding context words:
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img2.png"
      alt="A Word2vec training example: the target word &quot;cat&quot; flanked by the context words &quot;feed your&quot; and &quot;wet food&quot;.">

    <p>
      If you were to train a neural network such that, when given the target word as input, it produces
      the context words with high likelihood, then if you were to pass in a similar word, one that is
      likely to appear in similar contexts (e.g. &ldquo;kitten&rdquo;), you should expect the network to
      produce similar output. The structure of the network looks like this: two layers, an input layer
      that scales from the vocabulary size down to the embedding dimension size and an output layer that
      does the reverse. The output of the first layer is a vector of floats, also called the
      <strong><em>embedding vector</em></strong>, which can be used as a dense representation of the
      input word when training or using a language model.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img3.png"
      alt="A hand-drawn Word2vec network: the one-hot input vector for &quot;cat&quot; feeds an input layer that narrows to an embedding vector, then an output layer produces probabilities over the vocabulary for words like banana, wet, and food.">

    <h3>The part that blew my mind</h3>
    <p>
      So far so good. It makes intuitive sense that the vectors for &ldquo;cat&rdquo; and
      &ldquo;kitten&rdquo; should be similar i.e. close to each other in vector-space. But then, the
      author casually drops this bomb &ndash; these embedding vectors support simple mathematical
      operations. For example, if you take the embedding vector for &ldquo;king&rdquo;, subtract the
      vector for &ldquo;man&rdquo;, and add the vector for &ldquo;woman&rdquo;, you get a vector very
      similar to the one for &ldquo;queen&rdquo;.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img4.png"
      alt="Hand-lettered equation: &quot;king&quot; - &quot;man&quot; + &quot;woman&quot; = &quot;queen&quot;.">

    <p>What?</p>
    <p>How?</p>
    <p>That sounds completely made up.</p>

    <p>
      I had a little chat with Claude, trying to understand why this might be true. Claude made the
      argument to me that, within the vectors for &ldquo;king&rdquo; and &ldquo;queen&rdquo;, there is
      some subcomponent representing the concept of &ldquo;royalty&rdquo;. Honestly, that seems like
      nonsense to me.
    </p>
    <p>
      It gets a little clearer when I think of the operations as if they were happening in the space of
      training examples, or at least I can squint at it and pretend that it makes sense. Imagine all of
      the context examples for the word &ldquo;king&rdquo;. Some of them will include context about
      gender, many will not. When you subtract the vector for &ldquo;man&rdquo;, you&rsquo;re not
      removing only the examples that include both &ldquo;king&rdquo; and &ldquo;man&rdquo;. You are
      removing <em>all</em> of the context examples for the word &ldquo;man&rdquo;, as if the concept of
      &ldquo;man&rdquo; is being removed from your language entirely. That doesn&rsquo;t land you on some
      genderless concept of &ldquo;monarch&rdquo;; it moves you somewhere really weird.
    </p>
    <p>
      Now, add in all of the example texts for &ldquo;woman&rdquo;. Not only are we adding back in some
      examples for &ldquo;queen&rdquo;, we&rsquo;re also moving our whole language back from the strange
      universe in which &ldquo;man&rdquo; doesn&rsquo;t exist.
    </p>
    <p>
      Ok, no, maybe this doesn&rsquo;t actually help.
    </p>

    <h3>Visualizing embedding vectors</h3>
    <p>
      Obsessed with this idea, I decided to vibe-code an app that would let me play around with more of
      this word vector math. You can try it out here
      (<a href="https://www.maayanroth.com/word2vec_math/" target="_blank" rel="noopener">Word2Vec
      Arithmetic</a>,
      <a href="https://github.com/maayanroth/word2vec_math" target="_blank" rel="noopener">GitHub
      repo</a>). Over a smallish vocabulary of about 1600 words, you can add and subtract them together,
      and get a list of the closest resulting word vectors from a larger vocabulary of 30K words, along
      with a visualization of the operation in vector space. Distance is measured by cosine similarity
      between vectors.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img5.png"
      alt="Screenshot of the Word2Vec Arithmetic app showing the input chips king (added), man (subtracted), and woman (added).">

    <p>
      The quality of an embedding model should grow as the model is trained on a larger data set, and I
      wanted to see if I could visualize this improvement. I trained two embedding models, one on
      <a href="https://www.kaggle.com/datasets/gupta24789/text8-word-embedding" target="_blank" rel="noopener">text8</a>,
      which is the first 100MB of English Wikipedia, and one on
      <a href="https://mattmahoney.net/dc/textdata.html" target="_blank" rel="noopener">enwik9</a>, the
      first 1GB of English Wikipedia. I also downloaded one pretrained embedding model,
      <a href="https://nlp.stanford.edu/projects/glove/" target="_blank" rel="noopener">Stanford
      NLP&rsquo;s 6-billion token GloVe vectors</a>.
    </p>
    <p>
      So does it work? Well, sort of.
    </p>
    <p>
      The &ldquo;king - man + woman&rdquo; equation returns queen for all three vector models.
      Interestingly, the result vector computed by the enwik9 model is just a little bit closer to its
      actual vector for &ldquo;queen&rdquo; than the result that comes out of the GloVe model.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img6.png"
      alt="Three side-by-side vector-space plots for king - man + woman across the text8, enwik9, and GloVe 6B models; all three land near &quot;queen&quot;.">

    <p>
      The impact of model size starts to show up in &ldquo;walking - walk + swim&rdquo;. The two larger
      models return &ldquo;swimming&rdquo;, which is pretty cute. The small text8 model returns
      &ldquo;crawling&rdquo;. Initially, I was worried that this might be a vocabulary mismatch issue,
      that maybe &ldquo;swimming&rdquo; was simply missing from the top 30K most confidently-trained
      tokens in the text8 model. Once I restricted all three models to a common shared vocabulary, I was
      able to confirm that this is a genuine example of model quality improving as model training data
      size increases.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img7.png"
      alt="Three vector-space plots for walking - walk + swim: text8 returns &quot;crawling&quot; (0.673), while enwik9 and GloVe 6B both return &quot;swimming&quot; (0.665 and 0.801).">

    <p>
      Another interesting result, where you really see the impact of model quality most clearly:
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img8.png"
      alt="Three vector-space plots for paris - france + italy: text8 returns &quot;venice&quot; (0.785), enwik9 returns &quot;turin&quot; (0.803), and GloVe 6B returns &quot;rome&quot; (0.819).">

    <p>
      But a lot of the equations are simply nonsense, and Claude&rsquo;s explanation that &ldquo;king -
      man&rdquo; should expose some kind of &ldquo;royalty&rdquo; vector didn&rsquo;t show up at all.
    </p>

    <img class="post-image" src="https://www.maayanroth.com/blog/posts/images/hplm-ch2/img9.png"
      alt="Three vector-space plots for king - man: the top results are &quot;dukes&quot; (text8), &quot;accession&quot; (enwik9), and &quot;ethelred&quot; (GloVe 6B). None of the top results resemble a &quot;royalty&quot; concept.">

    <p>
      And with that, I&rsquo;ve sufficiently scratched this itch, and I&rsquo;m ready to move on to
      Chapter 3 &ndash; Recurrent Neural Networks.
    </p>]]></description>
    </item>
    <item>
      <title>Back to basics: The Hundred-Page Languages Models Book, Chapter 1</title>
      <link>https://www.maayanroth.com/blog/posts/hundred-page-lm-book-chapter-1.html</link>
      <guid>https://www.maayanroth.com/blog/posts/hundred-page-lm-book-chapter-1.html</guid>
      <pubDate>Wed, 22 Jul 2026 00:00:00 +0000</pubDate>
      <description><![CDATA[<p>
      As I wrote in
      <a href="https://www.maayanroth.com/blog/posts/early-misadventures-in-open-source-llms.html">my earlier entry</a>,
      I left my first foray into open-source LLMs with the strong conviction that I need to go back
      to basics and understand what is happening under the hood with these models. When I was in grad
      school in the early 2000s, we studied neural networks mostly as a historical curiosity, an
      evolutionary dead end that had been entirely evicted from use by statistical machine learning.
      When deep learning burst onto the scene in the 2010s, the idea that bigger models, bigger
      training data, more computation will combine to yield dramatically better results felt
      self-evident enough that I didn't bother trying to understand it more, well, deeply.
    </p>
    <p>
      So maybe it's embarrassing to admit this, but I never really bothered to update my mental model
      of LLMs beyond my (already cursory) understanding of deep learning. I did at least wrap my head
      around the colloquial concept of embeddings and the idea that you can represent semantic
      similarity between words in some machine-readable way, but I didn't go any further than that. I
      definitely did not do the work of understanding the math.
    </p>
    <p>
      But now, my goal is to be able to read a HuggingFace model card, and in order to do that, I have
      to learn all of the vocabulary of LLM architectures and hyperparameters.
    </p>
    <p>
      I've been steadily working my way through Andriy Burkov's phenomenal
      <a href="https://www.thelmbook.com/" target="_blank" rel="noopener">The Hundred-Page Languages Models Book</a>.
      I'm finding it very easy to read, and as long as I force myself to go slowly, and especially if
      I make sure that I am understanding all of the sample code snippets provided, the concepts that
      the book presents feel like they are resting in my brain in a way that feels like I'll actually
      retain them over time.
    </p>

    <h3>Chapter 1 &ndash; Machine Learning Basics</h3>
    <p>
      Just like it says on the box, the first chapter of the book is a review of machine learning
      basics, written for an audience that is being exposed to these ideas for the very first time.
      Since I am not encountering machine learning for the very first time, I was able to go through
      most of the chapter quite quickly. For me, it got interesting when moving from generic
      classification algorithms to neural networks in particular.
    </p>
    <p>
      The first bit of novel vocabulary that I encountered is the difference between a
      <strong><em>dense neural network</em></strong>, one in which each perceptron in a given layer is
      connected to every perceptron in the subsequent layer, and a
      <strong><em>convolutional neural network</em></strong>, in which the layers are not fully
      connected. The author notes that convolutional networks were originally designed for image
      processing, but have proved useful for certain kinds of text processing such as document
      classification. For me, this is interesting because one of the first bits of unfamiliar
      vocabulary that I encountered when browsing models in HuggingFace is that some LLMs are
      described as &ldquo;Dense&rdquo; whereas others are &ldquo;Mixtures of Experts&rdquo;.
    </p>
    <p>
      I'm trying not to skip ahead, so I haven't gone looking for an explanation of why a convolutional
      network might perform better in some domains or applications than a dense network. I can see the
      biological analogy; our brains are composed of clusters of neurons that are densely connected to
      their close neighbors, but only loosely connected to other clusters. I can imagine an image
      processing network working best when allowed to develop similar clusters of expertise, for
      example a set of neighboring perceptrons that together perform edge detection and another cluster
      that handles perspective and scale. I don't really understand why a convolutional network would
      be better for document classification, though, and I wonder whether the clusters need to be
      trained independently, or whether &ldquo;experts&rdquo; appear emergently, given large-enough
      training data and a convolutional network with enough subneighborhoods.
    </p>
    <p>
      The other novel concept for me from this chapter is the RELU activation function.
      <strong><em>RELU, or rectified linear unit</em></strong>, is the function:
    </p>
    <pre><code>RELU(x) = max(0, x)</code></pre>
    <p>
      What RELU does is take an input and truncate it at 0, so that the output is always positive.
      Apparently, RELU has been the predominantly-used activation function for neural networks since
      2012. I genuinely can't fathom why. When I first studied neural networks, the default activation
      function was the sigmoid, which makes perfect intuitive sense if you imagine each perceptron as
      a baby classifier. RELU makes no sense to me at all. However, the book promises that we will
      come back to RELU in Chapter 4 &ndash; Transformers, so I am, for now, suspending disbelief.
    </p>]]></description>
    </item>
    <item>
      <title>Learning Cultures reading group: “Like Coding In the Dark”</title>
      <link>https://www.maayanroth.com/blog/posts/coding-in-the-dark.html</link>
      <guid>https://www.maayanroth.com/blog/posts/coding-in-the-dark.html</guid>
      <pubDate>Thu, 09 Jul 2026 00:00:00 +0000</pubDate>
      <description><![CDATA[<p>
      While at Recurse Center, I'm hosting a weekly reading group centered around the collective
      works of <a href="https://www.drcathicks.com/" target="_blank" rel="noopener">Dr. Cat Hicks</a>,
      a researcher studying the psychology of software teams, and whose new book with that title
      just came out yesterday. Since none of us have gotten our hands on the book yet (my copy is
      waiting for me at my local bookstore), we had our discussion today about one of Dr. Hicks'
      older works:
      <a href="https://osf.io/preprints/psyarxiv/nz8m3_v1" target="_blank" rel="noopener">&ldquo;It's Like Coding in the Dark: The need for learning cultures within coding teams&rdquo;</a>.
    </p>

    <h3>A brief recap of the paper</h3>
    <p>
      Dr. Hicks interviewed 25 &ldquo;code writers&rdquo; of different levels of seniority and from
      different company sizes, all located in the Bay Area, on their experiences learning as a
      member of a software development team, with a particular focus on the experience of
      onboarding in an unfamiliar codebase. The themes that emerged from the interviews clustered
      into three main topics: the activities that code writers perform when learning a new codebase,
      code review as the common first instance in which a new team member receives feedback from
      their new teammates, and ways in which the company or team environment sends implicit and
      explicit messages about the value of learning.
    </p>
    <p>
      Most interviewees described a similar set of activities performed in order to build an
      iteratively more accurate mental model of the new code base. This learning was actively
      experimental in nature: intentionally breaking things, probing for potential edge cases, and
      forming hypotheses about the intentions or previous decisions of the previous writers of the
      code. In most environments, interviewees reported that this learning was conducted individually
      and privately, with limited opportunities for the new team member to share what they had
      learned with others.
    </p>
    <p>
      At the code review stage, interviewees reported feeling significant performance pressure. They
      were reluctant to use the code review as an opportunity to discuss their learning because of
      fear of being seen as less competent, and because of implicit or explicit messaging that
      communicated to them that only their output, the code artifact being reviewed, was of value,
      and the process that got them to that artifact was not.
    </p>
    <p>
      The code writers' environments reinforced a message that devalued learning both implicitly and
      explicitly. Explicitly, time pressure was a consistent theme, and activities that promote
      learning, such as documentation, code comments, and mentorship and collaboration, were seen as
      taking time away from producing code. Implicitly, new team members observed the absence of
      documentation, code comments, and pair programming, and inferred that these activities would
      not be valued by their new employer.
    </p>
    <p>
      Collectively, these themes combine to create cultures of what Dr. Hicks calls &ldquo;learning
      debt&rdquo;, defined as &ldquo;cumulative failure to support learning, created when code
      writers' investment in long-term understanding is disincentivized&rdquo;. Code writers working
      in cultures with large learning debts report feelings of loneliness, long-term stress, and
      demotivation.
    </p>

    <h3>Discussion themes</h3>
    <p>
      The themes and environments described by the interviewees in the paper resonated with many of
      us, and it felt validating to read about it as a commonly shared experience. One member of the
      discussion group recalled a time when, upon joining a new team as the only junior engineer,
      they were explicitly told by their manager that they were expected to &ldquo;sink or
      swim&rdquo;. The common theme of time pressure as a disincentive to learning was universally
      familiar.
    </p>
    <p>
      An interesting reflection that we had was that, even environments that want to promote learning
      sometimes struggle to do so effectively because of immature practices around knowledge transfer.
      One participant in our discussion described being on a team with a recurring Friday morning
      meeting called &ldquo;Knowledge Transfer&rdquo;, in which a member of the team would brain-dump
      everything they knew about a particular part of the code base. Attendees were expected to
      remember and retain everything that was said in those meetings, since there was no other
      documentation. We also noted that effective learning often requires a teacher, and that being
      an effective teacher is itself a skill that is not explicitly taught in most coding environments.
    </p>
    <p>
      Some of us have been fortunate enough to spend time in environments that do value and promote
      learning. Some useful practices from those environments include:
    </p>
    <ul>
      <li>Explicit and formal requirements to mentor others in order to be promoted to Senior Engineer</li>
      <li>
        Clearly documented onboarding expectations
        <ul>
          <li>
            For example, at one company, new team members were expected to reach a certain learning
            milestone by 3 months. However, if they failed to reach that milestone, this was
            explicitly named as a failure of their existing team, rather than the new employee
            themselves.
          </li>
        </ul>
      </li>
      <li>
        Onboarding as an objectively-evaluable rubric (e.g. &ldquo;can the new team member
        successfully deploy?&rdquo;, &ldquo;can the new team member successfully debug an issue?&rdquo;)
      </li>
    </ul>
    <p>
      We noted that all of these practices are only as effective as the managers who implement them.
      Individual team members are unlikely to successfully self-organize to promote a learning
      culture without leadership support.
    </p>
    <p>
      Finally, we spent a little while discussing the study itself, such as how it might have been
      impacted by a sample of 25 Bay Area software engineers, vs code writers from other countries or
      cultures, or employees in other fields. One participant described working in another country
      with an even stronger culture of not sharing information. In software teams in that country, the
      participant said, if you have knowledge, it's the norm to keep it to yourself because that will
      help you get ahead of your peers. Another participant described the substantial formal
      structures that exist to scaffold learning in other fields such as mental health and medicine,
      which are largely absent in software engineering.
    </p>

    <h3>My reflections</h3>
    <p>
      Over the years, I've worked in software environments with very different learning cultures.
      Reading the paper's section on code reviews, I couldn't help but think of my first code reviews
      as a brand new junior engineer at Google. I know that I learned so much from those reviews, but
      I definitely wouldn't describe the experience as comfortable. Later, at Flatiron, when we were
      writing our first engineering job ladder, we intentionally put teaching, mentoring, and sharing
      knowledge with others as expectations for senior engineers. Flatiron had recently acquired
      another company where being the &ldquo;go to expert&rdquo; on a topic was strongly valued, and
      some engineers from that company were reluctant to share their unique knowledge because they
      feared it would harm their job security. We encoded formal expectations around knowledge sharing
      in our ladder (and in the company value of &ldquo;Train Your Own Replacement&rdquo;) as a way of
      pushing back against that cultural norm.
    </p>
    <p>
      I also strongly agree with the paper's reflection that companies with strong learning cultures
      are those where it's safe to be seen making mistakes and where communicating about your process,
      and not just your results, is appreciated and rewarded. I don't need to write about blameless
      postmortems, plenty of others have said what needs to be said already. I haven't seen this idea
      about the value of showing your process said explicitly before. It made me think of a common
      practice on my most recent engineering team. Engineers would frequently record short videos in
      which they demonstrated some part of their work setup, or an experiment they had done, whether
      or not that experiment succeeded. The most senior and tenured engineers pioneered this practice,
      demonstrating to newer team members that showing your work was a behavior that would be valued
      within the team culture.
    </p>
    <p>
      It's fun to read this paper while at Recurse Center, a software environment with the stated goal
      of being a learning culture. There are lots of explicit ways that RC promotes learning (e.g.
      scheduled pair coding jams and presentations), but it's also been fun to notice the implicit
      ways that the value of learning-promoting activity is communicated. The paper describes cultural
      onboarding moments in which new employees look around and note whether their more established
      peers are writing comments and documentation, and through that observation decide whether or not
      to write comments and documents. Similarly, as a new batch member, I've noticed that RC
      participants devote as much or more space in their daily check-in messages to coffee chats and
      pairing sessions with other RCers as they do to their coding output.
    </p>
    <p>
      If you're a Recurser and would like to join us for a future discussion, we'll be meeting on
      Thursdays at 1pm ET for at least the next 4 weeks. I also highly recommend following
      <a href="https://bsky.app/profile/grimalkina.bsky.social" target="_blank" rel="noopener">Dr. Hicks on Bluesky</a>.
    </p>]]></description>
    </item>
    <item>
      <title>Early misadventures in open source LLMs</title>
      <link>https://www.maayanroth.com/blog/posts/early-misadventures-in-open-source-llms.html</link>
      <guid>https://www.maayanroth.com/blog/posts/early-misadventures-in-open-source-llms.html</guid>
      <pubDate>Wed, 08 Jul 2026 00:00:00 +0000</pubDate>
      <description><![CDATA[<h3>How it started</h3>
    <p>
      I came into Recurse Center with the goal of becoming a proficient user of open source
      LLMs, and some vague idea of hooking an open source model up with some kind of
      large-scale agent management framework like GasCity and seeing if I could get the
      system to make something useful.
    </p>
    <p>
      I was inspired by Vicki Boykis' recent newsletter issue,
      <a href="https://newsletter.vickiboykis.com/archive/running-local-models-is-good-now/" target="_blank" rel="noopener">Running local models is good now</a>,
      in which she describes her experience successfully getting a local open weight model to
      serve as her primary agentic coding tool. I love the idea of getting the benefit of an
      AI coding assistant without bleeding money to Anthropic. My first week at RC, I spent about a day wrestling
      with the
      <a href="https://patloeber.com/gemma-4-pi-agent/" target="_blank" rel="noopener">setup tutorial</a>
      that Vicki links to but ran into one yak-shaving problem after another.
    </p>
    <p>
      No shade to the tutorial &ndash; it's perfectly clear and the steps work perfectly. It's
      just that, when I followed the tutorial, I indeed got LM Studio up and running, I
      successfully downloaded the recommended Gemma model from HuggingFace, I hooked it up
      with Pi as my coding harness... And then watched my computer, with its poor sad 8GB of
      RAM, become completely unresponsive as soon as I started trying to use my new setup. Flipping
      back to Vicki's post, I saw that her computer has 64GB of RAM. Fancy!
    </p>
    <p>
      Ok, fine, maybe local models are not in my immediate future. But luckily, Recurse Center
      has a partnership with
      <a href="https://modal.com/" target="_blank" rel="noopener">Modal</a>, where we can get
      some free credits to run AI projects in their cloud. My next idea was to host an
      inference server on Modal and have Pi, running on my machine, make calls out to that
      server. Modal has a
      <a href="https://modal.com/docs/examples/vllm_inference" target="_blank" rel="noopener">tutorial and example script</a>
      for spinning up an inference server, which I downloaded and ran.
    </p>
    <p>
      Again, props to the folks at Modal &ndash; the tutorial script worked smoothly out of
      the box. I didn't change any of the defaults, just spun up the inference server and
      pointed Pi at it. And promptly burned $2.48 in Modal credits writing a Python function
      to generate the next number in a Fibonacci sequence.
    </p>

    <h3>Now what?</h3>
    <p>Let's back up.</p>
    <p>
      In his tutorial
      (<a href="https://patloeber.com/gemma-4-pi-agent/" target="_blank" rel="noopener">How to run a local coding agent with Gemma 4 and Pi</a>),
      Pat Loeber recommends using <code>Gemma 4 26B A4B (Q4_K_M)</code>. He describes it as a
      &ldquo;mixture of experts&rdquo; model, and suggests downloading the quantized GGUF
      version. I have no idea what any of those words mean.
    </p>
    <p>
      Vicki Boykis recommends <code>gemma-4-12b-qat</code>, noting that it is &ldquo;more
      recent and smaller and faster, without much sacrifice in accuracy&rdquo;. Sounds good to
      me, I like smaller, faster, and more accurate. Unfortunately, before I even tried to
      download it, LM Studio informed me that this model is too large to run successfully on
      my computer. Pat's model is much larger, an obvious non-starter.
    </p>
    <p>The model that I did semi-successfully run locally was <code>gemma-4-e2b</code>. Is that a good model?
    A bad model? If it had not completely frozen my computer, would it have done anything actually 
  useful? How am I to know?</p>

    <table>
      <thead>
        <tr>
          <th>Model</th>
          <th>Size</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Gemma 4 26B A4B (Q4_K_M)</td>
          <td>15.64 GB</td>
        </tr>
        <tr>
          <td>gemma-4-12b-qat</td>
          <td>7.15 GB</td>
        </tr>
        <tr>
          <td>gemma-4-e2b</td>
          <td>5.94 GB</td>
        </tr>
      </tbody>
    </table>

    <p>
      Modal's inference tutorial script recommends the same model as Pat,
      <code>google/gemma-4-26B-A4B-it</code>, but runs it on their third-most-expensive GPU,
      an H200. Since I wasn't excited to set quite that much money on fire quite that fast, I
      tried to sub out Vicki's recommended model.
    </p>
    <p>
      Here's where it got exciting. I tried to modify the Modal script to use
      <code>gemma-4-12b-qat</code> and a much cheaper GPU, only to discover that vLLM, the
      model serving framework that the tutorial relies on, doesn't support the Gemma 4 12B
      models
      (<a href="https://github.com/vllm-project/vllm/issues/44494" target="_blank" rel="noopener">open bug report here</a>).
    </p>
    <p>
      At this point, I had a series of very frustrating chats with Claude, in which I tried to
      select a different model, one that would effectively trade off low cost with adequate
      performance as a coding agent. But ultimately, I felt like I just really had no idea what
      was going on. What's the difference between 12B vs 26B vs E2B? What does QAT mean? Why
      would I pick a model from the Gemma 4 family vs Claude's suggestion of GPT-OSS-20B?
    </p>

    <h3>Changing direction</h3>
    <p>
      One of my goals during this batch at Recurse Center is to stop feeling like an imposter
      when it comes to large language models. Not so much how to use them, which honestly, I
      feel fine about, but to have a better mental model of what's going on under the hood,
      and how the different models vary. Maybe a good way to express this goal is, &ldquo;I'd
      like to be able to read a model card on HuggingFace and understand what all the words
      mean, both individually and together.&rdquo;
    </p>
    <p>
      A fellow Recurser recommended Andriy Burkov's
      <a href="https://www.thelmbook.com/" target="_blank" rel="noopener">The Hundred-Page Languages Models Book</a>
      as a good way to go all the way back to basics. I'm about halfway through Chapter 2 and
      finding it to be a fantastic read: clear, accessible, and the right mix of theory and
      implementation. I'll share more thoughts on what I've read so far, and what I've started
      to implement as a result, in a future post.
    </p>]]></description>
    </item>
    <item>
      <title>Hello, world</title>
      <link>https://www.maayanroth.com/blog/posts/hello-world.html</link>
      <guid>https://www.maayanroth.com/blog/posts/hello-world.html</guid>
      <pubDate>Mon, 06 Jul 2026 00:00:00 +0000</pubDate>
      <description><![CDATA[<p>
      This is the first post on this blog, mostly here to prove the wiring works. 
    </p>]]></description>
    </item>
  </channel>
</rss>
