| import torch |
| import torch.nn |
|
|
| def scaled_dot_product_attention(query, key, value, att_mask=None, is_causal=False, scale=None, enable_gqa=False): |
| |
| |
| |
|
|
| L, S = query.size(-2), key.size(-2) |
| if scale is None: |
| scale = query.size(-1) ** -0.5 |
|
|
| attn_bias = torch.zeros((L, S), dtype=query.dtype, device=query.device) |
| if is_causal: |
| assert att_mask is None |
| att_mask = (query.new_ones(L, S).tril(diagonal=0) == 1) |
|
|
| attn_bias.masked_fill_(~att_mask, float('-inf')) |
|
|
| if enable_gqa: |
| key = key.repeat_interleave(query.size(-3)// key.size(-3), dim=-3) |
| value = value.repeat_interleave(query.size(-3) // value.size(-3), dim=-3) |
| |
| attn_weights = query @ key.transpose(-2, -1) * scale |
| attn_weights += attn_bias |
| attn_weights = torch.nn.softmax(attn_weights, dim=-1) |
| attn_weights = attn_weights @ value |
| return attn_weights |
|
|
| def group_query_attention(x, Wq, Wk, Wv, att_mask = None, is_causal = False, enable_gqa=False): |
| query = torch.einsum('bld,dh->blh', x, Wq) |
| key = torch.einsum('bld,dh->blh', x, Wk) |
| value = torch.einsum('bld,dh->blh', x, Wv) |
|
|
| query = query.view(B, Q_L, H_q, -1).transpose(1, 2) |
| key = key.view(B, K_L, H_kv, -1).transpose(1, 2) |
| value = value.view(B, V_L, H_vv, -1).transpose(1, 2) |
|
|
| query, key = rotary_emb(query, key) |
|
|
| attention = scaled_dot_product_attention( |
| query, key, value, |
| att_mask=att_mask, |
| is_causal=is_causal, |
| scale=None, |
| enable_gqa=enable_gqa |
| ) |
| |
|
|
|
|
|
|
| |
|
|