from typing import Optional, Tuple, Union, Callable, List, Any, Generator from einops import rearrange import torch import torch.nn.functional as F import torch.utils.checkpoint from torch.nn import CrossEntropyLoss from torch import nn import torch.nn.init as init # for 0.1B n_layer = 3 n_embd = 256 D_DECAY_LORA = 64 D_AAA_LORA = 64 D_MV_LORA = 32 D_GATE_LORA = 128 dim_att = n_embd dim_ffn = n_embd * 4 vocab_size = 32 # DTYPE = torch.bfloat16 DTYPE = torch.float32 # better head_size_a = 64 # don't change HS = head_size_a class RWKV_Tmix_x070(nn.Module): def __init__(self, layer_id): super().__init__() self.layer_id = layer_id self.head_size = head_size_a self.n_head = dim_att // self.head_size assert dim_att % self.n_head == 0 H = self.n_head HS = self.head_size C = n_embd self.x_r = nn.Parameter(torch.empty(1, 1, C)) self.x_w = nn.Parameter(torch.empty(1, 1, C)) self.x_k = nn.Parameter(torch.empty(1, 1, C)) self.x_v = nn.Parameter(torch.empty(1, 1, C)) self.x_a = nn.Parameter(torch.empty(1, 1, C)) self.x_g = nn.Parameter(torch.empty(1, 1, C)) self.w0 = nn.Parameter(torch.empty(1, 1, C)) self.w1 = nn.Parameter(torch.empty(C, D_DECAY_LORA)) self.w2 = nn.Parameter(torch.empty(D_DECAY_LORA, C)) self.a0 = nn.Parameter(torch.empty(1, 1, C)) self.a1 = nn.Parameter(torch.empty(C, D_AAA_LORA)) self.a2 = nn.Parameter(torch.empty(D_AAA_LORA, C)) self.v0 = nn.Parameter(torch.empty(1, 1, C)) self.v1 = nn.Parameter(torch.empty(C, D_MV_LORA)) self.v2 = nn.Parameter(torch.empty(D_MV_LORA, C)) self.g1 = nn.Parameter(torch.empty(C, D_GATE_LORA)) self.g2 = nn.Parameter(torch.empty(D_GATE_LORA, C)) self.k_k = nn.Parameter(torch.empty(1, 1, C)) self.k_a = nn.Parameter(torch.empty(1, 1, C)) self.r_k = nn.Parameter(torch.empty(H, HS)) self.receptance = nn.Linear(C, C, bias=False) self.key = nn.Linear(C, C, bias=False) self.value = nn.Linear(C, C, bias=False) self.output = nn.Linear(C, C, bias=False) self.ln_x = nn.GroupNorm(H, C, eps=64e-5) # !!! notice eps value !!! def forward(self, x, v_first): B, T, C = x.size() # seq_len H = self.n_head # 12 xx = torch.zeros_like(x) # time_shift [1, seq_len, 768] -> [1, seq_len, 768] xx[:, 0, :] = -x[:, 0, :] xx[:, 1:, :] = x[:, :-1, :] - x[:, 1:, :] xr = x + xx * self.x_r # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] xw = x + xx * self.x_w # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] xk = x + xx * self.x_k # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] xv = x + xx * self.x_v # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] xa = x + xx * self.x_a # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] xg = x + xx * self.x_g # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] r = self.receptance(xr) # Linear [1, seq_len, 768] -> [1, seq_len, 768] xw = torch.tanh(xw @ self.w1) # -> [1, seq_len, 64] xw = xw @ self.w2 + self.w0 # -> [1, seq_len, 768] xw = -F.softplus(-xw) # 函数的输出范围为 [0,∞) w = xw - 0.5 # -> [1, seq_len, 768] k = self.key(xk) # Linear [1, seq_len, 768] -> [1, seq_len, 768] v = self.value(xv) # Linear [1, seq_len, 768] -> [1, seq_len, 768] if self.layer_id == 0: v_first = v # store the v of the first layer else: xv = (xv @ self.v1) @ self.v2 xv = xv + self.v0 xv = torch.sigmoid(xv) v = v + (v_first - v) * xv # add value residual # -> [1, seq_len, 768] xa = (xa @ self.a1) @ self.a2 xa = xa + self.a0 a = torch.sigmoid(xa) # -> [1, seq_len, 768] xg = xg @ self.g1 xg = torch.sigmoid(xg) g = xg @ self.g2 # -> [1, seq_len, 768] kk = k * self.k_k # [1, seq_len, 768] * [1, 1, 768] -> [1, seq_len, 768] kk = F.normalize(kk.view(B, T, H, -1), dim=-1, p=2.0).view(B, T, C) # -> [1, seq_len, 768] k = k * (1 + (a - 1) * self.k_a) # -> [1, seq_len, 768] # start op a_op = -kk b_op = kk * a B, T, C = r.size() # 768 H = C // HS # 12 r_op = r.view(B, T, H, HS, 1).float() # -> [1, seq_len, 12, 64, 1] k_op = k.view(B, T, H, 1, HS).float() # -> [1, seq_len, 12, 1, 64] v_op = v.view(B, T, H, HS, 1).float() # -> [1, seq_len, 12, 64, 1] a_op = a_op.view(B, T, H, HS, 1).float() # -> [1, seq_len, 12, 64, 1] b_op = b_op.view(B, T, H, 1, HS).float() # -> [1, seq_len, 12, 1, 64] w_op = w.view(B, T, H, HS).float() w_op = torch.exp(-torch.exp(w_op)) # -> [1, seq_len, 12, 64] w_op = w_op.view(B, T, H, 1, HS) # -> [1, seq_len, 12, 1, 64] out = torch.zeros((B, T, H, HS), device=r_op.device, dtype=torch.float) # -> [1, seq_len, 12, 64] state = torch.zeros((B, H, HS, HS), device=r_op.device, dtype=torch.float) # -> [1, seq_len, 12, 64] for t in range(T): rr_op = r_op[:, t, :] # [1, seq_len, 12, 64, 1] -> [1, 12, 64, 1] kk_op = k_op[:, t, :] # [1, seq_len, 12, 1, 64] -> [1, 12, 1, 64] vv_op = v_op[:, t, :] # [1, seq_len, 12, 64, 1] -> [1, 12, 64, 1] aa_op = a_op[:, t, :] # [1, seq_len, 12, 64, 1] -> [1, 12, 64, 1] bb_op = b_op[:, t, :] # [1, seq_len, 12, 1, 64] -> [1, 12, 1, 64] ww_op = w_op[:, t, :] # [1, seq_len, 12, 64] -> [1, 12, 1, 64] state = state * ww_op + state @ aa_op @ bb_op + vv_op @ kk_op # -> [1, 12, 64, 64] out[:, t, :] = (state @ rr_op).view(B, H, HS) # -> [1, seq_len, 12, 64] x = out.view(B, T, C).to(dtype=DTYPE) # -> [1, seq_len, 768] # end op x = self.ln_x(x.view(B * T, C)).view(B, T, C) # -> [1, seq_len, 768] xx = r.view(B, T, H, -1) * k.view(B, T, H, -1) # -> [1, seq_len, 12, 64] xx = xx * self.r_k # -> [1, seq_len, 12, 64] xx = xx.sum(dim=-1, keepdim=True) # -> [1, seq_len, 12, 1] xx = xx * v.view(B, T, H, -1) # [1, seq_len, 12, 1] x [1, seq_len, 12, 64] -> [1, seq_len, 12, 64] xx = xx.view(B, T, C) # -> [1, seq_len, 768] x = x + xx # -> [1, seq_len, 768] x = self.output(x * g) # Linear -> [1, seq_len, 768] return x, v_first class RWKV_CMix_x070(nn.Module): def __init__(self, layer_id): super().__init__() self.layer_id = layer_id # with torch.no_grad(): self.x_k = nn.Parameter(torch.empty(1, 1, n_embd)) self.key = nn.Linear(n_embd, dim_ffn, bias=False) self.value = nn.Linear(dim_ffn, n_embd, bias=False) def forward(self, x): shift = torch.zeros_like(x) shift[:, 1:, :] = x[:, :-1, :] xx = shift - x # time_shift -> [1, seq_len, 768] k = x + xx * self.x_k # -> [1, seq_len, 768] k = torch.relu(self.key(k)) ** 2 # Linear -> [1, seq_len, 768] return self.value(k) # Linear -> [1, seq_len, 768] class Block(nn.Module): def __init__(self, layer_id): super().__init__() self.layer_id = layer_id self.ln0 = nn.LayerNorm(n_embd) # only used in block 0, should be fused with emb self.ln1 = nn.LayerNorm(n_embd) self.ln2 = nn.LayerNorm(n_embd) self.att = RWKV_Tmix_x070(layer_id) self.ffn = RWKV_CMix_x070(layer_id) def forward(self, x, v_first): if self.layer_id == 0: x = self.ln0(x) # LayerNorm -> [1, seq_len, 768] normal at dim 768 * γ + β ln = self.ln1(x) # LayerNorm -> [1, seq_len, 768] normal at dim 768 * γ + β xx, v_first = self.att(ln, v_first) # [1, seq_len, 768] -> [1, seq_len, 768] x = x + xx # [1, seq_len, 768] -> [1, seq_len, 768] x = x + self.ffn(self.ln2(x)) # [1, seq_len, 768] -> [1, seq_len, 768] return x, v_first class RWKV(nn.Module): def __init__(self): super().__init__() self.emb = nn.Embedding(vocab_size, n_embd) self.blocks = nn.ModuleList([Block(i) for i in range(n_layer)]) self.ln_out = nn.LayerNorm(n_embd) self.head = nn.Linear(n_embd, vocab_size, bias=False) def forward(self, idx): x = self.emb(idx) # [1, seq_len] -> [1, seq_len, 768] v_first = torch.empty_like(x) # -> [1, seq_len, 768] for block in self.blocks: x, v_first = block(x, v_first) x = self.ln_out(x) # [1, seq_len, 768] -> [1, seq_len, 768] x = self.head(x) # [1, seq_len, 768] -> [1, seq_len, 65536] return x class RWKVLMHeadModel(nn.Module): def __init__(self, config): super().__init__() self.config = config self.rwkv = RWKV() self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False) self.hook_attention = None for name, param in self.rwkv.named_parameters(): init.normal_(param.data) def forward( self, input_ids: Optional[torch.LongTensor] = None, labels: Optional[torch.LongTensor] = None, token_type_ids: Optional[torch.LongTensor] = None, **kwargs, ): lm_logits = self.rwkv(input_ids) loss = None if labels is not None: labels = labels.to(lm_logits.device) shift_labels = labels[..., 1:].contiguous().view(-1) shift_logits = lm_logits[..., :-1, :].contiguous() shift_logits = shift_logits.view(-1, shift_logits.size(-1)) mask = shift_labels < self.config.vocab_size shift_labels = shift_labels[mask] shift_logits = shift_logits[mask] loss = CrossEntropyLoss()(shift_logits, shift_labels) return lm_logits, loss