chen459664's picture
Add files using upload-large-folder tool
11690a5 verified
Raw
History Blame Contribute Delete
10.2 kB
# Copyright (c) Meta Platforms, Inc. and affiliates.
# This software may be used and distributed according to the terms of the GNU General Public License version 3.
from typing import Optional, Tuple
from dataclasses import dataclass
import math
import torch
from torch import nn
import torch.nn.functional as F
import awq_inference_engine
from transformers.models.llama.modeling_llama import LlamaRotaryEmbedding
# from flash_attn.flash_attn_interface import flash_attn_unpadded_func
import tinychat.utils.constants
max_batch_size = tinychat.utils.constants.max_batch_size
global_max_seq_len = tinychat.utils.constants.max_seq_len
def gen_slopes(n_heads, alibi_bias_max=8):
_n_heads = 2 ** math.ceil(math.log2(n_heads))
m = torch.arange(1, _n_heads + 1, dtype=torch.float32)
m = m.mul(alibi_bias_max / _n_heads)
slopes = 1.0 / torch.pow(2, m)
if _n_heads != n_heads:
slopes = torch.concat([slopes[1::2], slopes[::2]])[:n_heads]
return slopes.view(1, n_heads, 1, 1)
def build_alibi_bias(
n_heads, seq_len, full=False, alibi_bias_max=8, dtype=torch.float32
):
alibi_bias = torch.arange(1 - seq_len, 1, dtype=torch.int32).view(1, 1, 1, seq_len)
if full:
alibi_bias = alibi_bias - torch.arange(1 - seq_len, 1, dtype=torch.int32).view(
1, 1, seq_len, 1
)
alibi_bias = alibi_bias.abs().mul(-1)
slopes = gen_slopes(n_heads, alibi_bias_max)
alibi_bias = alibi_bias * slopes
slopes = slopes.squeeze(0).squeeze(-1).squeeze(-1)
return slopes.to(dtype=dtype), alibi_bias.to(dtype=dtype)
def _cast_if_autocast_enabled(tensor):
if torch.is_autocast_enabled():
if tensor.device.type == "cuda":
dtype = torch.get_autocast_gpu_dtype()
elif tensor.device.type == "cpu":
dtype = torch.get_autocast_cpu_dtype()
else:
raise NotImplementedError()
return tensor.to(dtype=dtype)
return tensor
class LPLayerNorm(torch.nn.LayerNorm):
def __init__(self, normalized_shape, eps=1e-05, elementwise_affine=True):
super().__init__(
normalized_shape=normalized_shape,
eps=eps,
elementwise_affine=elementwise_affine,
)
def forward(self, x):
module_device = x.device
downcast_x = _cast_if_autocast_enabled(x)
downcast_weight = (
_cast_if_autocast_enabled(self.weight)
if self.weight is not None
else self.weight
)
downcast_bias = (
_cast_if_autocast_enabled(self.bias) if self.bias is not None else self.bias
)
with torch.autocast(enabled=False, device_type=module_device.type):
return torch.nn.functional.layer_norm(
downcast_x,
self.normalized_shape,
downcast_weight,
downcast_bias,
self.eps,
)
class SharedEmbedding(nn.Embedding):
def forward(self, input: torch.Tensor, unembed: bool = False) -> torch.Tensor:
if unembed:
return F.linear(input, self.weight)
return super().forward(input)
class MPTAttentionFused(nn.Module):
def __init__(self, args):
super().__init__()
self.args = args
self.n_local_heads = args.n_heads
self.head_dim = args.d_model // args.n_heads
args.max_seq_len = min(args.max_seq_len, global_max_seq_len)
self.Wqkv = nn.Linear(
args.d_model,
args.n_heads * self.head_dim * 3,
bias=False,
)
self.out_proj = nn.Linear(
args.n_heads * self.head_dim,
args.d_model,
bias=False,
)
# following fastertransformer definition
self.cache_v = (
torch.zeros(
(
max_batch_size,
self.n_local_heads,
args.max_seq_len,
self.head_dim,
)
)
.cuda()
.half()
) # added to half
# 8: pack 8 fp16 in FT, if fp32 then use 4
self.cache_k = (
torch.zeros(
(
max_batch_size,
self.n_local_heads,
self.head_dim // 8,
args.max_seq_len,
8,
)
)
.cuda()
.half()
) # added to half
alibi_slopes, alibi_bias = build_alibi_bias(
self.n_local_heads, args.max_seq_len
)
# TODO (Haotian): fix device
self.alibi_slopes = alibi_slopes.float().to("cuda:0")
self.alibi_bias = alibi_bias.to("cuda:0")
def forward(
self,
x: torch.Tensor,
start_pos: int,
mask: Optional[torch.Tensor],
):
bsz, seqlen, _ = x.shape
xqkv = self.Wqkv(x)
xqkv = xqkv.view(bsz, seqlen, -1, self.n_local_heads, self.head_dim)
xq = xqkv[:, :, 0]
xk = xqkv[:, :, 1]
xv = xqkv[:, :, 2]
if seqlen > 1:
xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
xk = xk.view(bsz, seqlen, self.n_local_heads, self.head_dim)
xv = xv.view(bsz, seqlen, self.n_local_heads, self.head_dim)
self.cache_k = self.cache_k.to(xq)
self.cache_v = self.cache_v.to(xq)
values_store = xv.transpose(2, 1)
keys_store = (
xk.reshape(bsz, seqlen, self.n_local_heads, self.head_dim // 8, 8)
.permute(0, 2, 3, 1, 4)
.contiguous()
)
self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
keys = xk
values = xv
xq = xq.transpose(1, 2)
keys = keys.transpose(1, 2)
values = values.transpose(1, 2)
scores = torch.matmul(xq, keys.transpose(2, 3)) / math.sqrt(self.head_dim)
scores += self.alibi_bias[..., :seqlen]
if mask is not None:
scores = scores + mask # (bs, n_local_heads, slen, cache_len + slen)
scores = F.softmax(scores.float(), dim=-1).type_as(xq)
output = torch.matmul(scores, values) # (bs, n_local_heads, slen, head_dim)
output = output.transpose(1, 2).contiguous().view(bsz, seqlen, -1)
else:
# xq = xq[:, 0, :, :]
# xk = xk[:, 0, :, :]
# xv = xv[:, 0, :, :]
xq = xq.view(bsz, self.n_local_heads, self.head_dim)
xk = xk.view(bsz, self.n_local_heads, self.head_dim)
xv = xv.view(bsz, self.n_local_heads, self.head_dim)
output = awq_inference_engine.single_query_attention(
xq,
xk,
xv,
self.cache_k,
self.cache_v,
None,
# with alibi embedding
self.alibi_slopes.float(),
start_pos,
# rotary embed dim = 0 => no rotary embedding
0,
10000,
1.0,
True,
)
output = output.reshape(bsz, 1, -1)
return self.out_proj(output)
class MPTMLP(nn.Module):
def __init__(self, d_model: int, expansion_ratio: int):
super().__init__()
self.up_proj = nn.Linear(d_model, expansion_ratio * d_model, bias=False)
self.act = nn.GELU(approximate="none")
self.down_proj = nn.Linear(expansion_ratio * d_model, d_model, bias=False)
self.down_proj._is_residual = True
def forward(self, x):
return self.down_proj(self.act(self.up_proj(x)))
class MPTBlock(nn.Module):
def __init__(self, layer_id: int, args):
super().__init__()
self.n_heads = args.n_heads
self.dim = args.d_model
self.head_dim = args.d_model // args.n_heads
self.attn = MPTAttentionFused(args)
self.ffn = MPTMLP(d_model=args.d_model, expansion_ratio=4)
self.layer_id = layer_id
self.norm_1 = LPLayerNorm(args.d_model, eps=1e-6)
self.norm_2 = LPLayerNorm(args.d_model, eps=1e-6)
def forward(
self,
x: torch.Tensor,
start_pos: int,
mask: Optional[torch.Tensor],
):
h = x + self.attn.forward(self.norm_1(x), start_pos, mask)
out = h + self.ffn.forward(self.norm_2(h))
return out
class Transformer(nn.Module):
def __init__(self, params):
super().__init__()
self.params = params
self.vocab_size = params.vocab_size
self.n_layers = params.n_layers
self.wte = SharedEmbedding(params.vocab_size, params.d_model)
self.blocks = torch.nn.ModuleList()
for layer_id in range(params.n_layers):
self.blocks.append(MPTBlock(layer_id, params))
self.norm_f = LPLayerNorm(params.d_model, eps=1e-6)
@torch.inference_mode()
def forward(self, tokens: torch.Tensor, start_pos: int):
_bsz, seqlen = tokens.shape
h = self.wte(tokens)
mask = None
if seqlen > 1:
mask = torch.full(
(1, 1, seqlen, seqlen), float("-inf"), device=tokens.device
)
mask = torch.triu(mask, diagonal=start_pos + 1).type_as(h)
for layer in self.blocks:
h = layer(h, start_pos, mask)
h = self.norm_f(h)
return h
class MPTForCausalLM(nn.Module):
def __init__(self, params):
super().__init__()
self.config = params
self.transformer = Transformer(params)
if params.no_bias:
for module in self.modules():
if hasattr(module, "bias") and isinstance(module.bias, nn.Parameter):
module.register_parameter("bias", None)
@torch.inference_mode()
def forward(self, tokens: torch.Tensor, start_pos: int):
h = self.transformer(tokens, start_pos)
output = self.transformer.wte(h, unembed=True) # only compute last logits
return output.float()