File size: 3,801 Bytes
ba41f77 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #!/usr/bin/env python
"""PALIMPSESTE — Train the killer model with BPE tokenizer.
BPE reduces tokens 5x → 5x fewer prediction errors → much better generation.
Combined with the killer knowledge corpus (quality over quantity).
"""
import json, sys, time, os
sys.path.insert(0, '.')
sys.path.insert(0, 'examples')
from palimseste.lm import PalimpsesteForCausalLM, PalimpsesteConfig
from palimseste.hf import HFPalimpsesteLM
from palimseste.bpe import BPETokenizer
from killer_corpus import get_killer_corpus
# Load data
pairs = list(get_killer_corpus())
# Also load trivia data for breadth
try:
with open('trivia_qa_pairs.json') as f:
trivia = json.load(f)
pairs.extend([(item['q'].lower(), item['a'].lower()) for item in trivia[:3000]])
print(f'Loaded {len(trivia[:3000])} trivia pairs', flush=True)
except FileNotFoundError:
pass
print(f'Total pairs: {len(pairs)}', flush=True)
# Config: ctx=256 for complete answers, temp=0.0 for greedy
cfg = PalimpsesteConfig(
D=20_000,
context_window=256,
kernel_radius=400,
kernel_min_weight=1e-6,
temperature=0.0,
)
print(f'Config: D={cfg.D} ctx={cfg.context_window} temp={cfg.temperature}', flush=True)
# Build model
lm = PalimpsesteForCausalLM(config=cfg)
# ================================================================
# BPE TOKENIZER — train once on the full corpus
# ================================================================
print('Training BPE tokenizer...', flush=True)
full_text = ' '.join(q + ' ' + a for q, a in pairs)
bpe = BPETokenizer(encoder=lm.encoder, vocab_size=2000)
bpe.train(full_text, verbose=False)
lm.attach_tokenizer(bpe)
print(f'BPE vocab: {bpe.vocab_size_actual} tokens', flush=True)
# Compare BPE vs char-level token count
sample = 'who are you'
char_ids = [ord(c) for c in sample] # rough char count
bpe_ids = bpe.encode(sample, add_bos=True, add_eos=True)
print(f'BPE reduction: "{sample}" = {len(sample)+2} chars → {len(bpe_ids)} BPE tokens '
f'({len(sample)/max(len(bpe_ids),1):.1f}x)', flush=True)
# ================================================================
# TRAIN with BPE
# ================================================================
print('Training with BPE...', flush=True)
t0 = time.perf_counter()
n_tokens = lm.train_on_qa_pairs(pairs, verbose=False)
dt = time.perf_counter() - t0
print(f'Trained: {n_tokens:,} tokens in {dt:.0f}s ({n_tokens/dt:.0f} tok/s)', flush=True)
print(f'|M| = {len(lm.mem):,} traces', flush=True)
# ================================================================
# TEST
# ================================================================
print('\n=== KILLER MODEL TESTS ===', flush=True)
tests = [
'who are you', 'hello', 'what is python', 'how do you learn',
'do you use a gpu', 'what is the capital of france',
'what can you do', 'are you conscious',
'what is a black hole', 'what is recursion',
'what is gravity', 'what is dna',
'how are you different from chatgpt', 'tell a joke',
]
for q in tests:
t0 = time.perf_counter()
r = lm.respond(q, max_new_tokens=200)
dt = time.perf_counter() - t0
print(f' [{dt:.1f}s] {q}', flush=True)
print(f' -> {r}', flush=True)
# ================================================================
# SAVE
# ================================================================
print('\nSaving killer model...', flush=True)
hf_lm = HFPalimpsesteLM(config=lm.config)
hf_lm.mem = lm.mem
hf_lm.phi = lm.phi
hf_lm.encoder = lm.encoder
hf_lm.tokenizer = lm.tokenizer
hf_lm._self_hv = lm._self_hv
hf_lm._token_bits_cache = None
hf_lm.save_pretrained('./palimpseste-max', tune_lsh=False)
sz = os.path.getsize('./palimpseste-max/palimpseste_memory.bin')
print(f'Saved: {sz/1024/1024:.0f} MB', flush=True)
print('DONE', flush=True)
|