What Actually Happens When an LLM Generates a Token? A Deep Dive into Softmax An engineer's deep dive explains the mechanics of how large language models generate tokens, focusing on the softmax function that converts raw logits into a probability distribution. The post breaks down the mathematical steps, showing how exponentiation and normalization turn scores like 8.2 for 'Paris' into probabilities such as 66.5%, and clarifies that LLMs are probabilistic in output but deterministic in their internal scoring. 21:38. Berlin. Tuesday evening. I had just come home from a meetup with a question in my head. Is an LLM probabilistic or not? Because, well... somehow yes. But also somehow no. What actually happens between "the model predicts a token" and "the model produces a token"? In summary, an LLM produces a probability distribution over possible next tokens. A decoding strategy then turns that distribution into an actual token. But that explanation hides most of the interesting engineering and actually very interesting mathematics. To fully understand what happens and to rediscover the beauty of e , it helps to follow the process one step at a time. When an LLM processes a prompt, it does not simply decide: "The next token is Paris." First of all, the model takes the input and produces a score for every possible next token, based on its learned weights . Suppose the context is: The capital of France is ... Conceptually, the model might produce something like: Paris 8.2 London 6.1 Berlin 5.4 Pizza -2.3 These scores are called logits . A logit is a raw score produced by the model for a possible next token. How do those scores become probabilities? That's where Softmax enters. The problem with raw logits is that they are not probabilities. They can be positive, negative, large, or small. Within a probability distribution, all probabilities are positive, and all probabilities add up to 100%. For example: Paris 70 % London 20 % Berlin 10 % Our logits don't do that. So we need a transformation that turns them into something that can be interpreted as probabilities. That's what Softmax does. The Softmax function is: At first glance, the formula might look a little bit intimidating. But it's actually pretty simple, so stay with me. Simply put, the formula does two things in order to transform the logits into probabilities: First, it transforms every logit into a positive value. In addition, it amplifies the relative differences between the values so that the probability distribution gets clearer. That's what the exponential function e^x is for. Finally, the fraction normalizes these values by dividing each one by the sum of all exponentiated logits. The result is a probability distribution where all values are positive and add up to 1. Let's go down the rabbit hole step by step. The little i simply identifies the token we're currently looking at . pi means the probability assigned to token i . If we're calculating the probability of Paris, we write: pi=pParis Nothing mysterious. It's just what we're interested in - the probability. zi is the corresponding logit for token i . So if the logit of Paris is 2, we write: zParis=2 Still straightforward. Look at: The symbol ∑ simply means: Add things together. And j is the index we use to go through all the tokens we're summing over . In this case: Take every possible token, calculate ezj , and add all the results together. In engineering language this would be: Start with zero, iterate over all possible next tokens, calculate ezj for each one, and add the result to the total. total = 0 for j in tokens: total += exp z j Suppose we have only three tokens: Paris z = 2 London z = 1 Berlin z = 0 Then: That's it. The denominator in the Softmax formula is simply the sum of all exponentiated logits. In our example, the result would be Now calculate the probability of Paris z=2 : So the probability of Paris is approximately 66.5% . Then London z=1 : So the probability of London is approximately 24.5% . Then Berlin z=0 : So the probability of Berlin is approximately 9.0% . Notice what happens: You get pretty differentiated results and at the same time, the scores turned to a probability. That is Softmax. Exponentiate every score. Add all those values together. Then divide each individual value by the total. And now the results form a probability distribution. The formula only looks intimidating because mathematics is extremely good at packing an entire paragraph into one line. Look at the following table: | Token / probability | With exponential pi=∑jezjezi | Without exponential pi=∑jzjzi | |---|---|---| | pParis | ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: …\mathbf{66.5%} | ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: …\mathbf{66.7%} | | pLondon | ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: …\mathbf{24.5%} | ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: …\mathbf{33.3%} | | pBerlin | ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: … \mathbf{9.0%} | ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: …=\mathbf{0.0%} | Sum | 100.0% | 100.0% | In this particular example, Paris and London still look relatively similar, but Berlin immediately drops to 0% without ex . More importantly, directly normalizing logits only works as a valid probability construction when the logits are non-negative. Real logits can also be negative. So the exponential isn't just decoration. It gives us a transformation with the properties we need: positive values and a way of amplifying relative differences before normalization. And that brings us to e . You might remember that e≈2.718281828... You might also remembered that it had something to do with exponential functions and logarithms. Let's explore why it matters. e naturally appears when we describe continuous exponential growth . And it has one remarkably convenient mathematical property: The rate at which ex changes - f′ x - is always and exactly its current value f x . Crazy. Take this table with x , the values f x and their exponential growth f′ x : | x | f x =ex | f′ x =ex | |---|---|---| | 0 | f 0 =1 | f′ 0 =1 | | 1 | f 1 =2.718 | f′ 1 =2.718 | | 2 | f 2 =7.389 | f′ 2 =7.389 | The larger the function becomes, the faster it grows — at a rate proportional to its current value. Did you notice? The equation is mathematically elegant. Computers, however, have finite-precision numbers. But exponentials grow fast. Very fast. If a logit is 10000, just calculating e10000 is not a nice thing to do to your processor with floating-point arithmetic. So real implementations use a mathematically equivalent, numerically stable form of Softmax: Why is this allowed? Because subtracting the same constant from every logit does not change the resulting Softmax probabilities: for any constant c . Let's explain this from an engineering perspective: In practice, we want to keep the numbers inside the exponential function as small as possible. Large exponents can cause numerical overflow and make the calculation unnecessarily difficult. So we subtract the largest logit from every logit . If the largest logit is max z , we calculate: zi′=zi−max z This makes the largest logit exactly zero: max z −max z =0 And because the largest logit was subtracted from all the others, every other adjusted logit is negative: zi−max z ≤0 Now look at what happens when we exponentiate them. The largest exponent is: e0=1 And all the other exponentials are between 0 and 1: 0