层1/T1: SFTConfig dataclass 与构造校验(docs/02 §4)
- ars_opd/configs.py: 冻结 dataclass,机器路径无默认强制显式传入; 双预算/enable_thinking/lr 差异均按 §7 规范标注 - __post_init__ 构造即校验,防"completion 预算为零→loss 恒 0"静默空训练 - tests/test_configs.py: 6 个校验测试 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
"""SFTConfig 的构造校验测试(层 1 / T1)。
|
||||
|
||||
只测"配置错误必须在构造时炸"这一条约定;参数语义本身没有逻辑可测。
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
|
||||
import pytest
|
||||
|
||||
from ars_opd.configs import SFTConfig
|
||||
|
||||
|
||||
def make(**overrides):
|
||||
"""最小合法配置;单测只关心被覆盖的那个字段。"""
|
||||
base = dict(dataset_path="dummy.parquet", output_dir="/tmp/dummy")
|
||||
base.update(overrides)
|
||||
return SFTConfig(**base)
|
||||
|
||||
|
||||
def test_合法配置可构造():
|
||||
cfg = make()
|
||||
assert cfg.max_length > cfg.max_prompt_length
|
||||
|
||||
|
||||
def test_prompt预算吞掉总预算时报错():
|
||||
# 这是最危险的静默失败:completion 预算为 0 → labels 全 -100 → loss 恒 0
|
||||
with pytest.raises(ValueError, match="max_prompt_length"):
|
||||
make(max_prompt_length=4096, max_length=4096)
|
||||
|
||||
|
||||
def test_非法学习率报错():
|
||||
with pytest.raises(ValueError, match="learning_rate"):
|
||||
make(learning_rate=0.0)
|
||||
|
||||
|
||||
def test_非法子集大小报错():
|
||||
with pytest.raises(ValueError, match="subset_size"):
|
||||
make(subset_size=0)
|
||||
|
||||
|
||||
def test_非法max_steps报错():
|
||||
with pytest.raises(ValueError, match="max_steps"):
|
||||
make(max_steps=0)
|
||||
|
||||
|
||||
def test_配置冻结不可变():
|
||||
cfg = make()
|
||||
with pytest.raises(dataclasses.FrozenInstanceError):
|
||||
cfg.learning_rate = 1e-3
|
||||
Reference in New Issue
Block a user