Files
wehub-resource-sync 770d92cb1f
Lint / lint (push) Waiting to run
Windows CI / Windows (push) Waiting to run
Build Docs / Deploy Docs (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:23:58 +08:00

94 lines
3.6 KiB
Python

"""Attention KV cache modeling."""
import json
from typing import Any, Dict, List, Literal, Optional, Union # noqa: UP035
import numpy as np
from tvm import relax as rx
from tvm import tirx
from tvm.relax.frontend.nn.llm.kv_cache import PagedKVCache as TVMPagedKVCache
from tvm.relax.frontend.nn.llm.kv_cache import RopeMode
class PagedKVCache(TVMPagedKVCache):
"""The Paged KV Cache used in LLM batching for efficient attention computation."""
@staticmethod
def create_generic(
attn_kind: Union[Literal["mha", "mla"], List[Literal["mha", "mla", "mha_sliding"]]], # noqa: UP006
max_batch_size: tirx.Var,
max_total_seq_len: tirx.Var,
prefill_chunk_size: tirx.Var,
page_size: tirx.Var,
support_sliding_window: tirx.Var,
num_hidden_layers: int,
num_attention_heads: int,
num_key_value_heads: int,
qk_head_dim: int,
v_head_dim: int,
rope_mode: RopeMode,
rope_scale: int,
rope_theta: int,
dtype: str,
mla_original_qk_head_dim: int = 0,
mla_original_v_head_dim: int = 0,
rotary_dim: Optional[int] = None,
rope_scaling: Optional[Dict[str, Any]] = None, # noqa: UP006
rope_ext_factors: Optional[List[int]] = None, # noqa: UP006
layer_partition: Optional[List[int]] = None, # noqa: UP006
enable_disaggregation: bool = False,
name: str = "paged_kv_cache",
) -> "PagedKVCache":
"""The generic function of creating a multi-head attention PagedKVCache,
which will be rewritten by functions in compilation pipeline.
"""
if rotary_dim is None:
rotary_dim = qk_head_dim
if rope_scaling is None:
rope_scaling = {}
if layer_partition is None:
layer_partition = [0, num_hidden_layers]
if isinstance(attn_kind, List): # noqa: UP006
rx_attn_kind = [rx.StringImm(layer_kind) for layer_kind in attn_kind]
else:
rx_attn_kind = rx.StringImm(attn_kind)
return PagedKVCache(
_expr=rx.call_pure_packed(
"mlc.create_paged_kv_cache_generic",
rx_attn_kind,
rx.ShapeExpr(
[
max_batch_size,
max_total_seq_len,
prefill_chunk_size,
page_size,
support_sliding_window,
]
),
rx.ShapeExpr(layer_partition),
rx.prim_value(num_hidden_layers),
rx.prim_value(num_attention_heads),
rx.prim_value(num_key_value_heads),
rx.prim_value(qk_head_dim),
rx.prim_value(v_head_dim),
rx.prim_value(mla_original_qk_head_dim),
rx.prim_value(mla_original_v_head_dim),
rx.prim_value(rope_mode),
rx.prim_value(rope_scale),
rx.prim_value(rope_theta),
rx.StringImm(json.dumps(rope_scaling)),
(
rx.const(np.array(rope_ext_factors, "float32"))
if rope_ext_factors is not None
else rx.prim_value(0)
# NOTE: since relax does not have "Optional" type, we use prim_value(0)
# to represent "undefined".
),
rx.prim_value(rotary_dim),
rx.prim_value(int(enable_disaggregation)),
rx.DataTypeImm(dtype),
ty_args=rx.ObjectType(),
),
_name=name,
)