Feature[add model mistralai/ministral3]#4293
Conversation
|
Thanks for your contribution! |
Codecov Report❌ Patch coverage is ❌ Your patch status has failed because the patch coverage (61.56%) is below the target coverage (75.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## develop #4293 +/- ##
==========================================
Coverage ? 35.00%
==========================================
Files ? 478
Lines ? 89900
Branches ? 0
==========================================
Hits ? 31467
Misses ? 58433
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
确保带Required的CI测试项通过,如果报错原因非此PR导致的,可以自行评论 /re-run all-failed 重跑CI |
risemeup1111
left a comment
There was a problem hiding this comment.
已完成初轮审查,发现需要先修复的问题,具体证据和建议都放在行级评论里。CI 当前显示通过,但这些问题会影响 use_cache=True 生成路径以及部分权重加载路径,建议修复后再合入。
| model_inputs = { | ||
| "input_ids": input_ids, | ||
| "past_key_values": past_key_values, | ||
| "use_cache": kwargs.get("use_cache", True), | ||
| } | ||
| if is_first_iteration or not kwargs.get("use_cache", True): | ||
| model_inputs["pixel_values"] = pixel_values | ||
| if attention_mask is not None: | ||
| model_inputs["attention_mask"] = attention_mask | ||
| if cache_position is not None: | ||
| model_inputs["cache_position"] = cache_position | ||
| return model_inputs |
There was a problem hiding this comment.
这里重写后没有复用 GenerationMixin.prepare_inputs_for_generation 的裁剪逻辑。PaddleFormers 的 generate 循环每一步都会传入累计增长的 input_ids,基类会在 past_key_values 已存在且 cache 非空时只保留最后一个 token;当前实现把完整序列连同旧 cache 再送进 decoder,会把已缓存 token 重复追加,导致 past_key_values 长度膨胀、后续位置/attention mask 错位,model.generate(..., use_cache=True) 的输出会和无 cache 推理不一致。建议复用基类准备输入,只在首轮保留视觉输入。
| model_inputs = { | |
| "input_ids": input_ids, | |
| "past_key_values": past_key_values, | |
| "use_cache": kwargs.get("use_cache", True), | |
| } | |
| if is_first_iteration or not kwargs.get("use_cache", True): | |
| model_inputs["pixel_values"] = pixel_values | |
| if attention_mask is not None: | |
| model_inputs["attention_mask"] = attention_mask | |
| if cache_position is not None: | |
| model_inputs["cache_position"] = cache_position | |
| return model_inputs | |
| model_inputs = super().prepare_inputs_for_generation( | |
| input_ids, | |
| past_key_values=past_key_values, | |
| inputs_embeds=inputs_embeds, | |
| attention_mask=attention_mask, | |
| cache_position=cache_position, | |
| logits_to_keep=logits_to_keep, | |
| **kwargs, | |
| ) | |
| if past_key_values is not None: | |
| model_inputs["pixel_values"] = None | |
| elif pixel_values is not None: | |
| model_inputs["pixel_values"] = pixel_values | |
| return model_inputs |
| if any(f.endswith(".safetensors") for f in files): | ||
| return False | ||
| marker_file = os.path.join(model_path, ".paddleformers_converted") | ||
| if os.path.exists(marker_file): | ||
| return True | ||
| config_file = os.path.join(model_path, "config.json") | ||
| if os.path.exists(config_file): | ||
| try: | ||
| import json | ||
|
|
||
| with open(config_file, "r") as f: | ||
| config = json.load(f) | ||
| if config.get("_paddleformers_converted", False): | ||
| return True |
There was a problem hiding this comment.
这里在看到任意 .safetensors 后立即返回 False,导致下面的 .paddleformers_converted 和 config.json 里的 _paddleformers_converted 分支永远不可达。from_pretrained() 因此会把已转换的 Paddle safetensors 误走 _load_hf_safetensors_to_paddle(),按 HF 原始 FP8 规则重命名/转置后再 legacy 加载,PR 描述里的“paddle 格式权重直接加载”对 safetensors 格式会失败。请先检查显式 converted 标记,再把无标记 safetensors 当作 HF 原始权重处理。
| if any(f.endswith(".safetensors") for f in files): | |
| return False | |
| marker_file = os.path.join(model_path, ".paddleformers_converted") | |
| if os.path.exists(marker_file): | |
| return True | |
| config_file = os.path.join(model_path, "config.json") | |
| if os.path.exists(config_file): | |
| try: | |
| import json | |
| with open(config_file, "r") as f: | |
| config = json.load(f) | |
| if config.get("_paddleformers_converted", False): | |
| return True | |
| marker_file = os.path.join(model_path, ".paddleformers_converted") | |
| if os.path.exists(marker_file): | |
| return True | |
| config_file = os.path.join(model_path, "config.json") | |
| if os.path.exists(config_file): | |
| try: | |
| import json | |
| with open(config_file, "r") as f: | |
| config = json.load(f) | |
| if config.get("_paddleformers_converted", False): | |
| return True | |
| except Exception: | |
| pass | |
| if any(f.endswith(".safetensors") for f in files): | |
| return False |
| ".*o_proj.*", | ||
| ".*gate.*", | ||
| ] | ||
| elif model.config.model_type == "mistral3": |
risemeup1111
left a comment
There was a problem hiding this comment.
已复查最新提交。此前关于 use_cache=True 生成输入裁剪、已转换 safetensors 检测以及 mistral3 LoRA 目标层的行级问题在当前代码中均已修复;本轮没有发现新的阻塞问题。CI 当前通过。
liuhao2638
left a comment
There was a problem hiding this comment.
已复查最新提交。此次更新主要是合入上游变更,Ministral3 相关代码与上次通过审查的状态一致;此前行级问题仍保持已修复,未发现新的阻塞问题。CI 当前通过。
liuhao2638
left a comment
There was a problem hiding this comment.
已复查最新提交。此前关于生成输入裁剪、converted safetensors 检测和 LoRA 目标层的问题仍保持已修复;但本次新增的 RoPE fallback 处理引入了一个会影响默认配置初始化的阻塞问题,细节已放在行级评论里。CI 当前显示通过,但建议先修复该配置路径后再合入。
| self.rope_parameters = cfg_dict.get("rope_parameters", cfg_dict.get("rope_scaling")) | ||
| rope_theta = cfg_dict.get("rope_theta", 1000000.0) | ||
| if self.rope_parameters is None: | ||
| self.rope_parameters = {"rope_type": "yarn", "rope_theta": rope_theta} |
There was a problem hiding this comment.
这里把缺省 RoPE 配置改成了 rope_type="yarn",但没有提供 factor。当前 Ministral3RotaryEmbedding.__init__() 会在 rope_type != "default" 时直接调用 ROPE_INIT_FUNCTIONS["yarn"],而共享的 _compute_yarn_parameters() 明确要求 config.rope_parameters["factor"];因此 Mistral3Config() 的默认 text_config(只有 rope_theta,没有 rope_scaling)或任何未显式传 rope_scaling.factor 的配置都会在模型初始化时触发 AssertionError: factor is required in rope_parameters_dict。请让“无 scaling 配置”的 fallback 与实际初始化路径一致,例如两个 fallback 分支都使用 default RoPE,或者补齐完整的 yarn 参数。
建议按下面的形状同步修复 Ministral3TextConfig wrapper 和 Mistral3TextConfig(PretrainedConfig) 的无 scaling fallback:
if self.rope_parameters is None:
self.rope_parameters = {"rope_type": "default", "rope_theta": rope_theta}如果希望默认仍走 yarn,则需要至少补齐 factor 和 original_max_position_embeddings 等 yarn 参数,并增加一个不传 rope_parameters/rope_scaling 的默认配置初始化测试。
liuhao2638
left a comment
There was a problem hiding this comment.
已复查最新提交。此前指出的 RoPE fallback 缺少 yarn factor 的问题已修复,并新增了无 rope_scaling/rope_parameters 初始化覆盖;之前关于生成输入裁剪、converted safetensors 检测和 LoRA 目标层的问题也保持已修复。本轮未发现新的阻塞问题,CI 当前通过。
…l-ministral3 Resolve conflicts in template.py, transformers/__init__.py and auto/configuration.py by keeping both ministral3 and gemma4_moe/phi4 entries.
risemeup1111
left a comment
There was a problem hiding this comment.
已复查最新提交。本轮主要是合入上游变更,Ministral3 相关实现和测试相对上次通过审查的状态未再改动;此前两个 P1 代码问题在当前 head 仍保持已修复,未新增行级代码意见。
当前还不能重新批准:此前 mistral3 LoRA 目标层那条 P2 行级评论虽然代码已按建议修改,但该线程尚未看到作者回复。请作者在对应行级线程回复 Done(或说明不同意的理由),以便按当前流程关闭该项。
另外,CI 目前仍有任务运行中,且两个 H20 integration job 在容器启动阶段失败(exit code 125),尚未进入实际测试步骤;建议待 CI 完成或重跑确认后再合入。
PaddleFormers Log Analysis
日志分析报告
失败的测试case: 根本原因分析: 修复建议:
🔄 每次 Re-run 后自动更新 |

PR 新增 mistralai系列的ministral3 模型
权重信息
目前提供了 Ministral-3-3B-Instruct-2512 和 Ministral-3-8B-Instruct-2512 2个版本的支持和权重转换。
代码即可以直接加载HF上的原始权重,也可以支持paddle格式权重的直接加载。
精度对齐
使用
tests/transformers/ministral3/test_modeling.py的TestMistral3DiffAlignment类实现精度对齐测试断言(top10 token和logits diff)。token top 10 对齐
使用prompt: 'Hello, how are you today?'
输出的token ids
PyTorch 生成文本: " I'm fine, thank you. How about you"
Paddle 生成文本: " I'm fine, thank you. How about you"
最后一层输出的logits diff
logits max_diff: 5.912781e-05 (threshold: 0.01)
logits mean_diff: 3.532475e-06
微调loss下降对比
paddle使用配置
tests/config/ci/ministral3_sft.yamlms-swift需要特别注意,需要安装一下依赖,不然可能会有问题
pip install "mistral-common>=1.8.6" -Ums-swift使用配置如下:
注册模板my_register.py
启动命令