1import numpy as np2import pandas as pd3from tokenizer import Tokenizer45defload_corpus(path,column,max_rows) ->str:6 df = pd.read_csv(path, nrows=max_rows)78if column notin df.columns:9raiseValueError(f"no column {column!r}, the file has {list(df.columns)}")1011 texts = df[column].dropna().astype(str).str.strip()12return"\n".join(texts)+"\n"1314# BPE tokenizer is called to turn this into a 1D array of integers15defencode_corpus(text:str,tok: Tokenizer) -> np.ndarray:16return np.array(tok.encode(text), dtype=np.int64)1718# this cuts id stream so 0.1 keeps first 90% for training and last 10% for testing19defsplit_ids(ids,val_fraction):20 cut =int((1- val_fraction) *len(ids))21return ids[:cut], ids[cut:]2223# A language model learns to predict the next token. We slide a window of length T along the ids. The input is the window, and the target is the same window shifted one token to the left.24defmake_windows(ids,seq_len,stride=1):25iflen(ids)<= seq_len:26raiseValueError(f"need more than seq_len={seq_len} tokens, got {len(ids)}")2728 starts = np.arange(0, len(ids) - seq_len, stride)29 rows = starts[:,None]+ np.arange(seq_len)3031 inputs = pd.DataFrame(ids[rows])32 targets = pd.DataFrame(ids[rows +1])33return inputs, targets3435# Training doesn’t use all windows at once, because that would make each update slow. It also doesn’t use one window at a time, because that would make updates noisy. This function hands out batch_size windows at a time.36defiterate_batches(inputs,targets,batch_size,rng,shuffle=True):37 order = inputs.index38if shuffle:39 order = inputs.sample(frac=1, random_state=rng).index4041for i inrange(0, len(order), batch_size):42 rows = order[i : i + batch_size]43yield inputs.loc[rows].to_numpy(), targets.loc[rows].to_numpy()