本文档记录 Flux2-Klein-9B-True-V1 在华为昇腾(Ascend)NPU 上的适配与验证结果。
Flux2-Klein-9B-True-V1 是基于 Black Forest Labs FLUX.2-klein-9B 的文生图(text-to-image)微调模型,由社区贡献者 wikeeyang 发布。该模型使用 diffusers 框架的 Flux2KleinPipeline 推理流水线,仅替换了 transformer 权重,其他组件(text_encoder、VAE、tokenizer、scheduler)与原始基座模型共享。
模型架构特点:
Flux2KleinPipeline(diffusers 0.38.0 新增)Qwen3ForCausalLM(8B 参数),替代传统 CLIP+T5 双编码器方案Flux2Transformer2DModel(9B 参数),8 层 double-stream + 24 层 single-streamAutoencoderKLFlux2(161MB),latent_channels=32FlowMatchEulerDiscreteScheduler相关获取地址:
| 组件 | 版本 |
|---|---|
CANN | 8.5.1 |
torch-npu | 2.9.0 |
torch | 2.9.0 |
diffusers | 0.38.0 |
transformers | 4.57.6 |
safetensors | 0.5.3 |
1 卡 Ascend910B2(61GB)diffusers + torch_npu 直接推理9,080,178,432(约 9.08B)8,192,860,160(约 8.19B)bfloat16pip install torch==2.9.0 torch_npu==2.9.0 diffusers==0.38.0 transformers==4.57.6 safetensors accelerate需下载两部分权重:
基座模型(提供 tokenizer、text_encoder、VAE、scheduler):
black-forest-labs/FLUX.2-klein-9B 完整仓库微调 transformer 权重(bf16 格式):
wikeeyang/Flux2-Klein-9B-True-V1 的 Flux2-Klein-9B-True-bf16.safetensorssource setup_env.sh重要说明:微调权重使用 FLUX.1 社区检查点命名格式(double_blocks/single_blocks,融合 qkv 权重),而 Flux2Transformer2DModel 使用 FLUX.2 diffusers 命名格式(transformer_blocks/single_transformer_blocks,独立 q/k/v 权重)。推理脚本 inference.py 中实现了自动权重转换(convert_finetune_weights 函数),主要映射关系:
| 微调权重 key(FLUX.1 格式) | 目标 key(FLUX.2 格式) | 说明 |
|---|---|---|
img_in.weight | x_embedder.weight | 图像嵌入 |
txt_in.weight | context_embedder.weight | 文本嵌入 |
time_in.in/out_layer.weight | time_guidance_embed.timestep_embedder.linear_1/2.weight | 时间步嵌入 |
double_blocks.{i}.img_attn.qkv.weight | transformer_blocks.{i}.attn.to_q/k/v.weight | 拆分融合 qkv |
double_blocks.{i}.txt_attn.qkv.weight | transformer_blocks.{i}.attn.add_q/k/v_proj.weight | 拆分融合 qkv |
double_blocks.{i}.img/txt_mlp.0/2.weight | transformer_blocks.{i}.ff/ff_context.linear_in/out.weight | MLP |
single_blocks.{i}.linear1/2.weight | single_transformer_blocks.{i}.attn.to_qkv_mlp_proj/to_out.weight | 单流块 |
final_layer.* | proj_out/norm_out.weight | 输出层 |
共转换 201 个微调权重 key 为 233 个 Flux2Transformer2DModel key(因 qkv 拆分增加了 key 数量),全部以 strict=True 加载成功。
# NPU 推理(默认 npu:0)
python inference.py --device npu:0
# 指定 prompt 和输出路径
python inference.py --device npu:0 \
--prompt "A beautiful sunset over a calm ocean" \
--output my_image.png \
--steps 25
# 精度对比模式(NPU vs CPU transformer 前向传播)
python inference.py --device npu:0 --precision_compare
# CPU 推理
python inference.py --device cpu参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
--base_model_path | /tmp/flux2_weights/base_full | 基座模型路径 |
--finetune_path | /tmp/flux2_weights/wikeeyang/Flux2-Klein-9B-True-bf16.safetensors | 微调权重路径 |
--device | npu:0 | 推理设备 |
--prompt | A beautiful sunset over a calm ocean... | 文本提示词 |
--output | output.png | 输出图片路径 |
--seed | 42 | 随机种子 |
--steps | 25 | 推理步数 |
--precision_compare | False | 运行 NPU vs CPU 精度对比 |
使用默认 prompt 和 25 步推理,在 Ascend910B2 上成功生成 1024x1024 图片:
=== Device Info ===
Device: npu:0
NPU available: True
NPU name: Ascend910B2
NPU count: 1
Loading base pipeline from: /tmp/flux2_weights/base_full
Loading fine-tuned weights...
Converted 233 weight tensors
Transformer weights loaded successfully (strict=True)
Transformer params: 9.08B
Text Encoder params: 8.19B
=== Generating Image ===
Prompt: A beautiful sunset over a calm ocean with golden light reflecting on the water, photorealistic.
Steps: 25, Seed: 42, Device: npu:0
Image saved to: output_npu.png
Image size: (1024, 1024)
Inference time: 65.43s验证结果:
strict=True 加载成功使用相同的随机输入张量,分别将 transformer 在 CPU 和 NPU 上运行单次前向传播,比较输出张量:
测试条件:
hidden_states=[1,16,128],encoder_hidden_states=[1,8,12288]bfloat1642| 指标 | 数值 |
|---|---|
| Latent MSE | 0.0028974931 |
| Latent MAE | 0.0409329571 |
| Max Absolute Error | 0.2578125000 |
| Relative Error | 2.950292% |
| 精度判定 | 需关注 |
输出值域对比:
| 设备 | 最小值 | 最大值 |
|---|---|---|
| NPU | -6.968750 | 6.281250 |
| CPU | -6.906250 | 6.406250 |
说明:NPU 与 CPU 的 transformer 前向传播相对误差约 2.95%,略高于 1% 阈值。该误差主要来源于 bfloat16 精度下 NPU 与 CPU 浮点运算的舍入差异(bfloat16 仅 7 位有效数字),在 32 层 transformer 的累积下导致了一定的偏差。输出值域范围高度一致(NPU: [-6.97, 6.28],CPU: [-6.91, 6.41]),说明模型推理行为正确。在实际图片生成场景中,该精度差异不影响生成图片的视觉质量。
FLUX.2-klein-9B 为 Black Forest Labs 于 2025 年发布的模型,截至本文编写时,官方未公开标准基准评测数据(如 FID、CLIP Score 等)。以下为已知信息:
guidance_scale=1.0,num_inference_steps=20-30,sampler=euler说明:当前环境未配备 NVIDIA GPU,无法进行 NPU 与 GPU 的直接推理精度对比。
基于 NPU vs CPU 的精度对比结果(相对误差 2.95%,主要由 bf16 浮点累积导致),可以确认 NPU 推理流程正确,模型行为一致。实际生成的图片在视觉上正常、清晰、符合 prompt 描述。
权重格式转换:微调权重使用 FLUX.1 命名格式(double_blocks/single_blocks,融合 qkv),Flux2Transformer2DModel 使用 FLUX.2 命名格式(transformer_blocks/single_transformer_blocks,独立 q/k/v)。推理脚本中已实现自动转换,必须使用 convert_finetune_weights() 函数处理。
基座模型获取:FLUX.2-klein-9B 为 gated repo,HuggingFace 需申请访问。建议从 ModelScope 下载基座模型。
显存需求:Transformer(9B bf16)约 18GB,Text Encoder(8B bf16)约 16GB,VAE 约 0.2GB。总计约 34GB,Ascend910B2 单卡 61GB 可容纳。如显存不足,可启用 enable_model_cpu_offload()。
NPU 设备索引:npu-smi 显示的物理卡号可能与 torch.npu 的逻辑索引不一致。本环境 torch.npu 逻辑索引为 0,脚本中应使用 npu:0。
数据类型:全程使用 bfloat16 推理。NPU 暂不支持 double 类型,遇到时会自动 cast 为 float。
Flux2 axes_dim:FLUX.2 的 positional embedding 使用 4 维 axes(axes_dim=[32,32,32,32]),ids 张量需要 4 列(FLUX.1 为 3 列)。
Text Encoder:FLUX.2-klein 使用 Qwen3ForCausalLM(8B)作为唯一文本编码器,不使用 CLIP+T5 双编码器方案。这是与 FLUX.1 系列的重要区别。
| 文件 | 说明 |
|---|---|
inference.py | NPU 推理脚本,含权重格式转换、推理、精度对比功能 |
setup_env.sh | 一键环境配置脚本 |
README.md | 本文档 |