【Bug已解决】Kohya->diffusers LoRA key converter fails for Chroma and Flux1, if LoRA is not attention-onl
【Bug已解决】Kohya-diffusers LoRA key converter fails for Chroma and Flux1, if LoRA is not attention-only 解决方案一、现象长什么样diffusers 提供convert_kohya_lora_to_diffusers把 Kohya 格式的 LoRA常见来自 sd-scripts / Kohya_ss GUI转成 diffusers 可直接load_lora_weights的格式。当 LoRA 是「纯注意力」时一切正常但只要 LoRA 里包含非注意力模块如 MLP、norm/modulation 层转 Chroma 或 FLUX.1 权重就会失败from diffusers.loaders import LoraLoaderMixin LoraLoaderMixin.lora_state_dict( None, kohya_chroma_mlp_lora.safetensors )报错KeyError Cannot find corresponding diffusers key for lora_unet_double_blocks_0_img_mlp_fc1.lora_up.weight或者转换脚本静默跳过这些 key加载后效果不对WARNING: skipping unmapped key lora_unet_double_blocks_0_img_modulation_lin.weight现象总结Kohya→diffusers 转换器只为 FLUX/Chroma 的注意力模块to_q/k/v/out、img_attn、txt_attn写了 key 映射正则而 Chroma/FLUX.1 的 LoRA 可能包含mlp、modulation、norm等非注意力模块的 key这些 key 没有映射规则于是KeyError或被静默丢弃。二、背景Kohya 的 LoRA key 命名约定形如lora_unet_block_module.lora_up.weight/lora_down.weight/alpha对 FLUX.1module可能是double_blocks_0_img_attn_proj注意力、也可能是double_blocks_0_img_mlp_fc1MLP、double_blocks_0_img_modulation_lin调制、single_blocks_3_modulation_lin等。diffusers 侧的对应命名是transformer.transformer_blocks.X.attn.to_q.lora.up.weight这种嵌套路径。转换器的工作就是把 Kohya 的扁平名「翻译」成 diffusers 的嵌套名。问题在于原转换器只覆盖注意力相关的module片段遇到mlp_fc1/modulation_lin/norm这类非注意力片段时正则匹配不到于是 KeyError 或 skip。Chroma 因为结构里 MLP/modulation 占比更大纯注意力 LoRA 很少见几乎必踩。三、根因根因两点key 映射正则只覆盖注意力模块转换器内部用一个UNET_TO_DIFFUSERS映射表 正则只列举了to_q/to_k/to_v/to_out/proj/linear等注意力关键词没列mlp、modulation、norm_linear、final_layer等。没有「未知模块即报错」的兜底策略转换器遇到匹配不上的 key有的版本直接raise KeyError有的版本warn skip。两种都不好——前者阻断转换后者悄悄丢权重导致效果错。正确做法是先把所有可能的模块家族补全进映射再对真正未知的 key 才报错。本质转换器的「模块家族白名单」不全且对非注意力模块没有统一翻译规则。四、最小可运行复现用标准库复现「正则只匹配注意力mlp key 漏掉」import re # 原转换器的不完整映射只管注意力 ATTENTION_ONLY { rto_q$: to_q, rto_k$: to_k, rto_v$: to_v, rto_out$: to_out.0, rimg_attn_proj$: attn.to_q, # 简化示意 } def convert_key(kohya_key: str): base kohya_key.replace(lora_unet_, ).replace(.lora_up.weight, ) for pat, repl in ATTENTION_ONLY.items(): if re.search(pat, base): return ftransformer.transformer_blocks.{base}.lora.up.weight.replace(base, repl) raise KeyError(fCannot find corresponding diffusers key for {kohya_key}) # Chroma 的 MLP LoRA key try: convert_key(lora_unet_double_blocks_0_img_mlp_fc1.lora_up.weight) except KeyError as e: print(KeyError, e) # 因为 mlp_fc1 不在注意力白名单要复现「静默 skip」把raise换成warnings.warn return None转换后该权重丢失。五、解决方案第一层最小直接修复最小修复把 MLP / modulation / norm 等非注意力模块的映射片段补进转换正则并对未知 key 显式报错而不是静默丢import re # 补全后的模块家族映射含非注意力 MODULE_MAP { # 注意力 rimg_attn_proj$: attn.to_q, rimg_attn_qkv$: attn.to_qkv, rtxt_attn_proj$: attn.to_q, rto_q$: to_q, rto_k$: to_k, rto_v$: to_v, rto_out$: to_out.0, # 非注意力MLP rimg_mlp_fc1$: ff.net.0.proj, rimg_mlp_fc2$: ff.net.2, rtxt_mlp_fc1$: ff.net.0.proj, rtxt_mlp_fc2$: ff.net.2, # 非注意力modulation / norm rimg_modulation_lin$: norm_linear, rtxt_modulation_lin$: norm_linear, rmodulation_lin$: norm_linear, rfinal_layer_norm_linear$: norm_out.linear, } def convert_key(kohya_key: str): base kohya_key.replace(lora_unet_, ).replace(.lora_up.weight, ) base base.replace(.lora_down.weight, ).replace(.alpha, ) for pat, repl in MODULE_MAP.items(): if re.search(pat, base): diff base[: base.rfind(re.findall(pat, base)[0])] repl suffix .alpha if kohya_key.endswith(.alpha) else .lora.up.weight return ftransformer.transformer_blocks.{diff}{suffix} # 真正未知才报错绝不静默丢 raise KeyError(f未识别的 Kohya key请补充映射: {kohya_key})这一改后Chroma/FLUX.1 的 MLP、modulation LoRA key 都能正确翻译且未知 key 会明确报错而非悄悄丢失。六、解决方案第二层结构性改进把「每个模型支持哪些模块家族」收敛成一个 dataclass 单一真源转换器按需加载对应模型的映射from dataclasses import dataclass, field from typing import Dict, List dataclass(frozenTrue) class KohyaLoraModulePolicy: Kohya-diffusers LoRA 转换的模块家族单一真源。 model_family: str # 该模型可能出现的模块家族注意力 非注意力 module_families: Dict[str, str] field(default_factorydict) # 是否允许非注意力模块False 时遇到 mlp/modulation 直接报错 allow_non_attention: bool True def known_suffixes(self) - List[str]: return list(self.module_families.keys()) def translate(self, module_fragment: str) - str: for pat, repl in self.module_families.items(): if module_fragment.endswith(pat): return repl raise KeyError(f未识别模块片段: {module_fragment}) CHROMA_POLICY KohyaLoraModulePolicy( model_familychroma, allow_non_attentionTrue, module_families{ img_attn_proj: attn.to_q, img_mlp_fc1: ff.net.0.proj, img_mlp_fc2: ff.net.2, img_modulation_lin: norm_linear, txt_attn_proj: attn.to_q, txt_mlp_fc1: ff.net.0.proj, txt_modulation_lin: norm_linear, }, ) FLUX1_POLICY KohyaLoraModulePolicy( model_familyflux1, allow_non_attentionTrue, module_families{ img_attn_proj: attn.to_q, img_mlp_fc1: ff.net.0.proj, img_mlp_fc2: ff.net.2, modulation_lin: norm_linear, final_layer_norm_linear: norm_out.linear, }, )转换主函数convert_kohya_lora_to_diffusers(state_dict, policy)只依赖传入的policy新增模型家族只需补一个KohyaLoraModulePolicy实例转换器主体不动。七、解决方案第三层断言 / CI 守护用 pytest 把「非注意力 key 可翻译 未知 key 报错 不静默丢」固化成回归import pytest from mylib.kohya_convert import convert_key_v2, KohyaLoraModulePolicy, CHROMA_POLICY, FLUX1_POLICY def test_mlp_key_translates(): out convert_key_v2(lora_unet_double_blocks_0_img_mlp_fc1.lora_up.weight, CHROMA_POLICY) assert ff.net.0.proj in out, Chroma MLP LoRA key 应被翻译 assert out.endswith(.lora.up.weight) def test_modulation_key_translates(): out convert_key_v2(lora_unet_double_blocks_0_img_modulation_lin.lora_up.weight, CHROMA_POLICY) assert norm_linear in out def test_unknown_key_raises_not_skipped(): with pytest.raises(KeyError, match未识别): convert_key_v2(lora_unet_double_blocks_0_unknown_xyz.lora_up.weight, CHROMA_POLICY) def test_flux1_final_layer_key(): out convert_key_v2(lora_unet_final_layer_norm_linear.lora_up.weight, FLUX1_POLICY) assert norm_out.linear in out def test_roundtrip_preserved_count(): sd { lora_unet_double_blocks_0_img_attn_proj.lora_up.weight: None, lora_unet_double_blocks_0_img_mlp_fc1.lora_up.weight: None, lora_unet_double_blocks_0_img_modulation_lin.lora_up.weight: None, } converted {convert_key_v2(k, CHROMA_POLICY): v for k, v in sd.items()} assert len(converted) 3, 所有 key 都应被翻译无一遗漏CI 把test_mlp_key_translates与test_unknown_key_raises_not_skipped作为 LoRA 转换模块的必过项防止非注意力模块再次漏映射或被静默丢弃。八、排查清单Kohya→diffusers LoRA 转换失败按顺序查报错 key 是否含mlp/modulation/norm/final_layer这些是常见非注意力模块原映射常漏。转换器是否只对注意力写正则是就用MODULE_MAP把非注意力片段补全。未知 key 是被raise还是被warn skip静默 skip 会导致权重丢失、效果错必须改成显式报错。模型家族Chroma / FLUX.1是否各自有不同的模块命名用KohyaLoraModulePolicy分别描述。alpha标量是否一起转换LoRA 的alphakey 也要映射到 diffusers 的alpha字段否则缩放比例错。转换后load_lora_weights是否真的注入了这些模块用pipe.unet.double_blocks[0].ff.net[0].proj.lora_up.weight之类确认权重落地而非空张量。九、小结「Kohya→diffusers LoRA key converter fails for Chroma and Flux1, if LoRA is not attention-only」本质是转换器的模块家族白名单不全且对非注意力模块没有统一翻译规则遇到未知 key 要么 KeyError 要么静默丢权重。第一层把 MLP/modulation/norm 等片段补进映射正则并改成「未知即显式报错」第二层把每个模型的模块家族收敛到KohyaLoraModulePolicy单一真源转换器主体与模型无关第三层用 pytest 守住「非注意力 key 可翻译、未知 key 报错、无遗漏」。通用教训任何 key 转换/格式迁移工具都必须把「源 schema 的全部字段家族」列为单一真源否则只要源多出一个字段类别转换就崩或静默失真。

相关新闻

【Bug已解决】attention dispatcher assumes wrong attributes for flash attn kernel from hub 解决方案

【Bug已解决】attention dispatcher assumes wrong attributes for flash attn kernel from hub 解决方案

【Bug已解决】attention dispatcher assumes wrong attributes for flash attn kernel from hub 解决方案 一、现象长什么样 diffusers 里有一层「注意力后端分发器」(attention dispatcher):根据环境里装了哪个 flash-attention 内核&#x…

2026/10/17 4:43:59 阅读更多 →
对抗性原理:从贝叶斯先验到多视角验证

对抗性原理:从贝叶斯先验到多视角验证

对抗性原理:从贝叶斯先验到多视角验证 对抗性原理是一种通过改变审查者先验默认来提高发现问题概率的方法论:把"待证实"翻转为"待反驳",并要求反驳必须给出可复现的证据。它依赖三条支柱——贝叶斯先验翻转、波普尔证伪、…

2026/10/17 4:47:07 阅读更多 →
浏览器中的ADB:Tango如何重新定义Android调试体验

浏览器中的ADB:Tango如何重新定义Android调试体验

浏览器中的ADB:Tango如何重新定义Android调试体验 【免费下载链接】ya-webadb ADB in your browser 项目地址: https://gitcode.com/gh_mirrors/ya/ya-webadb 想象一下,无需安装任何本地工具,直接在浏览器中就能调试和管理Android设备…

2026/10/17 4:47:16 阅读更多 →

最新新闻

老旧ARM盒子部署可道云:Docker自建私有网盘的完整实战

老旧ARM盒子部署可道云:Docker自建私有网盘的完整实战

玩ARM盒子的人,迟早会走到“自建私有网盘”这一步。手头一台吃灰的ARM设备,刷上Armbian 5.77(Debian 9),跑在老旧内核上,想要一个能传大文件、能在线看文档、能挂到电脑上当网络硬盘的Web网盘,可…

2026/10/18 14:21:29 阅读更多 →
AI辅助毕业论文写作:从选题到终稿的实操指南

AI辅助毕业论文写作:从选题到终稿的实操指南

1. 毕业论文的真正难题,不是“写不出来”而是“不知道怎么开始”每年毕业季,我都能看到一大批学生对着空白的Word文档坐到天亮。有人说论文难在写作,其实写作只是最后一步。真正的痛点在前置环节:选题方向拿不准、文献堆成山却读不…

2026/10/18 14:21:29 阅读更多 →
Cursor 把 C 盘吃掉 20GB?用 Python 开源工具 cursor-clean 一键清理

Cursor 把 C 盘吃掉 20GB?用 Python 开源工具 cursor-clean 一键清理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 14:21:29 阅读更多 →
LangChain多智能体实战:用TaoToken统一Key跑通Agent协作链路

LangChain多智能体实战:用TaoToken统一Key跑通Agent协作链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 14:21:29 阅读更多 →
期权Alpha系统化交易框架:从波动率定价到风险管理四步闭环

期权Alpha系统化交易框架:从波动率定价到风险管理四步闭环

这个系列写到第4章,所有拆过的策略、参数和案例,是时候拢到一起做个收口了。Option Alpha这个题目,很多人误以为是一套能稳定盈利的期权策略模板,但四章写下来,我反复想强调的观点其实只有一个:期权本身不产…

2026/10/18 14:21:29 阅读更多 →
从空白需求到自动化数据采集:Playwright实战全链路记录

从空白需求到自动化数据采集:Playwright实战全链路记录

上周收到一个需求,项目名叫【无标题】,正文空白、关键词空白,连摘要也只留了一句“先看看能做什么”。一开始我以为是对方漏贴了内容,后来发现这事在真实工作里太常发生了:很多项目最早期根本没有成文的需求&#xff0…

2026/10/18 14:20:28 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →