rwkv7-g1h-7.2b-hf / configuration_rwkv7.py
Hakureirm's picture
Retire the optional kernels, carry the tokenizer, drop dead config keys
7376b3f verified
Raw History Blame Contribute Delete
7.35 kB
# Copyright 2026 The RWKV team and The HuggingFace Inc. team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""RWKV-7 (Goose) model configuration."""
from huggingface_hub.dataclasses import strict
from transformers.configuration_utils import PreTrainedConfig
from transformers.utils import auto_docstring
@auto_docstring(
custom_intro="""
Configuration for [`Rwkv7Model`], an all-recurrent (attention-free) RWKV-7 "Goose"
model. Instantiating with the defaults yields the ~0.1B RWKV-7 configuration.
Parameter names follow the upstream RWKV reference implementation
(`BlinkDL/RWKV-LM`) rather than a renamed variant, so converting a native
`.pth` checkpoint is close to a rename-free copy.
""",
checkpoint="Hakureirm/rwkv7-168m-pile-hf",
)
@strict
class Rwkv7Config(PreTrainedConfig):
r"""
vocab_size (`int`, *optional*, defaults to 65536):
Vocabulary size (RWKV "world" tokenizer).
hidden_size (`int`, *optional*, defaults to 768):
Model width `C`.
num_hidden_layers (`int`, *optional*, defaults to 12):
Number of blocks.
head_dim (`int`, *optional*, defaults to 64):
Width of one WKV head. `hidden_size` must be divisible by it.
num_heads (`int`, *optional*, defaults to 12):
Number of WKV heads; must equal `hidden_size // head_dim`.
decay_low_rank_dim (`int`, *optional*, defaults to 64):
Rank of the decay (`w`) LoRA.
a_low_rank_dim (`int`, *optional*, defaults to 64):
Rank of the in-context-learning-rate (`a`) LoRA.
v_low_rank_dim (`int`, *optional*, defaults to 32):
Rank of the value-residual (`v`) LoRA. Unused on layer 0, which
*produces* `v_first` instead of mixing towards it.
gate_low_rank_dim (`int`, *optional*, defaults to 128):
Rank of the output-gate (`g`) LoRA.
intermediate_size (`int`, *optional*):
Channel-mix inner width. Defaults to `4 * hidden_size`.
norm_eps (`float`, *optional*, defaults to 1e-05):
Epsilon of every LayerNorm/GroupNorm in the model.
norm_bias (`bool`, *optional*, defaults to `True`):
Whether the norms carry a bias.
max_position_embeddings (`int`, *optional*, defaults to 8192):
Training context length. RWKV is recurrent and not bounded by it at
inference; it only sizes generation defaults.
tie_word_embeddings (`bool`, *optional*, defaults to `False`):
Whether to tie the input embedding and the LM head.
use_cache (`bool`, *optional*, defaults to `True`):
Whether to return the recurrent state.
use_deep_embed (`bool`, *optional*, defaults to `False`):
Enable the RWKV-8 "DeepEmbed" hook: a per-layer, per-token vector that
channelwise-modulates the channel-mix. The table is deliberately NOT a
model weight. It is meant to live in RAM/SSD and be prefetched per
token, which is the whole point of the design (VRAM savings), so it is
passed to the forward as `deep_embeds` instead. No RWKV-7 checkpoint
carries one; this is an extension point, off by default.
wkv_state_dtype (`str`, *optional*, defaults to `"float32"`):
Precision the recurrent WKV state is carried and accumulated in,
independently of the activation dtype. The recurrence is unrolled over
the whole sequence, so a narrow state drifts; `"float32"` with fp16
activations is the combination the reference implementation uses.
`"float16"`/`"bfloat16"` trade that for a smaller state.
wkv_implementation (`str`, *optional*, defaults to `"eager"`):
Which WKV recurrence to use, by name, from
`models.rwkv7.modeling_rwkv7.RWKV7_WKV_FUNCTIONS`. `"eager"` is the
portable PyTorch path: the sequential step when decoding, the
chunk-parallel form otherwise, and per-segment when a packed batch is
passed. Register an entry in that mapping to plug in a fused or varlen
kernel without forking the model.
bos_token_id (`int`, *optional*, defaults to 0):
Beginning-of-sequence id. The RWKV world tokenizer has no dedicated BOS
token and the reference implementation prepends nothing, so this exists to
satisfy `GenerationMixin` rather than to be emitted.
eos_token_id (`int`, *optional*, defaults to 0):
End-of-sequence id, id 0 in the RWKV world vocabulary.
pad_token_id (`int`, *optional*, defaults to 0):
Padding id, the same id 0. Set deliberately rather than left `None`:
`generate` needs one to pad a batch, and without it a batched call either
raised or fell back to the eos id with a warning on every step.
```python
>>> from transformers import Rwkv7Config, Rwkv7Model
>>> configuration = Rwkv7Config()
>>> model = Rwkv7Model(configuration)
>>> configuration = model.config
```"""
model_type = "rwkv7"
keys_to_ignore_at_inference = ["past_key_values"]
vocab_size: int = 65536
hidden_size: int = 768
num_hidden_layers: int = 12
head_dim: int = 64
num_heads: int = 12
decay_low_rank_dim: int = 64
a_low_rank_dim: int = 64
v_low_rank_dim: int = 32
gate_low_rank_dim: int = 128
# `None` rather than a number: a literal default is correct for the default
# `hidden_size` and silently wrong for every other one, so a config built as
# `Rwkv7Config(hidden_size=4096, num_heads=64)` would come back with a channel-mix
# four times narrower than the architecture it names. `__post_init__` resolves it,
# and the resolved value is written to `config.json` either way.
intermediate_size: int | None = None
norm_eps: float = 1e-5
norm_bias: bool = True
max_position_embeddings: int = 8192
tie_word_embeddings: bool = False
use_cache: bool = True
use_deep_embed: bool = False
wkv_state_dtype: str = "float32"
wkv_implementation: str = "eager"
bos_token_id: int | None = 0
eos_token_id: int | None = 0
pad_token_id: int | None = 0
def __post_init__(self, **kwargs):
if self.intermediate_size is None:
self.intermediate_size = 4 * self.hidden_size
if self.wkv_state_dtype not in ("float32", "float16", "bfloat16"):
raise ValueError(f"wkv_state_dtype must be float32/float16/bfloat16, got {self.wkv_state_dtype}")
if self.hidden_size % self.head_dim != 0:
raise ValueError(f"hidden_size {self.hidden_size} must be divisible by head_dim {self.head_dim}")
if self.num_heads != self.hidden_size // self.head_dim:
raise ValueError(
f"num_heads must be hidden_size // head_dim = {self.hidden_size // self.head_dim}, "
f"got {self.num_heads}"
)
super().__post_init__(**kwargs)
__all__ = ["Rwkv7Config"]