    def qkv_proj(
            self,
            q,
            q_size,
            k,
            k_size,
            v,
            v_size,
            batch_size,
            chan_size,
    ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
        """
        Args:
            q(torch.Tensor):
                q tensor.
            q_size(List[int]):
                q tensor size.
            k(torch.Tensor):
                k tensor.
            k_size(List[int]):
                k tensor size.
            v(torch.Tensor):
                v tensor.
            v_size(List[int]):
                v tensor size.
            batch_size(List[int]):
                batch size.
            chan_size(List[int]):
                channel size.
        """
        q = (
            self.q(q)
                .reshape(batch_size, q_size, self.num_heads, chan_size // self.num_heads)
                .permute(0, 2, 1, 3)
        )
        k = (
            self.k(k)
                .reshape(batch_size, k_size, self.num_heads, chan_size // self.num_heads)
                .permute(0, 2, 1, 3)
        )
        v = (
            self.v(v)
                .reshape(batch_size, v_size, self.num_heads, chan_size // self.num_heads)
                .permute(0, 2, 1, 3)
        )
        return q, k, v
Args:
q(torch.Tensor):
q tensor.
q_size(List[int]):
q tensor size.
k(torch.Tensor):
k tensor.
k_size(List[int]):
k tensor size.
v(torch.Tensor):
v tensor.
v_size(List[int]):
v tensor size.
batch_size(List[int]):
batch size.
chan_size(List[int]):
channel size.
towhee/models/layers/multi_scale_attention.py