IAU-1 / model.py
BrodyMakezAI's picture
Update model.py
228f8cd verified
Raw History Blame Contribute Delete
3.26 kB
import math, torch
import torch.nn as nn, torch.nn.functional as F
T = 1024
N_LAYER = 24
N_HEAD = 12
N_EMBD = 768
VOCAB = 50304 # gpt2 vocab padded to a multiple of 64
class Block(nn.Module):
def __init__(s):
super().__init__()
s.ln1 = nn.LayerNorm(N_EMBD); s.ln2 = nn.LayerNorm(N_EMBD)
s.qkv = nn.Linear(N_EMBD, 3 * N_EMBD, bias=False)
s.proj = nn.Linear(N_EMBD, N_EMBD, bias=False)
s.fc = nn.Linear(N_EMBD, 4 * N_EMBD, bias=False)
s.out = nn.Linear(4 * N_EMBD, N_EMBD, bias=False)
def forward(s, x):
B, L, C = x.shape
q, k, v = s.qkv(s.ln1(x)).split(C, dim=2)
q, k, v = [t.view(B, L, N_HEAD, C // N_HEAD).transpose(1, 2) for t in (q, k, v)]
a = F.scaled_dot_product_attention(q, k, v, is_causal=True)
x = x + s.proj(a.transpose(1, 2).reshape(B, L, C))
return x + s.out(F.gelu(s.fc(s.ln2(x))))
class GPT(nn.Module):
def __init__(s):
super().__init__()
s.wte = nn.Embedding(VOCAB, N_EMBD)
s.wpe = nn.Embedding(T, N_EMBD)
s.blocks = nn.ModuleList([Block() for _ in range(N_LAYER)])
s.lnf = nn.LayerNorm(N_EMBD)
s.head = nn.Linear(N_EMBD, VOCAB, bias=False)
s.head.weight = s.wte.weight # tied
s.apply(s._init)
for n, p in s.named_parameters():
if n.endswith('proj.weight') or n.endswith('out.weight'):
nn.init.normal_(p, std=0.02 / math.sqrt(2 * N_LAYER))
def _init(s, m):
if isinstance(m, (nn.Linear, nn.Embedding)):
nn.init.normal_(m.weight, std=0.02)
def forward(s, idx):
x = s.wte(idx) + s.wpe(torch.arange(idx.size(1), device=idx.device))
for b in s.blocks: x = b(x)
return s.head(s.lnf(x))
def load_iau1(path='model.safetensors', device='cpu'):
from safetensors.torch import load_file
m = GPT()
# head.weight is tied to wte.weight, so it is not stored in the file
m.load_state_dict(load_file(path), strict=False)
return m.to(device).eval()
@torch.no_grad()
def generate(model, prompt, n=80, temp=0.8, top_k=50, rep_penalty=1.2, no_repeat_ngram=3):
import tiktoken
enc = tiktoken.get_encoding('gpt2')
dev = next(model.parameters()).device
idx = torch.tensor([enc.encode_ordinary(prompt)], device=dev)
for _ in range(n):
logits = model(idx[:, -T:])[:, -1, :].float()
if rep_penalty != 1.0: # push down tokens that already appeared
seen = torch.unique(idx[0])
l = logits[0, seen]
logits[0, seen] = torch.where(l > 0, l / rep_penalty, l * rep_penalty)
if no_repeat_ngram and no_repeat_ngram >= 2 and idx.size(1) >= no_repeat_ngram:
k = no_repeat_ngram
toks = idx[0].tolist()
prefix = toks[-(k - 1):]
banned = [toks[i + k - 1] for i in range(len(toks) - k + 1) if toks[i:i + k - 1] == prefix]
if banned: logits[0, banned] = -float('inf') # never repeat an exact n-gram
logits = logits / temp
v, _ = torch.topk(logits, top_k)
logits[logits < v[:, [-1]]] = -float('inf')
idx = torch.cat([idx, torch.multinomial(F.softmax(logits, -1), 1)], dim=1)
return enc.decode(idx[0].tolist())