elya-snes / train /sample.py
elyanlabs's picture
Source snapshot of github.com/Scottcjn/elya-snes@544ccea (part 4)
8e0f023 verified
Raw History Blame Contribute Delete
2.73 kB
#!/usr/bin/env python3
"""Generate text with host/ref.py - the exact-integer reference the ROM is
verified against - and detokenise it.
Greedy argmax with ties to the lowest index, exactly as rom/nn.s does, so the
strings printed here are the strings the cartridge produces. The ROM free-runs
from a single seed token; --prompt is a host-only convenience for inspecting
conditional behaviour and is labelled as such wherever it is used.
"""
import argparse
import json
import os
import sys
import numpy as np
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(HERE, "..", "host"))
import ref
def load_vocab(path="data/vocab.json"):
v = json.load(open(path))
return v["vocab"], v["base"]
def detok(ids, vocab):
return "".join(vocab[i] for i in ids)
def encode(text, vocab, base):
"""Longest-match tokenisation against the 64-symbol vocabulary."""
order = sorted(range(len(vocab)), key=lambda i: -len(vocab[i]))
out, i = [], 0
while i < len(text):
for t in order:
s = vocab[t]
if s and text.startswith(s, i):
out.append(t)
i += len(s)
break
else:
i += 1
return out
def run(model, prompt_ids, nsteps):
"""Teacher-force the prompt, then free-run greedy. Returns the full id list."""
r = ref.Runner(model)
ids = list(prompt_ids)
cur = ids[0]
p = 0
while p < nsteps:
nxt = r.step(cur, p)
p += 1
if p < len(ids):
cur = ids[p] # still inside the prompt
else:
ids.append(nxt)
cur = nxt
return ids
def main():
ap = argparse.ArgumentParser()
ap.add_argument("npz")
ap.add_argument("--vocab", default="data/vocab.json")
ap.add_argument("--seeds", default=None, help="comma separated seed token ids")
ap.add_argument("--prompt", default=None, help="host-only text prompt")
ap.add_argument("--n", type=int, default=ref.T - 1)
ap.add_argument("--survey", action="store_true", help="all 64 seed tokens")
a = ap.parse_args()
vocab, base = load_vocab(a.vocab)
m = ref.Model.from_npz(a.npz)
if a.prompt is not None:
ids = encode(a.prompt, vocab, base)
out = run(m, ids, a.n)
print("prompt (host-only) %-20r -> %r"
% (detok(ids, vocab), detok(out, vocab)))
return 0
seeds = (list(range(len(vocab))) if a.survey else
[int(s) for s in (a.seeds or "1").split(",")])
for s in seeds:
out = run(m, [s], a.n)
print("seed %2d %-8r -> %r" % (s, vocab[s], detok(out, vocab)))
return 0
if __name__ == "__main__":
sys.exit(main())