outlines 0.15 用 regex 约束生成中文姓名,正则写成中文字符区间加 2 到 8 次重复,transformers 后端输出空串,换 vLLM 后端直接抛 No valid tokens found。
一开始怀疑是「FSM 没有预编译,运行时反复构建」,查了一圈,方向不对。
真正麻烦的地方在于,几个原因的现象几乎一样。正则的字符区间和 BPE 词表边界对不齐。少数情况下是所选后端不支持 Unicode 区间约束。
不容易想到的是,中文在词表里被拆成多个字节 token。
先把约束换成 JSON schema 里的枚举或长度
python smoke_outlines.py --schema person.json
随后用 outlines-core 预编译正则再复用
python compile_regex.py --pattern '[一-龥]{2,8}' --out fsm.pkl
接着换 xgrammar 后端跑同一约束做对照
python smoke_outlines.py --backend xgrammar --schema person.json
末了在输出后加一次长度和字符集校验
python validate_name.py --min 2 --max 8
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
别只看报错消失,验证要多做一步。模型能稳定输出 2 到 8 个汉字,空串比例为 0,换后端后结果一致。
补一句。正则约束在 token 级别执行,不是字符级别,涉及中文、emoji 这类多字节字符时,用结构化 schema 限制字段长度更可靠。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
