Skip to content

Support InternVL3.5 model - #4867

Open
fjaijf wants to merge 14 commits into
PaddlePaddle:developfrom
fjaijf:Intervl3.5
Open

Support InternVL3.5 model#4867
fjaijf wants to merge 14 commits into
PaddlePaddle:developfrom
fjaijf:Intervl3.5

Conversation

@fjaijf

@fjaijf fjaijf commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

PR 类型

新增模型支持 / Models

PR 变更

新增 InternVL3.5-1B 在 PaddleFormers 中的模型接入,包括配置、模型、Processor、ImageProcessor、Auto 注册、单测与本地真实权重验证。

主要内容

  1. 新增 paddleformers/transformers/internvl3_5

    • InternVLChatConfig
    • InternVisionConfig
    • InternVLChatModel
    • InternVisionModel
    • InternVLProcessor
    • InternVLImageProcessor
  2. 接入 Auto 入口

    • AutoConfig
    • AutoModel
    • AutoProcessor
    • AutoImageProcessor
  3. 支持从原始 HuggingFace 权重加载

    • 本地验证模型路径:/sda/housaijie/code/InternVL3_5-1B
    • 支持 convert_from_hf=True
    • 已验证 model.safetensors 权重可完整加载
    • PaddleFormers 加载日志显示所有 checkpoint 权重均被使用
  4. 复用主线 Qwen3 / Qwen3-MoE 实现

    • dense 结构复用 Qwen3ForCausalLMDeprecated
    • MoE 结构复用 Qwen3MoeForCausalLMDeprecated
    • 未重新实现 Qwen3 decoder / attention
    • 单测覆盖 Qwen3-MoE config dispatch 与 router gate 权重转换
  5. 新增测试

    • tests/transformers/internvl3_5/test_modeling.py
    • tests/transformers/internvl3_5/test_processor.py

验证结果

1. 单卡前向精度对齐

使用本地真实 InternVL3.5-1B 权重,对齐 transformers/PyTorch 与 PaddleFormers 的 FP32 forward logits。

固定输入:

  • 模型路径:/sda/housaijie/code/InternVL3_5-1B
  • 图像输入:pixel_values shape = (1, 3, 448, 448)
  • 文本输入:Describe the image.
  • 图像 token 数:256
  • <IMG_CONTEXT> token id:151671

结果:

logits shape: (1, 262, 151936)
logits mean abs diff: 5.262756531010382e-05
logits p95 abs diff: 0.00017404556274414062
logits p99 abs diff: 0.00036716461181640625
logits max abs diff: 0.002592325210571289

满足 1e-2 量级要求。

2. 生成结果对齐
使用 greedy search,对比前 10 个生成 token。

torch tokens:
[1096, 2168, 7952, 311, 387, 264, 49400, 476, 49400, 2319]

paddle tokens:
[1096, 2168, 7952, 311, 387, 264, 49400, 476, 49400, 2319]

first10_equal: True

3. 单测结果
执行命令:
> [!NOTE]
>  miniconda3/envs/paddleformers/bin/python -m unittest \
  tests.transformers.internvl3_5.test_modeling \
  tests.transformers.internvl3_5.test_processor

@risemeup1111 risemeup1111 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

序号 位置 优先级 状态
1 modeling.py:270 P1
2 modeling.py:92 P1
3 processor.py:97 P1
4 internvl3_5/modeling.py:23 P1
5 internvl3_5/modeling.py:507 P2
Powered by Nyanpasu with gpt-5.5 xhigh, please check the suggestions carefully.

llm_config = {"architectures": ["Qwen3ForCausalLM"]}

self.vision_config = InternVisionConfig(**vision_config) if isinstance(vision_config, dict) else vision_config
self.llm_config = Qwen3Config(**llm_config) if isinstance(llm_config, dict) else llm_config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 这里把所有 llm_config 都构造成 dense Qwen3Config,但公开的 OpenGVLab/InternVL3_5-30B-A3BOpenGVLab/InternVL3_5-241B-A28B 配置声明的是 model_type: qwen3_moe / Qwen3MoeForCausalLM。随后 InternVLChatModel.__init__ 又固定实例化 Qwen3ForCausalLMDeprecated,因此这些官方 InternVL3.5 检查点会创建 dense 层,expert/router 权重无法匹配。请按 llm_config.model_typearchitectures 分派 Qwen3/Qwen3Moe 的配置、模型及转换规则;若本次只支持 dense 变体,也应在这里显式拒绝不支持的架构,避免静默构造错误模型。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

仍未完全解决:modeling.py:258-272transpose_weight_keys 没有包含 MoE router 的 gateload_checkpoint_format="" 从 HF 权重加载时会保留 [num_experts, hidden_size],无法匹配 Paddle Linear 的 [hidden_size, num_experts];请补上 gate,并增加该加载路径的 MoE checkpoint 转换测试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已确认当前提交将 gate 加入 transpose_weight_keys,并新增 load_checkpoint_format="" 从 HF safetensors 回读 router 权重的回归测试;该问题已解决。


def forward(self, pixel_values):
target_dtype = self.patch_embedding.weight.dtype
patch_embeds = self.patch_embedding(pixel_values)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 InternVLImageProcessor 固定返回 float32pixel_values,而官方 InternVL3.5 配置带有 torch_dtype: bfloat16from_pretrained 会据此以 bf16 创建这里的卷积权重。当前输入未经转换就进入 Conv2D,所以 model.generate(**processor(...)) 在真实 bf16 检查点上会遇到输入与权重 dtype 不一致;仓库内其他 VLM 也都在视觉 patch embedding 前按权重 dtype 转换。请先将 pixel_values 转成 target_dtype,并增加一个 bf16 模型接收处理器输出的集成测试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已确认当前提交在视觉 patch embedding 前将 pixel_values 转为卷积权重 dtype,并补充了 bf16 回归测试;该问题已解决。


text_inputs = self.tokenizer(text, **output_kwargs["text_kwargs"], return_tensors=return_tensors)
data = dict(text_inputs)
data.update(dict(image_inputs))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 image_inputs 中包含 num_patches_list,这里会把它原样放进处理器的最终 BatchFeature;但 InternVLChatModel.forward 不接受该参数,因此标准的 model(**processor(text=..., images=..., return_tensors="pd")) 路径会直接报 unexpected keyword argument 'num_patches_list'。图像 token 展开完成后该元数据已不再参与前向,请在返回前移除它,或让模型显式接收,并补一个处理器输出直连模型的测试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已确认当前提交在展开图像 token 后移除 num_patches_list,最终处理器输出与模型前向参数一致;该问题已解决。

@Paddle-CI-Bot

Copy link
Copy Markdown

PaddleFormers Log Analysis

Run #31492406384 · Attempt 1

日志分析报告

流水线名称 问题标签 修复建议 日志片段
Unittest GPU CI 依赖包缺失 paddlefleet_ops==0.4.0.dev20260811+5819cd68 尚未发布到包源,等待 PaddleFleet ops wheel 构建完成后 rerun 报错代码
Model Unittest GPU CI 其他(MergeModel 导入失败) qwen3 所有训练 case 均报 ModuleNotFoundError: Could not import module 'MergeModel',需确认 PR 改动是否破坏了 paddleformers/transformers/qwen3/modeling.py 的模块注册或导入链 报错代码

失败的测试case:

# Model Unittest GPU CI (run 31477970528)
scripts/regression/test_models.py::TestTrain::test_full[qwen3-sft]
scripts/regression/test_models.py::TestTrain::test_full[qwen3-dpo]
scripts/regression/test_models.py::TestTrain::test_full[qwen3-pt]
scripts/regression/test_models.py::TestTrain::test_full_map[qwen3-sft]
scripts/regression/test_models.py::TestTrain::test_lora[qwen3-sft]
scripts/regression/test_models.py::TestTrain::test_lora[qwen3-dpo]
scripts/regression/test_models.py::TestTrain::test_lora[qwen3-pt]
scripts/regression/test_models.py::TestTrain::test_full_tp_pp[qwen3-sft]
scripts/regression/test_models.py::TestTrain::test_full_tp_pp[qwen3-dpo]
scripts/regression/test_models.py::TestTrain::test_full_tp_pp[qwen3-pt]
scripts/regression/test_models.py::TestTrain::test_lora_tp_pp[qwen3-sft]
scripts/regression/test_models.py::TestTrain::test_lora_tp_pp[qwen3-dpo]
scripts/regression/test_models.py::TestTrain::test_lora_tp_pp[qwen3-pt]
scripts/regression/test_models.py::TestTrain::test_full_function_call[qwen3-sft]
scripts/regression/test_models.py::TestTrain::test_full_function_call[qwen3-dpo]

# Unittest GPU CI (run 31477970534)
(单测因 paddlefleet_ops 安装失败提前退出,未执行到 pytest 阶段,无具体 case 输出)

根本原因分析:

  • Unittest GPU CI:安装环境阶段即失败——scripts/install_ops_wheel.sh 按 PaddleFleet 当天 commit(5819cd68)计算出版本 0.4.0.dev20260811+5819cd68,但该版本尚未发布到 https://www.paddlepaddle.org.cn/packages/nightly/cu129/,导致 pip 找不到包直接退出,与本 PR(InternVL3.5 新增)无关。

  • Model Unittest GPU CI:qwen3 全部训练 case 报 ModuleNotFoundError: Could not import module 'MergeModel',同时日志中有 PyTorch was not found。PR 修改了 paddleformers/transformers/qwen3/modeling.py31+2 行),该改动中的 Keep Qwen3 deprecated import fallback 提交引入了对 torch 的条件导入或模块别名,可能破坏了 PaddleFormers 自身的 MergeModel 注册路径。

修复建议:

  1. Unittest GPU CI:等待 PaddleFleet CI 完成 5819cd68 对应 ops wheel 的构建并发布后直接 rerun,无需修改本 PR 代码。

  2. Model Unittest GPU CI

    • 检查 paddleformers/transformers/qwen3/modeling.py 最近的改动,定位 MergeModel 相关的导入/注册逻辑(__init__.pyauto/modeling.py 中的 mapping)。
    • 报错 ModuleNotFoundError: Could not import module 'MergeModel' 通常发生在 AutoModel/MergeModel 的 lazy mapping 找不到对应类时,检查是否在改动 qwen3 modeling 时意外移除或重命名了导出的类名。
    • 复现命令:在本地安装 PR 分支后运行一个最简 qwen3 sft full case,查看完整 traceback 确定具体缺失的导入链。
    • 修复后重新 push 触发 CI。

🔍 准确性记录:请点击评论底部 😊 图标,选择 👍(准确)或 👎(有误),将自动记录到 CI 监控系统

🔄 每次 Re-run 后自动更新

CausalLMOutputWithPast,
)
from ..model_utils import PretrainedModel
from ..qwen3.modeling import Qwen3ForCausalLMDeprecated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 这里的顶层导入会让标准安装无法导入 InternVL3.5:qwen3.modeling 无条件导入 gpt_provider,而后者在未安装可选 extra paddlefleet 时会在模块导入阶段抛出 ImportErrorsetup.py 只在 paddleformers[paddlefleet] 中声明该依赖,因此即使这里只构造不依赖 Fleet 的 Qwen3ForCausalLMDeprecatedfrom paddleformers.transformers import InternVLChatModel 也会失败。请恢复 lazy/guarded import,或把 deprecated 实现从 Fleet provider 的导入链中隔离,并补充无 PaddleFleet 的 import smoke test。

labels: Optional[paddle.Tensor] = None,
use_cache: Optional[bool] = None,
output_attentions: Optional[bool] = None,
output_hidden_states: Optional[bool] = None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 这个参数现在被静默忽略:下方 language_model_kwargs 未包含 output_hidden_states,返回值只是读取底层 outputs.hidden_states;当前 Qwen3ForCausalLMDeprecated 也不处理该标志,所以显式传入 True 仍会得到 None。与此同时测试已改成直接构造 InternVisionModel,不再覆盖 chat wrapper。请恢复 wrapper 的语言模型 hidden states 行为(或移除该公共参数),并用 InternVLChatModel 补充回归测试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已确认当前提交移除了 InternVLChatModel 不支持的 output_hidden_states 参数,并将回归测试明确改为 InternVisionModel;该问题已解决。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants