
LlamaConfig rejects explicit head_dim when hidden_size is not divisible by num_attention_heads
快速结论:当使用 LlamaConfig 并显式传递 head_dim 参数,但 hidden_size 不能被 num_attention_heads 整除时,配置验证会错误地拒绝该配置。优先排查 head_dim 是否已显式设置,并注意确保配置代码位于最新版 transformers 或已应用修复补丁。
问题场景
用户在使用 transformers 库(版本 5.8.0.dev0 或当前 main 分支,提交 a0fb01c)通过 LlamaConfig 初始化模型时触发。典型场景是自定义脚本中为 LlamaForCausalLM 传递自定义 head_dim 参数,但 hidden_size 与 num_attention_heads 不满足整除关系。
报错原文
ValueError: The hidden_size (512) is not a multiple of the number of attention heads (9).
原因分析
问题出在 configuration_llama.py 中的 validate_architecture 方法。该方法无条件地检查 hidden_size 是否被 num_attention_heads 整除,即使 head_dim 已被用户显式提供,且 LlamaAttention 中的建模代码已正确使用 num_attention_heads * head_dim 确定投影维度。该验证在 __init__ 后通过 @strict 装饰器运行,此时 head_dim 已被赋值为默认值(hidden_size // num_attention_heads),因此无法通过简单的 head_dim is not None 判断用户意图。根本原因:验证逻辑没有区分 head_dim 是用户显式传入还是派生出的默认值。
环境排查
transformers版本:确认当前版本是否为5.8.0.dev0或更早版本(main分支 commita0fb01c前)。- Python 版本:与报错无直接关联,但可确认版本号(本 Issue 中为
3.13.12)。 - 依赖版本:确保
torch、transformers已正确安装。
解决步骤
- 确认报错原因:运行以下代码验证是否复现:
from transformers import LlamaConfig, LlamaForCausalLM
config = LlamaConfig(
vocab_size=99,
hidden_size=512,
intermediate_size=1024,
num_hidden_layers=1,
num_attention_heads=9,
num_key_value_heads=1,
head_dim=56,
)
model = LlamaForCausalLM(config) # 应触发验证错误
- 临时绕过方案:确保
hidden_size能被num_attention_heads整除(例如将num_attention_heads改为8或16)。此方法不适用于需要非标准head_dim的场景。 - 推荐修复(手动补丁):修改
configuration_llama.py文件中的__post_init__和validate_architecture方法。在__post_init__中添加一个私有属性_head_dim_was_explicit以记录head_dim是否为显式传入,然后在验证逻辑中检查该标志。具体修改如下(来源于 Issue 讨论的修复方案):
在__post_init__中添加:
def __post_init__(self):
self._head_dim_was_explicit = self.head_dim is not None # 捕获用户意图
if self.head_dim is None:
self.head_dim = self.hidden_size // self.num_attention_heads
在 validate_architecture 中修改验证条件:
def validate_architecture(self):
if self.hidden_size % self.num_attention_heads != 0 and not self._head_dim_was_explicit:
raise ValueError(...)
- 检查 JSON 保存/加载兼容性:修复中的
_head_dim_was_explicit是私有属性(非 dataclass 字段),不会被序列化到 JSON。从 JSON 加载配置时,head_dim会存在于 JSON 中,因此__post_init__会正确把_head_dim_was_explicit设置为True,不会产生回环问题。 - 等待合并 PR:该修复已有开发者在其分支上实现并通过本地测试,建议关注上游仓库的合并进度。在没有正式发布前,可优先尝试上述手动补丁。
验证方法
应用修复或绕过方案后,运行上述复现代码,应不再触发 ValueError,模型能正常构建。可进一步测试保存配置并重新加载:
config.save_pretrained("./test_config")
loaded_config = LlamaConfig.from_pretrained("./test_config")
model = LlamaForCausalLM(loaded_config) # 应正常加载
也可运行 tests/models/llama/test_modeling_llama.py 中的测试套件确认无回归(预期除少量无关的 FSDP/TP 失败外,全部通过)。



