The World Vol 8 · Words
ch 83 / 105
Chapter 83

Guessing What Comes Next

The missing next token

The attention head turns four tokens from this world's history into four richer descriptions of those same tokens. It never produces the fifth token. A machine that writes has to turn a row into a guess about what may come next, and that is a different operation.

A model hands back a share for every token it could produce next, and a separate picker chooses one token from those shares. The arithmetic never picks, and the picker never reasons. That split is why the page can produce a fluent sentence about an event that did not happen, produce a different sentence on the second run, and repeat itself when the picker is turned down.

The model here is the smallest one that can be called that with a straight face. Take the chronicle The World has been appending to since it was given a founding document, cut it into tokens with the merge table from two chapters ago, and count how often each token was followed by each other token. That count is the model. There are no matrices in it, nothing is projected into anything, and no number in it was arrived at by any means except adding one. It is small enough to print a row of, and it is enough to demonstrate every property in the paragraph above.

By the end of the page internal/lang has a Chain that holds the counts, a Shares that turns one row of them into a distribution at a chosen temperature, a Draw that takes one number off this world's own seeded generator and picks with it, and a Write that repeats the whole thing until an entry ends. There is a bench, cmd/guess, whose every mode runs on a laptop with nothing switched on. Nothing here starts a container, dials a server or opens a model file. The valley is untouched for the third page running: the five simulation packages gain nothing, the store gains nothing, and the sealed-import test written two chapters ago reads the same six packages and finds the same nothing.

One word this page will not use about any of it. Counting how often one token followed another is counting. There is no gradient here, no backward pass, no loss and no learning rate, and a page that called this training would have said the wrong thing about a distinction the rest of the volume leans on.

The follow-count chain

A refresher on the two things this section stands on, because both were built pages ago. A token is a run of bytes the merge table has a number for: 256 numbers for the 256 byte values, then one more for every merge counted off the corpus, 512 in all for the table this book keeps. And the corpus is the text column of the chronicle, one entry a line, 7,123 bytes of it, which encode to 1,419 tokens. Encoding is deterministic, so those 1,419 numbers are the same 1,419 numbers on any machine that runs it.

Counting pairs across a row of tokens is the same loop that found the merges, with the merging taken out. Walk the list, and for every position add one to a tally kept under two keys: the token you are standing on and the token after it. In Go that is a map of maps, and the only care it needs is the care every map in this book needs.

▣ Build · stage 1 — the whole model, which is a tally
// internal/lang/guess.go
func Count(ids []int, size int) (*Chain, error) {
	if size < 1 {
		return nil, fmt.Errorf("lang: a chain wants a vocabulary of at least 1, not %d", size)
	}
	tally := make(map[int]map[int]int)
	for i, id := range ids {
		if id < 0 || id >= size {
			return nil, fmt.Errorf("lang: token %d of %d is %d, and the vocabulary holds %d", i+1, len(ids), id, size)
		}
		if i+1 == len(ids) {
			break
		}
		if tally[id] == nil {
			tally[id] = make(map[int]int)
		}
		tally[id][ids[i+1]]++
	}

The rest of the function turns each inner map into a slice sorted commonest first, with ties broken by the lower token number, which is the same rule the merge counting uses and is there for the same reason. A Go map hands its keys back in a different order on every run. A row whose order came out of the map would be a different row on Tuesday, and a draw made against it would be unreproducible for a reason that has nothing to do with the seed. Sorting the row once, at counting time, is what makes everything after it a fixed object.

$ go run ./cmd/guess -mode counts
guess: which token followed which across the chronicle, a table of 256 merges

  the corpus and the table it is cut with
    chronicle entries                            91
    bytes of text                              7123
    vocabulary                                  512
    tokens the whole corpus encodes to         1419

  the counting
    adjacent pairs walked                      1418
    tokens anything was ever seen after         289
    distinct continuations among them          1168
    rows with nothing to choose between          73
    rows a temperature cannot change            215
    the widest row                               25

  the 8 widest rows
    token  width  total  stands for
       53     25     25  "5"
       51     24     24  "3"
       56     22     22  "8"
       57     22     22  "9"
       55     20     20  "7"
       50     19     19  "2"
       48     18     18  "0"
       32     17     17  " "

  the model is 1168 numbers

Eleven hundred and sixty-eight numbers. That is the entire model, and it is the figure to sit with before anything else on this page happens, because every claim made later about what such a thing can and cannot know has to be true of a tally this small. Of the 512 tokens in the vocabulary, only 289 were ever followed by anything at all. Seventy-three of those 289 have exactly one continuation, so whatever setting anybody picks they have nothing to choose between. Another line in that block will not mean much until the next section and is measured here because it belongs with the others: 215 of the 289 rows hold nothing but equal counts, and a row of equal counts is a row no setting on this page can move. Three quarters of this model is already decided. And the widest rows in the table are all single digits: token 53 is the character 5, and twenty-five different tokens were seen after it in seven thousand bytes.

The digits being the widest rows is not an accident of this corpus, it is the corpus itself showing through. Eighty of the ninety-one entries are the same sentence with four numbers substituted into it, and the merge table spent most of its rows learning that sentence, so a digit is exactly the place where the history stops repeating and starts being about a particular year. A wide row is a place where the counting learned little. That will matter twice before the page is over.

There is one token that behaves differently from all the others and it is the reason this works without any bookkeeping. Pairs were counted inside an entry and never across the end of one when the merge table was learned, so no merge can contain a line ending, so the byte \n is always token 10 and never part of anything larger. Encoding the whole corpus in one pass therefore produces token 10 exactly where an entry finished, and counting straight down that list gives the chain something no other token gives it: a row that means an entry ended, and here is how the next one began.

▣ Build · stage 2 — one row, which is what a model hands back
// internal/lang/guess.go
// Row is the continuations of one token, commonest first. A token the
// corpus never followed with anything has an empty row, which is not
// an error: it is a token that only ever ended a line.
func (c *Chain) Row(from int) ([]Step, error) {
	if from < 0 || from >= c.size {
		return nil, fmt.Errorf("lang: no token %d in a chain over a vocabulary of %d", from, c.size)
	}
	return c.rows[from], nil
}
$ go run ./cmd/guess -mode row
guess: one token's row of counts, and the same row as shares, a table of 256 merges, temperature 1.00

  the token the row belongs to
    token 10, 1 byte, "\n"

  what followed it, how often, and what that is as a share
       to  count   share  running  stands for
      328     11  0.1222   0.1222  "year 1"
      329     11  0.1222   0.2444  "year 2"
      330     11  0.1222   0.3667  "year 3"
      331     11  0.1222   0.4889  "year 4"
      332     11  0.1222   0.6111  "year 5"
      333     11  0.1222   0.7333  "year 6"
      334     11  0.1222   0.8556  "year 7"
      269      5  0.0556   0.9111  "The "
      303      3  0.0333   0.9444  "year "
       80      2  0.0222   0.9667  "P"
       87      2  0.0222   0.9889  "W"
       65      1  0.0111   1.0000  "A"

  continuations it has                         12
  times the token was followed at all          90
  the shares add to                        1.0000

That block is the sentence at the top of the page, printed. It is not an answer to anything. It is twelve options with a number against each, and the numbers add to one. Ask this model how a chronicle entry begins and the honest report of what it holds is the whole column, and any single token you pull out of it is a decision somebody else made.

Read the counts and the corpus is visible in them. The chronicle is an append-only log and its entries are written in two registers: eleven founding rows in an operator's prose and eighty annual rows in the terse annalistic form the yearly count uses. Seven of the twelve options are the tokens year 1 through year 7, each occurring eleven times, because eighty years numbered 1 to 80 give ten entries starting with each of those and one more from the single-digit year itself. Then The five times and a capital letter here and there, which is ten of the eleven founding rows. The total is 90 and not 91 for two reasons that come to one line: the last line ending in the file is followed by nothing at all, and the first entry in the file has no line ending in front of it, so the founding row missing from that column is the one the document opens with.

One property of this model has to be named now, because everything the page shows later would otherwise look like a defect in the counting instead of a consequence of the design. This model reads exactly one token. The row it consults depends on the token it is standing on and on nothing before that, so a prompt of forty tokens is, to this thing, its last token and no more. The previous chapter spent a page on the machinery that fixes this, and priced it: every token looking at every other token means the work grows with the square of the row. What is on this page is that count at its cheapest setting, and the point of running it is that the interesting failures do not need the expensive setting to appear.

Temperature and the draw

Turning a row of counts into shares of one could be done with a division. Divide each count by the row's total and stop. It gives the right answer, it is one line, and it is not what anything does. The row a real model produces holds signed numbers that can be negative and can be enormous, never counts, and the operation that turns a list like that into shares of one is the softmax the last chapter built and exercised: raise e to each number, divide each result by the total of all of them, and take the row's largest entry off every entry first so the biggest thing e is ever raised to is zero.

So the counts get turned into scores first, by taking the natural log of each one, and then the softmax turns the scores back into shares. That looks like a detour that cancels out, and at one particular setting it exactly does: raising e to the log of a count gives the count back, so the softmax then divides each count by the row's total and the answer is the plain division after all. The detour buys one thing, and the thing it buys is the dial.

▣ Build · stage 3 — the same counts, at a temperature
// internal/lang/guess.go
// Zero is refused here rather than handled. Dividing by it is not a
// temperature and the limit it stands for is a different operation,
// which Draw does under its own name.
func (c *Chain) Shares(from int, temp float64) ([]float64, error) {
	if temp <= 0 {
		return nil, fmt.Errorf("lang: a temperature divides every score, so it has to be above zero, not %g", temp)
	}
	row, err := c.Row(from)
	if err != nil {
		return nil, err
	}
	if len(row) == 0 {
		return nil, nil
	}
	scores := make([]float64, len(row))
	for i, s := range row {
		scores[i] = math.Log(float64(s.N)) / temp
	}
	return Softmax(scores), nil
}
$ go run ./cmd/guess -mode dial -from 311
guess: one row of counts, a table of 256 merges, at temperatures 5.00,1.00,0.30 and at the likeliest token every time

  the token the row belongs to
    token 311, " born and 15"

  the same counts as shares, at each temperature
       to  count  T=5.00  T=1.00  T=0.30  stands for
       55      2  0.2231  0.3333  0.7159  "7"
       53      1  0.1942  0.1667  0.0710  "5"
      417      1  0.1942  0.1667  0.0710  "27 gone"
      476      1  0.1942  0.1667  0.0710  "10 gone"
      493      1  0.1942  0.1667  0.0710  "67 gone"

  the largest share in the row
    T=5.00                                 0.2231
    T=1.00                                 0.3333
    T=0.30                                 0.7159
    the likeliest token every time                     1.0000

Token 311 stands for twelve bytes reading born and 15, which is the model standing halfway through a number in the middle of a yearly entry with five ways to finish it. One of them was seen twice and four were seen once each. At temperature 1 the shares are those counts and nothing else: a third and four sixths. Turn the dial down to 0.30 and the one that was seen twice takes 0.7159 of the row while the four others share what is left. Turn it up to 5.00 and the five options converge toward being equally likely, with the commonest holding 0.2231 against 0.1942 for each of the rest. The counts have not moved. Nothing has been counted again. One division changed how hard the row leans on what it knows.

∑ Math Interlude — a count, a share, and a power

Do the row above by hand, with the numbers first and the letters afterwards. Five continuations with counts 2, 1, 1, 1, 1. The total is 6, so the plain shares are 2/6 and four lots of 1/6, which is 0.3333 and 0.1667 four times. That is what the run printed at temperature 1, and it is what a division would have given.

Now the temperature. Each count becomes a score by taking its natural log, and the score is divided by the temperature before the softmax sees it. Follow one entry through at a temperature of one half. The score of the count 2 is ln 2, dividing by 0.5 doubles it to 2 ln 2, and raising e to 2 ln 2 gives 4. The score of each count 1 is ln 1, which is 0, and 0 divided by anything is still 0, and e to the 0 is 1. So the softmax is handed 4, 1, 1, 1, 1, whose total is 8, and the shares come out 0.5 and four lots of 0.125.

Four is two squared, and the halving of the temperature is where the squaring came from. That generalises exactly, and it is the whole of what temperature is:

pi = ci1/T ÷ Σcj1/T

A share at temperature T is that option's count raised to the power one over T, divided by the total of every count raised to the same power. At T = 1 the power is 1 and the shares are the counts over their total. At T = 0.30 the power is 3.33, so 2 becomes 10.08 against four 1s and the commonest takes 0.7159. At T = 5 the power is 0.2, so 2 becomes 1.149 against four 1s and the row nearly flattens. Push T higher and every count tends toward 1, which is a row where everything is equally likely and the counting might as well not have happened. Pull T toward 0 and the largest count runs away from the others, and in the limit the row is one option at 1 and everything else at 0. The chain refuses to compute that limit, because the arithmetic divides by T, and the run above prints the 1.0000 it stands for on a line of its own.

cithe count: how often token i was seen after this one
Σcjthe row's total, added over every continuation it has
pithe share: what fraction of the row token i holds, all of them adding to 1
Tthe temperature, above zero, dividing every score before the softmax
1/Tthe power every count is raised to: above 1 sharpens the row, below 1 flattens it
ln cthe score: the natural log of a count, which the softmax undoes at T = 1
▤ Note — why the log is safe at the far end of the dial

Taking a log and then exponentiating it looks like an invitation to trouble at small temperatures, and it would be without the one line the last chapter put at the top of Softmax: the row's largest entry is taken off every entry before anything is raised to anything. Do the arithmetic on the row printed a page ago. Its biggest count is 11 and the natural log of 11 is 2.3979. At a temperature of 0.003 that becomes a score of 799.3, and the largest number a float64 can hold is e to about 709.78, so raising e to 799.3 gives an infinity and every share in the row becomes an infinity divided by an infinity. With the subtraction the largest score becomes 0, the rest become large negative numbers, e to a large negative number is 0, and the row comes out as one share of 1.0000 and eleven of 0.0000 that still add to one. Run -mode row -temp 0.003 and that is what prints.

Shares are still not a token. Something has to pick, and the thing that picks in this world is the generator every stochastic system in this book has taken since a valley first decided where to put a rock: a numbered stream opened off an explicit seed, never off the clock. The bench opens number 23 for its draws and says so in its banner, and the two modes on this page that draw no number at all leave the seed out of theirs, because a banner naming a setting its run never read is a banner a reader would be right to trust and wrong to.

▣ Build · stage 4 — one number, and where it lands
// internal/lang/guess.go
func (c *Chain) Draw(r *rand.Rand, from int, temp float64) (int, float64, error) {
	u := r.Float64()
	row, err := c.Row(from)
	if err != nil {
		return 0, u, err
	}
	if len(row) == 0 {
		return 0, u, fmt.Errorf("lang: nothing ever followed token %d", from)
	}
	if temp == 0 {
		return row[0].To, u, nil
	}
	share, err := c.Shares(from, temp)
	if err != nil {
		return 0, u, err
	}
	run := 0.0
	for i, p := range share {
		run += p
		if u < run {
			return row[i].To, u, nil
		}
	}
	return row[len(row)-1].To, u, nil
}
$ go run ./cmd/guess -mode draw -from 311
guess: one number off the stream, and the token it lands on, a table of 256 merges, seed 83 on stream 23, temperature 1.00

  the row, laid end to end from 0 to 1
       to  share   from      to  stands for
       55 0.3333 0.0000  0.3333  "7"
       53 0.1667 0.3333  0.5000  "5"
      417 0.1667 0.5000  0.6667  "27 gone"
      476 0.1667 0.6667  0.8333  "10 gone"
      493 0.1667 0.8333  1.0000  "67 gone"

  the first number off the stream        0.6338
  the segment it falls in                     3
  the token that segment belongs to         417   "27 gone"

  20 draws from the same row, from the same seed
       to  drawn  expected  stands for
       55      7      6.67  "7"
       53      3      3.33  "5"
      417      4      3.33  "27 gone"
      476      5      3.33  "10 gone"
      493      1      3.33  "67 gone"

The picking is a running total and a comparison. Lay the shares end to end from 0 to 1 so each option owns a stretch of the line as wide as its share, take a number between 0 and 1, and see whose stretch it fell in. The first number this stream ever produces is 0.6338, which falls between 0.5000 and 0.6667, so the answer is token 417 and the model has finished the number as 1527 gone. Nothing in that decision consulted what the tokens mean, and nothing in it could have. A share and a stretch of a line are the same object measured two ways.

Twenty draws off the same seed give 7, 3, 4, 5 and 1 against expectations of 6.67, 3.33, 3.33, 3.33 and 3.33. Close, and not equal, and it would be a mistake to want them equal: twenty draws from a five-way split are twenty draws, and a run that came out exactly on the expectation every time would be a run that was not drawing.

Two decisions inside Draw are load-bearing and neither is an optimisation. The first is that the number comes off the stream on the very first line, before the row is even fetched, so a draw costs exactly one number at every temperature including the one where the number is never consulted. This book settled that rule when it decided how a genome copies: an operation whose appetite for the stream changes with a setting puts two runs of the same seed at different places in the same stream, and every figure after the first difference is a figure about a different world. Here it means the four blocks of the temperature run below are drawing on identical numbers, so any difference between them is the temperature and cannot be anything else.

The second is the line reading if temp == 0. Zero is not a very low temperature, because the arithmetic divides by it. It is a different instruction: stop sampling, take the commonest. The distribution is unchanged and the thing reading it has been swapped out, and that is what a decoding setting always is.

A row of counts, its shares, and the number that picks Three stages stacked. At the top, five boxes holding the counts 2, 1, 1, 1, 1, labelled underneath with the tokens they belong to: 7, 5, 27 gone, 10 gone and 67 gone. In the middle, the same five as segments of one bar running from 0 to 1, the first taking 0.3333 of the bar and the other four taking 0.1667 each. At the bottom, an arrow pointing up into the third segment at 0.6338, the first number off the seeded stream, which is the token the draw returns. A DISTRIBUTION, AND A NUMBER THAT PICKS the model produces the bar; the seed produces the arrow 1 · how often each token followed token 311 2 7 1 5 1 27 gone 1 10 gone 1 67 gone 2 · the same counts as shares of one 0.3333 0.1667 0.1667 0.1667 0.1667 0 1 3 · one number off the seeded stream 0.6338 falls in the third stretch, so the token is 27 gone
Figure 83.1 — the counting produces every stretch of the line and never picks; the generator produces one number and never reads a count. Change the temperature and the stretches move. Change the seed and the arrow moves.

Ten entries about nothing

Writing is the draw in a loop. Start at the token that means an entry ended, draw the next, move onto it, draw again, and stop when the entry break comes back around or when a limit is reached. What comes back is the tokens the chain produced and not the token it was given, decoded through the same merge table that cut the corpus in the first place.

▣ Build · stage 5 — the loop, and what it writes
// internal/lang/guess.go
func (c *Chain) Write(r *rand.Rand, from, stop, limit int, temp float64) ([]int, bool, error) {
	var out []int
	at := from
	for len(out) < limit {
		next, _, err := c.Draw(r, at, temp)
		if err != nil {
			return out, false, err
		}
		if next == stop {
			return out, true, nil
		}
		out = append(out, next)
		at = next
	}
	return out, false, nil
}
$ go run ./cmd/guess -mode write
guess: 10 entries out of the counting table, a table of 256 merges, seed 83 on stream 23, temperature 1.00

  every line below is the table's output. Nothing in the valley wrote any of it.

   1  year 6: 12 hobbs standing in The Hollow, 62 born and 1753 gone
   2  year 126 gone
   3  year 45: 238 hobbs standing in The Hollow, 1912 born and 1732 gone
   4  year 372 born and 166: 240 hobbs standing in The Hollow, 191 hobbs standing in The Hollow, 1643 hobbs standing in The Hollow, 205 gone
   5  Plast now whit is filt of what ce of them is agak afoulacksaft ground. I ks. Anything here ten Pending. I have skn it, and not one ppria named nothing stands mades it bread there is griced going tomes ho I have soes this is The what igh it.
   6  year 605 born and 168391 gone
   7  year 683 gone
   8  year 531 born and 1744 gone
   9  year 209 born and 1684 gone
  10  year 31: 237 hobbs standing in The Hollow, 1771 hobbs standing in The Hollow, 45 born and 9 born and 9: 238 hobbs standing in The Hollow, 173: 238 hobbs standing in The Hollow, 169: 239 hobbs standing in The Hollow, 166727 gone

  entries that stopped on the entry break     10 of 10
  the rest ran to the limit of 200 tokens, and are marked +

Line 1 is the thing this chapter exists to show you. It is a chronicle entry. It has the year, the count standing, the ground's name, the births and the deaths, in the order the world writes them, with the punctuation in the right places and no word out of register. It is also not something that happened. In the world this table counted, year 6 finished with 338 born and 355 gone, and 1,753 dead against 62 born is not a year, it is two unrelated years' figures ending up next to each other because a token that ends one number is a perfectly ordinary token to follow with a token that begins another.

The header line above the block is printed by the bench and it is there on purpose. Every one of those ten lines is the output of a counting table, shown as the output of a counting table. Nothing in the valley wrote any of it, nothing in the valley has been told about it, and the chronicle those counts came off is untouched: it is an append-only log, it gained nothing today, and the ninety-one entries in it are the ninety-one entries it had this morning.

Read down the rest of the block and the failures sort themselves into two kinds, and both come straight off the count listing at the top of the page. Lines 2, 6, 7, 8 and 9 are fragments: the model got into the middle of a yearly sentence, hit a digit, and a digit is a row twenty-five options wide, so it took the exit that goes straight to the end. Line 4 and line 10 are the same wide rows failing in the other direction, looping back into the middle of the sentence they had already written and writing it again, three and four times over, because nothing in a table of pairs has any memory of having been here before.

Line 5 is the interesting one. It is the founding register, and it has come apart into something that has the rhythm of English and almost none of the words. The reason is arithmetic: eighty of the ninety-one entries are one sentence written eighty times, and eleven are prose that occurs exactly once. The counting had eighty examples of how the annual line goes and one example of how each founding sentence goes, so it is fluent where the history repeated itself and it is noise everywhere else. A model is as good as its counts are dense, and there is no part of it that knows the difference between the two.

The dial from the last section moves all of this, and the way to see it is the same seed run at several temperatures. Because a draw costs one number whatever the setting, every block below is drawing on the same numbers in the same order.

$ go run ./cmd/guess -mode heat -entries 3 -limit 60
guess: 3 entries at each temperature, a table of 256 merges, seed 83 on stream 23, at temperatures 5.00,1.00,0.30 and at the likeliest token every time

  T=5.00
    year 79 hobbs standing in The Hollow, 1274: 236 hobbs standing in The Hollow, 18783 born and ...
    year 52: 235 hobbs standing in The Hollow, 1881 gone
    Pelast malive. Nodieen one of them is aps gree is ple of the ground fore of them is agak afou...
  T=1.00
    year 6: 12 hobbs standing in The Hollow, 62 born and 1753 gone
    year 126 gone
    year 45: 238 hobbs standing in The Hollow, 1912 born and 1732 gone
  T=0.30
    year 58: 234 hobbs standing in The Hollow, 188 born and 1732 gone
    year 10: 236 hobbs standing in The Hollow, 1643 born and 138 gone
    year 48: 234 hobbs standing in The Hollow, 188 born and 1748 gone
  the likeliest token every time
    year 101010101010101010101010101010101010101010101010101010101010
    year 101010101010101010101010101010101010101010101010101010101010
    year 101010101010101010101010101010101010101010101010101010101010

  every block above starts from the same seed on the same stream,
  and a draw costs one number at every temperature, so the numbers
  landing on these tokens are the same numbers in all four blocks

Four settings, one seed, and a clean progression. At 5.00 the rare continuations get too much of the line and the entries wander, the third one into the founding-prose noise. At 1.00 the counts are used as counted. At 0.30 the entries come out tight and orderly, all three of them clean yearly lines, because the row's favourite is taking most of the line and the odd exits are being starved. The reader who wants entries that look right turns the dial down, and pays for it in a way the last block makes unmissable.

A block of ten lines is an anecdote, though, and the claim being made is not an anecdote. Turn it into a measurement: write two hundred entries and hold every one of them against the history they were counted from. The bench works out what a real annual entry looks like from the chronicle itself, by taking one and turning its digit runs into holes, and then checks the arithmetic that every real one keeps.

▣ Build · stage 6 — two hundred entries, held against the history
// cmd/guess/show.go
// annual is the sentence this valley writes at the end of every year,
// worked out from the chronicle rather than typed in: the digit runs
// of a real entry become holes and everything between them stays put.
// Four holes in this order: the year, the count standing, the number
// born and the number gone.
func annual(lines []exemplars.Line) (*regexp.Regexp, string) {
	var from string
	for _, l := range lines {
		if l.Kind == "count" {
			from = l.Text
			break
		}
	}
$ go run ./cmd/guess -mode check
guess: 200 entries, held against the chronicle, a table of 256 merges, seed 83 on stream 23, temperature 1.00

  the sentence this valley writes every year, taken off the chronicle
    year N: N hobbs standing in The Hollow, N born and N gone
    entries that match it                      80 of 91

  the arithmetic every one of those entries keeps
    standing = founded + born - gone
    founded, worked out from the first of them    29
    entries it holds for                       80 of 80

  now the same two tests on what the table wrote
  the first 8 of its entries that came out as exactly that sentence
      n  in the chronicle  the arithmetic  the entry
      1  no                no              year 6: 12 hobbs standing in The Hollow, 62 born and 1753 gone
      3  no                no              year 45: 238 hobbs standing in The Hollow, 1912 born and 1732 gone
     13  no                no              year 61: 237 hobbs standing in The Hollow, 1904 born and 1655 gone
     20  no                no              year 58: 234 hobbs standing in The Hollow, 188 born and 1626 gone
     26  no                no              year 239: 239 hobbs standing in The Hollow, 1927 born and 1427 gone
     34  no                no              year 33: 238 hobbs standing in The Hollow, 1784 born and 552 gone
     35  no                no              year 49: 235 hobbs standing in The Hollow, 18942 born and 1544 gone
     50  no                yes             year 8: 238 hobbs standing in The Hollow, 1962 born and 1753 gone

  entries written                             200
  of those, entries the chronicle holds          0
  of those, exactly the yearly sentence         22
  and of those 22, the arithmetic works           3

The middle block is the part that makes the rest of it a test and not an opinion. Every yearly entry the world has ever written keeps one identity: the count standing is the founding population plus everything born minus everything gone. The bench does not know that number; it works out the 29 from the first annual line and then checks it against all eighty, and gets eighty. So there is a rule the real history obeys without exception, and it costs three subtractions to apply to anything else.

Twenty-two of two hundred came out as exactly the sentence this valley writes at the end of a year. Not one of the two hundred is a line the chronicle holds. And of the twenty-two, three keep the identity, which means nineteen of them are entries a reader could catch with arithmetic they can do in their head.

Then there is entry 50, and it is the whole chapter in one line. year 8: 238 hobbs standing in The Hollow, 1962 born and 1753 gone is well formed, it is in register, and 29 plus 1,962 minus 1,753 is 238, so it passes the only consistency check this world has. It is still false, and the way it is false can be read straight off the chronicle. In year 8 there were 105 hobbs standing. Everything after the colon in that entry is year 75's line to the last digit: 238 standing, 1,962 born and 1,753 gone. The table wrote a real body and put a different year in front of it, and the identity holds precisely because the body is real. A check over three of the four numbers cannot see a fourth number that does not belong with them. The entry is not wrong because the model made an error. Nothing in the model was consulted about whether it was true, because there is nothing in the model that could be: the model is 1,168 counts of which token followed which, and a count of an adjacency has no opinion about the world at all.

That is the mechanism, and it has to be stated without any hedging: a made-up fact is not a malfunction of a system like this. It is the system working exactly as built, on a distribution that was never a distribution over true things and was only ever a distribution over what tended to follow what. Everything that makes the output convincing, the register, the punctuation, the plausible magnitudes, comes from the counts. Nothing that would make it true has been anywhere near it.

⚠ Worked failure — the temperature turned all the way down

The last section left an obvious lever unpulled. If a low temperature makes the entries come out cleaner, and the noise is the rare continuations getting a stretch of the line they do not deserve, then take the sampling out. Always take the commonest continuation. The model is being asked for its best guess and now it is being made to give it, and the output should be the most chronicle-like thing this table can produce.

$ go run ./cmd/guess -mode loop -limit 40
guess: one token followed to the next until it repeats, a table of 256 merges, seed 83 on stream 23, the likeliest token every time

  the walk
    step  token  stands for
       0     10  "\n"
       1    328  "year 1"
       2     48  "0"
       3     49  "1"
       4     48  "0"   already stood on at step 2

  the walk repeats from step 2, and the loop is 2 tokens long
  what it says over and over               "01"

  what the writing mode does with it, at a limit of 40 tokens
    year 1010101010101010101010101010101010101010
    it stopped on the entry break                no

Four steps in and it is finished. From the entry break, seven openings were seen eleven times each, they tie, and the tie-break takes the lowest-numbered token, which is year 1. Then the walk goes to 0, then to 1, then back to 0, which it stood on two steps ago. It never leaves, and it cannot, and the entry runs to the limit because the only token that ends an entry is the break and the break is not what either member of the pair leads to.

The obvious reading of the middle two steps is that 0 is what usually follows year 1 in a history of eighty years, ten of which are numbered in the teens. Ask the chain instead of guessing.

$ go run ./cmd/guess -mode row -from 328
guess: one token's row of counts, and the same row as shares, a table of 256 merges, temperature 1.00

  the token the row belongs to
    token 328, 6 bytes, "year 1"

  what followed it, how often, and what that is as a share
       to  count   share  running  stands for
       48      1  0.0909   0.0909  "0"
       49      1  0.0909   0.1818  "1"
       50      1  0.0909   0.2727  "2"
       51      1  0.0909   0.3636  "3"
       52      1  0.0909   0.4545  "4"
       53      1  0.0909   0.5455  "5"
       54      1  0.0909   0.6364  "6"
       56      1  0.0909   0.7273  "8"
       57      1  0.0909   0.8182  "9"
      362      1  0.0909   0.9091  ": 1"
      421      1  0.0909   1.0000  "7: 23"

  continuations it has                         11
  times the token was followed at all          11
  the shares add to                        1.0000

Eleven continuations and every count is 1. Nothing here is likelier than anything else: the years 10 to 19 contribute one entry each, the year 1 entry contributes its colon, and the merge table folded two of them into longer tokens on the way past. 0 comes first because 48 is the lowest number in the column, and that is the entire reason. The row after 0 is eighteen continuations all seen once, and the row after 1 is fourteen continuations all seen once, so the same thing happens twice more. The loop is not this model's favourite phrase. It is the sort order of a slice, promoted to a decision by a picker that was told never to draw.

That is what the flat-row count at the top of the page was measuring. Two hundred and fifteen of the 289 rows in this chain hold nothing but equal counts, so on three quarters of the model there is no commonest continuation to take, and an instruction to take the commonest one resolves to whatever the tie-break put first.

The ending is guaranteed for a reason that does not mention this corpus at all. A walk that always takes the first entry of a row is a function: one token in, one token out, the same answer every time it is asked. Applying a function to its own answer over and over, on a set of at most 512 tokens, cannot produce more than 512 distinct tokens before it stands on one it has already stood on, and from that moment the sequence is a cycle it repeats for ever. The pigeonhole is the proof. A test in the package asserts it from every starting token in the chain instead of from the one this page shows.

Now the part that makes this the same lesson as the last section instead of a separate curiosity. Both of these things are properties of the picker and neither is a property of the model. The counts did not change between the two runs, and the block above proves it: the row after year 1 holds eleven continuations at 0.0909 apiece, at that temperature and at every other, because no power separates counts that are equal. What changed is that one setting threw away ten of those eleven, and the moment the picker stopped drawing, the whole system stopped being able to produce anything it had not already produced. The variety that lets the table write a plausible entry about a year that never happened is the same variety that lets it write an entry at all. Turn it off to stop the invention and the output stops.

The honest reading of the pair of failures is therefore not that one setting is right and the other is wrong. It is that a distribution over what tended to follow what has no setting at which it becomes a distribution over what is true, and choosing a temperature is choosing where on a line between noise and a loop you would like to sit.

Why model and picker stay separate

Take the chronicle out of it and the arrangement generalises to every system of this kind, including the ones with billions of numbers in them instead of 1,168. Something produces one number per token in the vocabulary. Those numbers are turned into shares of one by a softmax, after a division by a temperature. And a separate piece of code, which has no access to anything except the shares, returns a token. The first stage is the model and it is fixed the moment it stops being counted or trained. The second stage is a setting, it is changed by a flag, and it accounts for a surprising fraction of what people attribute to the model.

The counting model here differs from the ones the rest of this volume is about in exactly two ways, and it is useful to name both so that nothing on this page gets over-read. It reads one token of context where they read thousands, and its numbers come from adding one rather than from a training run. Neither difference touches anything the page demonstrated. Next-token prediction, the distribution, the temperature, the sampled draw, the fluent falsehood and the greedy loop are all present at a vocabulary of 512 and a context of one, which is the reason the small one comes first: everything it does can be checked by hand, and none of it goes away when the numbers get bigger.

The verification story is the same one this book has told since a valley first grew a plant, and it is the last thing on the page that needs saying. Every number quoted here came out of ordinary Go over small integers with an explicit seed. The merge table is determined by the corpus and the merge count. The rows are determined by the table and the tie-break. The shares are determined by the rows and the temperature. The draws are determined by the seed and the stream number, and a draw costs one number whatever else is set. So the two hundred entries in the check run are the same two hundred entries on any machine that runs it, including the one about year 8 that passes the arithmetic and did not happen, and a reader who gets different text has found a bug rather than a different roll.

▣ Build · stage 7 — nine sentences off this page, pinned
$ go test ./internal/lang/ -run 'SharesAtOneAreTheCountsThemselves|ATemperatureRaisesEveryCountToOneOverIt|EverySharesRowAddsToOne|ADrawCostsOneNumberAtEveryTemperature|TheSameSeedWritesTheSameTokens|TheLikeliestTokenEveryTimeEndsInALoop|ACountedPairIsAnAdjacencyAndNothingElse|AChainRefusesWhatItCannotHaveCounted|ATemperatureOfZeroIsNotATemperature' -v
=== RUN   TestSharesAtOneAreTheCountsThemselves
    guess_test.go:52: 40 rows, every share equal to its own count over the row's total
--- PASS: TestSharesAtOneAreTheCountsThemselves (0.00s)
=== RUN   TestATemperatureRaisesEveryCountToOneOverIt
--- PASS: TestATemperatureRaisesEveryCountToOneOverIt (0.00s)
=== RUN   TestEverySharesRowAddsToOne
--- PASS: TestEverySharesRowAddsToOne (0.00s)
=== RUN   TestADrawCostsOneNumberAtEveryTemperature
    guess_test.go:143: 200 draws at four temperatures, and the generator ends in one state
--- PASS: TestADrawCostsOneNumberAtEveryTemperature (0.00s)
=== RUN   TestTheSameSeedWritesTheSameTokens
--- PASS: TestTheSameSeedWritesTheSameTokens (0.00s)
=== RUN   TestTheLikeliestTokenEveryTimeEndsInALoop
    guess_test.go:211: 40 starting tokens, 40 of them walk into a loop and none of them walks for ever
--- PASS: TestTheLikeliestTokenEveryTimeEndsInALoop (0.00s)
=== RUN   TestACountedPairIsAnAdjacencyAndNothingElse
--- PASS: TestACountedPairIsAnAdjacencyAndNothingElse (0.00s)
=== RUN   TestAChainRefusesWhatItCannotHaveCounted
    guess_test.go:248: counting: lang: token 3 of 3 is 291, and the vocabulary holds 291
    guess_test.go:253: asking: lang: no token 291 in a chain over a vocabulary of 291
--- PASS: TestAChainRefusesWhatItCannotHaveCounted (0.00s)
=== RUN   TestATemperatureOfZeroIsNotATemperature
    guess_test.go:264: shares: lang: a temperature divides every score, so it has to be above zero, not 0
--- PASS: TestATemperatureOfZeroIsNotATemperature (0.00s)
PASS
ok  	theworld/internal/lang	0.009s

The one to look at is the fourth. It runs two hundred draws four times over, at temperatures 0, 0.2, 1 and 5, and then asks the generator itself what state it is in afterwards. All four answers are the same twenty bytes, which is the only way to prove the fixed cost rather than assert it: a generator is the one witness that can say how much of a stream was spent. The sixth walks greedily from every token in the chain that has a continuation and finds a repeat in every one of them, so the loop in the failure box above is a property of the method and not a quirk of where that walk started.

What this page did not build, listed so nothing later has to work it out. There is no stopping rule beyond a marker token and a limit, and the fragments in the write run are what a system without one produces. There is nothing that refuses a token because it was used a moment ago, which is the family of settings sold as penalties and which this chain would benefit from and does not have. There is no way to hand it any context beyond the token it is standing on. And there is no gradient here, no backward pass, no loss and no learning rate: the model was counted, not fitted, and every number in it can be recovered by anybody who has the corpus and a piece of paper long enough.

What is left standing is small and it is the last thing this world builds for itself out of nothing. There is a package that can count adjacencies over any list of tokens, hand back a row of counts as a distribution at a temperature anybody chooses, draw from it against a numbered stream, and repeat until a marker comes up. It has a stream number of its own in this world's register, 23, which nothing in the valley draws from and no snapshot ever holds. And it produced, at temperature 1 and seed 83, two hundred entries about a valley, not one of which the valley wrote.

✓ Checkpoint — counts, shares and a picker
  • Why the row after token 10 totals 90 when the chronicle holds 91 entries, and what the eleven-apiece counts of year 1 through year 7 are counting.
  • Why taking the log of a count and then pushing it through a softmax gives the count back at temperature 1, and what the detour buys at every other temperature.
  • What number the count 2 becomes at a temperature of 0.30, and why the four counts of 1 in the same row do not move at any temperature at all.
  • Why Draw takes its number off the stream before it looks at the row, and what would go wrong across two runs of one seed if it did not.
  • Why entry 50 of the check run passes the identity that all eighty real entries keep and is still not something that happened.
  • Why always taking the commonest continuation has to end in a cycle, in an argument that does not mention this corpus.
⚡ Exercises — try first, then reveal
Exercise 1 — find the temperature that stops the invention. Turning the dial down makes entries come out cleaner. Find the temperature at which the check run stops producing entries that are not in the chronicle, and say what you found instead.

The check mode takes the temperature on a flag, so this is four runs and no code:

go run ./cmd/guess -mode check -temp 0.60 | tail -5
go run ./cmd/guess -mode check -temp 0.30 | tail -5
go run ./cmd/guess -mode check -temp 0.10 | tail -5
go run ./cmd/guess -mode check -temp 0.02 | tail -5

There is no such temperature, and the way the two counts refuse to move is the answer. Exactly the yearly sentence goes 22, 23, 23, 24, 24 across a temperature falling from 1 to 0.02, and entries the chronicle holds stays at 0 the whole way down. Fifty times sharper and almost nothing happens, which is not what the dial did to the single row in the listing mode and wants explaining.

The explanation is the line in -mode counts reading rows a temperature cannot change. A temperature raises every count in a row to the same power, and a row whose counts are all equal is still all equal at every power there is. Of the 289 rows in this chain, 73 have a single continuation and another 142 have several continuations that were each seen exactly the same number of times, so 215 of 289 are rows the dial cannot touch. On a corpus of 7,123 bytes most of what was counted was counted once, and a setting that decides how hard to lean on the counts has nothing to lean on. Two runs to make beside it: -mode write -temp 0.02 -entries 6, where the entries are still varied and still wrong, and -mode row -temp 0.02, where a row that does have a favourite collapses onto it completely.

Exercise 2 — give the model a second token of memory. The chain counts one token followed by one token. Count pairs of tokens followed by one token instead, and say what it fixes and what it does not.

Copy guess.go to a scratch file and key the tally on two ids instead of one, which is a two-line change: make the map key a struct{ A, B int } and walk the corpus in threes. Then write from it and compare. The run-on entries mostly stop, because the token 1771 arrived at from standing in The Hollow, is a different situation from the same token arrived at from born and , and the pair keeps them apart. The invention does not stop at all: the entries get better formed and stay untrue, and a few of them become verbatim copies of real chronicle lines, which is worse than it sounds. Count the rows while you are there, because the numbers say why nobody does this past two. The one-token chain has 289 rows holding 1,168 numbers between them. The two-token chain has 1,168 rows, one for every continuation the first one found, holding 1,371 numbers, and 1,052 of those rows have exactly one continuation in them. It is nearly all table and nearly no choice, which is what running out of corpus looks like from the inside: the context got longer, and the count behind every decision fell to one.

Exercise 3 — make the check catch entry 50. One of the twenty-two well-formed entries passes the identity the real chronicle keeps. Add a second test to the check mode that catches it, and then find an entry your new test misses too.

The identity uses three of the four numbers and ignores the year, so the obvious second test is the one that uses it: the chronicle already holds an entry for every year from 1 to 80, so look the year up and compare all three of the other figures against the real ones. In showCheck the map of real entries by year is already built for you. Entry 50 fails that immediately, because year 8 stood at 105 and not 238. Then run it over a larger sample with -sample 2000 and look at what still gets through: entries whose year is above 80, which no lookup can refute because the world has not lived that long, and entries whose year appears twice in the run with different figures each time. The general lesson is the one to take away. Every test you can add is a test against something you already know, and the entries that survive are the ones that make claims about the parts of the world nobody wrote down.