llama.cpp b11103修复HunyuanOCR的DFlash投机解码支持
llama.cpp发布b11103构建,核心改动是让HunyuanOCR目标模型支持DFlash草稿模型:图像请求可以跑通,草稿接受率约 0.5,OCR输出与非投机运行逐字节一致。
AI解读:llama.cpp的b11103版本把DFlash投机解码接进了HunyuanOCR。此前在HunyuanOCR目标上加载DFlash草稿模型会在第一次构建计算图时就断言失败退出,因为Hunyuan系列没有像Qwen3那样暴露每层输入的残差流张量,草稿模型拿不到跨上下文所需的数据。修法是照搬Qwen3的做法,在层循环开头注册该张量。
用腾讯HunyuanOCR 1.5和它的DFlash草稿模型实测,图像请求已经能正常运行,草稿接受率约 0.5,OCR输出与非投机路径逐字节一致。也就是说,这次改动换来的是速度空间,而识别结果本身没有变化。
另一个修复针对模型转换环节:用HunYuan目标模型转换DFlash草稿此前会因属性错误直接中断,原因是词表处理代码被借用到了DFlashModel实例上,而其中调用了只有HunYuanModel才有的方法。现在词表辅助函数被改成模块级函数,并在借用期间切换配置,转换流程不再依赖实例类型。
需要说明的是,这些张量只有在投机解码启用对应层号时才会被读取,不挂草稿模型时行为没有变化;hunyuan-moe使用的是另一套计算图,本次未受影响。
llama.cpp发布b11103构建,合入的改动是让HunyuanOCR目标模型支持DFlash投机解码(PR #28890)。
此前,在HunyuanOCR目标模型上挂DFlash草稿模型会在第一次构建计算图时中止,报出断言:GGML_ASSERT(t_layer_inp[il] != nullptr && "layer input tensor is null")。原因是DFlash投机解码需要目标图暴露每一层的输入残差流(res->t_layer_inp[il]),草稿模型读取这些张量来构建它的跨上下文;Qwen3以及其他支持DFlash的目标模型都会注册这些张量,Hunyuan的计算图没有注册。
修复方式是在层循环开头注册该张量,做法与qwen3一致。该层输入是进入第il层的残差流,即第il-1层的输出,也就是草稿的target_layers元数据所指的对象(转换器写入的是target_layer_ids+1)。hunyuan-dense.cpp复用这套计算图,因此同样被覆盖;hunyuan-moe使用独立计算图,未受影响。
作者表示,这个向量只有投机实现启用那些层号时才会被读取,因此不挂草稿模型时没有行为变化。用tencent/HunyuanOCR 1.5及其DFlash草稿模型测试的结果是:图像请求现在可以运行,草稿接受率约 0.5,OCR输出与非投机运行逐字节一致。该提交由wendadawen共同完成。
模型转换环节的两处修复
同一PR还修复了用HunYuan目标模型转换DFlash草稿时的问题,此前转换会以两种方式失败。
第一种:DFlashModel.set_vocab() 通过以草稿实例做无绑定调用来复用目标类的词表处理,但HunYuanModel.set_vocab() 调用了self._fix_special_tokens(),这个方法只存在于HunYuanModel,于是转换总是以AttributeError: 'DFlashModel' object has no attribute '_fix_special_tokens' 中止。改法是把词表辅助函数改成接收模型作为显式参数的模块级函数,使其不再依赖实例必须是HunYuanModel;这些函数没有其他调用方,两次id查找被合并进 _fix_special_tokens()。
第二种:被委托的调用运行时self.dir_model指向目标模型,却保留草稿模型的self.hparams,导致目标词表代码里的配置查找(如pad_token_id)出错。修复方式是在借用set_vocab() 期间把hparams切换为目标配置,与已有的dir_model替换保持一致,而不是去教HunYuanModel::set_vocab认识草稿模型。
- 同一PR的提交还包括:convert : fix HunYuan special token ids for DFlash drafts;convert : use load_hparams for HunYuan special token ids。
- hunyuan-dense.cpp复用该计算图,hunyuan-moe使用独立计算图,两者在本次改动中的覆盖情况不同。
- 该向量仅在投机实现启用对应层号时读取,因此没有草稿模型时行为不变。