sweedworks

← all sources

precompute_merges.py

Computes the figures on /vocabulary/

66 lines. This is the file the build actually runs, copied verbatim at build time.

"""Generate merges/data.json — every figure on /merges/, computed not written."""

import json
import os

import bpe
from cjsload import Reference
from corpora import BERRIES

OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..",
                   "vocabulary", "data.json")

N_MERGES = 30

# Words that show the three outcomes: learned whole, learned in pieces, unseen.
PROBES = [" strawberry", "strawberry", " blackberry", "strawberries", " kiwi"]

# Where the assembly of " strawberry" visibly changes.
CHECKPOINTS = [0, 1, 2, 3, 4, 16, 17]


def main():
    trained = bpe.train(BERRIES, N_MERGES)
    merges = trained["merges"]
    real = Reference("o200k_base")

    data = {
        "corpus": BERRIES,
        "corpus_chars": len(BERRIES),
        "corpus_words": len(bpe.pretokenize(BERRIES)),
        "corpus_unique": len(set(bpe.pretokenize(BERRIES))),
        "alphabet": trained["alphabet"],
        "steps": trained["steps"],
        "vocab_size": trained["vocab_size"],
        "n_merges": len(merges),
        "checkpoints": [
            {"after": n, "symbols": bpe.encode(" strawberry", merges[:n])}
            for n in CHECKPOINTS
        ],
        "probes": [
            {
                "text": p,
                "toy": bpe.encode(p, merges),
                "real": [t["text"] for t in real.tokens(p)],
            }
            for p in PROBES
        ],
    }

    with open(OUT, "w", encoding="utf-8") as fh:
        json.dump(data, fh, ensure_ascii=False, indent=1)

    print(f"wrote {os.path.relpath(OUT, os.path.dirname(OUT))}")
    print(f"  corpus: {data['corpus_chars']} chars, {data['corpus_words']} words, "
          f"{data['corpus_unique']} unique")
    print(f"  {data['n_merges']} merges, alphabet {len(data['alphabet'])}, "
          f"vocab {data['vocab_size']}")
    print("  first merges: " +
          " ".join(f"{s['token']!r}" for s in data["steps"][:5]))
    for p in data["probes"]:
        print(f"  {p['text']!r:>16}  toy {len(p['toy']):>2}  real {len(p['real']):>2}")


if __name__ == "__main__":
    main()