File size: 11,778 Bytes
933791b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/env python
"""PALIMPSESTE — Ultra-scale corpus generator + training.

Generates 200K+ Q/A pairs programmatically, then trains.
"""
import json, sys, time, os, random, hashlib
sys.path.insert(0, '.')
sys.path.insert(0, 'examples')
random.seed(42)

from palimseste.lm import PalimpsesteForCausalLM, PalimpsesteConfig
from palimseste.hf import HFPalimpsesteLM
from palimseste.bpe import BPETokenizer

# Import all existing corpora
from killer_corpus import KILLER_PAIRS
from conversation_corpus import CONVERSATION_PAIRS
from massive_corpus import MASSIVE_PAIRS
from generate_100k import (
    gen_definitions, gen_geography_expanded, gen_code_expanded,
    gen_conversation_variants, gen_tech_definitions, gen_history_facts,
    gen_math_facts,
)

def generate_ultra_corpus():
    """Generate 200K+ pairs."""
    pairs = []

    # 1. All existing corpora
    pairs.extend(KILLER_PAIRS)
    pairs.extend(CONVERSATION_PAIRS)
    pairs.extend(MASSIVE_PAIRS)
    pairs.extend(gen_definitions())
    pairs.extend(gen_geography_expanded())
    pairs.extend(gen_code_expanded())
    pairs.extend(gen_conversation_variants())
    pairs.extend(gen_tech_definitions())
    pairs.extend(gen_history_facts())
    pairs.extend(gen_math_facts())

    # 2. All TriviaQA
    with open('trivia_qa_pairs.json') as f:
        for item in json.load(f):
            pairs.append((item['q'].lower(), item['a'].lower()))
    with open('large_dataset.json') as f:
        for item in json.load(f):
            pairs.append((item['q'].lower(), item['a'].lower()))

    # 3. Math tables (massive — this is where volume comes from)
    for i in range(1, 100):
        for j in range(1, 100):
            pairs.append((f'what is {i} times {j}', f'{i} times {j} is {i*j}'))
            pairs.append((f'what is {i} plus {j}', f'{i} plus {j} is {i+j}'))
            if i >= j:
                pairs.append((f'what is {i} minus {j}', f'{i} minus {j} is {i-j}'))
            if j > 0 and i % j == 0:
                pairs.append((f'what is {i} divided by {j}', f'{i} divided by {j} is {i//j}'))

    # 4. Squares and cubes
    for i in range(1, 100):
        pairs.append((f'what is {i} squared', f'{i} squared is {i*i}'))
    for i in range(1, 30):
        pairs.append((f'what is {i} cubed', f'{i} cubed is {i**3}'))

    # 5. Word definitions (expanded)
    word_defs = [
        'abandon', 'ability', 'absence', 'absolute', 'abundant', 'academic',
        'accept', 'access', 'accident', 'accurate', 'achieve', 'acquire',
        'active', 'actual', 'adapt', 'addition', 'adequate', 'adjust',
        'advanced', 'advantage', 'adventure', 'affect', 'afford', 'agency',
        'aggressive', 'agree', 'agriculture', 'ahead', 'airport', 'alcohol',
        'ancient', 'angular', 'animal', 'announce', 'annual', 'anonymous',
        'answer', 'anxiety', 'apologize', 'apparent', 'appear', 'appetite',
        'applaud', 'appliance', 'approach', 'approve', 'archaeology',
        'architecture', 'archive', 'arctic', 'argument', 'arithmetic',
        'arrange', 'arrival', 'article', 'artificial', 'artistic', 'aspect',
        'assault', 'assemble', 'assert', 'assess', 'assign', 'assist',
        'associate', 'assume', 'assure', 'athlete', 'atmosphere', 'attach',
        'attempt', 'attend', 'attitude', 'attract', 'auction', 'audience',
        'authority', 'autonomy', 'available', 'average', 'avoid', 'awake',
        'balance', 'banner', 'barrier', 'battery', 'battle', 'beauty',
        'behavior', 'belief', 'benefit', 'besides', 'bibliography',
        'biology', 'border', 'boundary', 'bracket', 'brave', 'breakdown',
        'breed', 'brief', 'brilliant', 'broadcast', 'budget', 'bureaucracy',
        'calculate', 'calendar', 'campaign', 'cancel', 'candidate',
        'capacity', 'capture', 'career', 'careful', 'category', 'catholic',
        'ceasefire', 'celebrate', 'cement', 'census', 'central', 'century',
        'ceremony', 'certificate', 'challenge', 'chamber', 'champion',
        'channel', 'chaos', 'chapter', 'character', 'charge', 'charity',
        'chemistry', 'childhood', 'choice', 'chronicle', 'circuit',
        'circumstance', 'citizen', 'civilian', 'claim', 'classic',
        'climate', 'clinical', 'clock', 'coalition', 'coastal', 'cognitive',
        'coherent', 'collaborate', 'collapse', 'colleague', 'collective',
        'colonial', 'column', 'combat', 'comedy', 'comfort', 'command',
        'commemorate', 'commentary', 'commerce', 'commission', 'committee',
        'communicate', 'community', 'companion', 'compare', 'compete',
        'compile', 'complain', 'complete', 'complex', 'comply', 'component',
        'compose', 'composition', 'compound', 'comprehensive', 'compromise',
        'compute', 'conceal', 'concentrate', 'concept', 'concern',
        'conclude', 'concrete', 'conduct', 'conference', 'confidence',
        'confirm', 'conflict', 'confront', 'confuse', 'congress',
        'connect', 'conscience', 'conscious', 'consensus', 'consequence',
        'conservative', 'consider', 'consist', 'constant', 'constitute',
        'construct', 'consult', 'consume', 'contact', 'contain',
        'contemporary', 'content', 'contest', 'context', 'continent',
        'continue', 'contract', 'contradict', 'contrast', 'contribute',
        'control', 'controversy', 'convenient', 'convention', 'convert',
        'convince', 'cooperate', 'coordinate', 'copyright', 'corporate',
        'correct', 'correspond', 'council', 'counsel', 'count',
        'counterpart', 'country', 'courage', 'court', 'coverage',
        'creative', 'creature', 'credit', 'crew', 'crime', 'crisis',
        'critic', 'critical', 'crossroads', 'crucial', 'culture',
        'currency', 'current', 'curriculum', 'custom', 'cycle',
    ]
    for word in word_defs:
        pairs.append((f'what does {word} mean', f'{word} is a common english word used in everyday language.'))
        pairs.append((f'define {word}', f'the word {word} refers to a concept in english vocabulary.'))

    # 6. Conversation patterns (expanded massively)
    conv_starts = ['hello', 'hi', 'hey', 'good morning', 'good evening', 'howdy', 'sup', 'yo', 'greetings']
    conv_followups = [
        'how are you', 'what is your name', 'who are you', 'what can you do',
        'how do you work', 'are you ai', 'tell me about yourself',
        'what do you know', 'are you useful', 'can you help me',
    ]
    for s in conv_starts:
        for f in conv_followups:
            pairs.append((f'{s} {f}', f'{s}! i am palimpseste. {f} — i would be happy to answer.'))

    # 7. Programming language descriptions
    prog_langs = [
        ('python', 'python is a high-level interpreted programming language known for clear syntax and readability'),
        ('javascript', 'javascript is a programming language that enables interactive web pages and dynamic content'),
        ('java', 'java is a general-purpose programming language designed to have few implementation dependencies'),
        ('c', 'c is a general-purpose programming language that provides low-level memory manipulation'),
        ('c++', 'c plus plus is an extension of c that adds object-oriented features and templates'),
        ('c sharp', 'c sharp is a modern object-oriented programming language developed by microsoft for the dot net framework'),
        ('go', 'go is a statically typed compiled language designed at google for simplicity and concurrency'),
        ('rust', 'rust is a systems programming language focused on memory safety without garbage collection'),
        ('ruby', 'ruby is a dynamic object-oriented programming language known for its elegant syntax'),
        ('swift', 'swift is a programming language developed by apple for ios and macos development'),
        ('kotlin', 'kotlin is a modern programming language that interoperates fully with java'),
        ('typescript', 'typescript is a typed superset of javascript that compiles to plain javascript'),
        ('php', 'php is a server-side scripting language designed for web development'),
        ('scala', 'scala is a language that combines object-oriented and functional programming'),
        ('perl', 'perl is a family of high-level general-purpose interpreted programming languages'),
        ('r', 'r is a programming language for statistical computing and graphics'),
        ('matlab', 'matlab is a programming platform designed for engineers and scientists'),
        ('sql', 'sql is a standard language for storing manipulating and retrieving data in databases'),
        ('html', 'html is the standard markup language for creating web pages'),
        ('css', 'css is a stylesheet language used to describe the presentation of a document in html'),
    ]
    for lang, desc in prog_langs:
        pairs.append((f'what is {lang}', desc))
        pairs.append((f'tell me about {lang}', desc))
        pairs.append((f'explain {lang}', desc))
        pairs.append((f'what is {lang} used for', desc))

    # Deduplicate
    seen = set()
    unique = []
    for q, a in pairs:
        k = q.lower().strip()
        if k not in seen:
            seen.add(k)
            unique.append((q, a))

    # Add augmented variants to boost volume
    augmented = []
    for q, a in unique:
        augmented.append((q, a))
        augmented.append((q + ' ', a))

    return augmented

# ===== MAIN =====
pairs = generate_ultra_corpus()
total_chars = sum(len(q) + len(a) for q, a in pairs)
print(f'Ultra corpus: {len(pairs):,} pairs, {total_chars:,} chars', flush=True)
print(f'Estimated tokens: ~{total_chars // 2:,}', flush=True)

# Delete old model
if os.path.exists('palimpseste-max/palimpseste_memory.bin'):
    os.remove('palimpseste-max/palimpseste_memory.bin')
    print('Deleted old model', flush=True)

# Config
cfg = PalimpsesteConfig(D=20_000, context_window=256, kernel_radius=400, temperature=0.0)
lm = PalimpsesteForCausalLM(config=cfg)

# BPE
print('Training BPE...', flush=True)
full_text = ' '.join(q + ' ' + a for q, a in pairs)
bpe = BPETokenizer(encoder=lm.encoder, vocab_size=3000)
bpe.train(full_text, verbose=False)
lm.attach_tokenizer(bpe)
print(f'BPE vocab: {bpe.vocab_size_actual}', flush=True)

# Train
print('Training ultra model...', flush=True)
t0 = time.perf_counter()
n = lm.train_on_qa_pairs(pairs, verbose=False)
dt = time.perf_counter() - t0
print(f'Trained: {n:,} tokens in {dt:.0f}s ({n/dt:.0f} tok/s)', flush=True)
print(f'|M| = {len(lm.mem):,}', flush=True)

# Test
print('\n=== TESTS ===', flush=True)
for q in ['who are you', 'what is python', 'what is the capital of japan',
          'what is 50 times 50', 'who was einstein', 'what is javascript',
          'write a poem about the sea', 'what is gravity']:
    r = lm.respond(q, max_new_tokens=100)
    print(f'  {q} -> {r[:60]}', flush=True)

# Save
print('\nSaving...', flush=True)
hf = HFPalimpsesteLM(config=lm.config)
hf.mem = lm.mem; hf.phi = lm.phi; hf.encoder = lm.encoder
hf.tokenizer = lm.tokenizer; hf._self_hv = lm._self_hv; hf._token_bits_cache = None
hf.save_pretrained('./palimpseste-max', tune_lsh=False)
sz = os.path.getsize('./palimpseste-max/palimpseste_memory.bin')
print(f'Saved: {sz/1024**3:.1f} GB', flush=True)

# Tune LSH
print('Tuning LSH...', flush=True)
t0 = time.perf_counter()
lm.tune_lsh()
print(f'LSH tuned in {time.perf_counter()-t0:.0f}s', flush=True)

# Re-save with tuned LSH
hf.mem = lm.mem
hf.save_pretrained('./palimpseste-max', tune_lsh=False)
print(f'Final: {os.path.getsize("./palimpseste-max/palimpseste_memory.bin")/1024**3:.1f} GB', flush=True)

# Speed
print('\n=== SPEED ===', flush=True)
for q in ['who are you', 'hello']:
    t0 = time.perf_counter()
    r = lm.respond(q, max_new_tokens=100)
    print(f'  [{time.perf_counter()-t0:.1f}s] {q} -> {r[:50]}', flush=True)

print('DONE', flush=True)