Skip to content

Commit c05ec89

Browse files
Merge remote-tracking branch 'upstream/main' into chore/bump-mcore-dev-260720
2 parents 035bfd4 + 0e7ffb7 commit c05ec89

6 files changed

Lines changed: 58 additions & 24 deletions

File tree

.github/workflows/cache-hf-model.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,23 @@ jobs:
3939

4040
- name: Install dependencies
4141
run: |
42-
TRANSFORMERS_VERSION=$(grep -E 'transformers[[:space:]]*[=><!~]+' ${GITHUB_WORKSPACE}/pyproject.toml | sed -E 's/.*transformers[[:space:]]*([=><!~]+)[[:space:]]*"?([0-9a-zA-Z\.\-\*]+)"?.*/\1\2/')
43-
pip install torch "transformers${TRANSFORMERS_VERSION}" "huggingface_hub[cli]"
42+
TRANSFORMERS_REQUIREMENT=$(
43+
python - "${GITHUB_WORKSPACE}/pyproject.toml" <<'PY'
44+
import re
45+
import sys
46+
import tomllib
47+
48+
with open(sys.argv[1], "rb") as pyproject:
49+
dependencies = tomllib.load(pyproject)["project"]["dependencies"]
50+
51+
pattern = re.compile(r"^transformers(?:$|[\s\[<>=!~;@])", re.IGNORECASE)
52+
requirement = next((item for item in dependencies if pattern.match(item)), None)
53+
if requirement is None:
54+
raise SystemExit("Transformers requirement not found in pyproject.toml")
55+
sys.stdout.write(requirement)
56+
PY
57+
)
58+
pip install torch "${TRANSFORMERS_REQUIREMENT}" "huggingface_hub[cli]"
4459
4560
- name: Log in to HuggingFace
4661
env:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ classifiers = [
7171
"Topic :: Utilities",
7272
]
7373
dependencies = [
74-
"transformers>=5.8.1,<5.9.0",
74+
"transformers>=5.8,<=5.12.1",
7575
"mistral-common>=1.10.0",
7676
"peft>=0.18.1",
7777
"datasets>=2.20.0",

src/megatron/bridge/models/qwen_audio/modeling_qwen2_audio.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,31 @@
4141
# Import HuggingFace Qwen2Audio model classes with fallback
4242
try:
4343
from transformers import Qwen2AudioForConditionalGeneration
44+
from transformers.models.qwen2_audio import modeling_qwen2_audio as hf_modeling_qwen2_audio
4445
from transformers.models.qwen2_audio.modeling_qwen2_audio import (
4546
Qwen2AudioEncoder,
4647
Qwen2AudioMultiModalProjector,
4748
)
4849

50+
HFQwen2AudioModel = getattr(hf_modeling_qwen2_audio, "Qwen2AudioModel", None)
4951
HAS_QWEN2_AUDIO = True
5052
except ImportError:
5153
Qwen2AudioForConditionalGeneration = None
5254
Qwen2AudioEncoder = None
5355
Qwen2AudioMultiModalProjector = None
56+
HFQwen2AudioModel = None
5457
HAS_QWEN2_AUDIO = False
5558

5659

60+
_QWEN2_AUDIO_MERGE_METHOD = None
61+
if HAS_QWEN2_AUDIO:
62+
_QWEN2_AUDIO_MERGE_METHOD = getattr(
63+
Qwen2AudioForConditionalGeneration, "_merge_input_ids_with_audio_features", None
64+
)
65+
if _QWEN2_AUDIO_MERGE_METHOD is None and HFQwen2AudioModel is not None:
66+
_QWEN2_AUDIO_MERGE_METHOD = getattr(HFQwen2AudioModel, "_merge_input_ids_with_audio_features", None)
67+
68+
5769
class Qwen2AudioModel(MegatronModule):
5870
"""
5971
Qwen2-Audio Model wrapper for Megatron.
@@ -141,11 +153,9 @@ def __init__(
141153
self.share_embeddings_and_output_weights = config.share_embeddings_and_output_weights
142154
self.shared_embedding_or_output_weight = self.language_model.shared_embedding_or_output_weight
143155

144-
# Monkey-patch methods from HuggingFace Qwen2AudioForConditionalGeneration
145-
if HAS_QWEN2_AUDIO and Qwen2AudioForConditionalGeneration is not None:
146-
self._merge_input_ids_with_audio_features = types.MethodType(
147-
Qwen2AudioForConditionalGeneration._merge_input_ids_with_audio_features, self
148-
)
156+
# Bind the merge method from the Hugging Face Qwen2-Audio implementation.
157+
if _QWEN2_AUDIO_MERGE_METHOD is not None:
158+
self._merge_input_ids_with_audio_features = types.MethodType(_QWEN2_AUDIO_MERGE_METHOD, self)
149159

150160
# Store audio token id from config
151161
self.audio_token_id = getattr(config, "audio_token_id", 151646)

tests/functional_tests/test_groups/models/ministral3/test_ministral3_conversion.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
import pytest
2020
import torch
21+
from tokenizers import Tokenizer
22+
from tokenizers.models import WordLevel
23+
from tokenizers.pre_tokenizers import Whitespace
24+
from transformers import PreTrainedTokenizerFast
2125

2226

2327
# Ministral 3 toy model configuration based on typical Ministral 3 structure
@@ -105,19 +109,19 @@ def ministral3_toy_model_path(self, tmp_path_factory):
105109
print(f"Before save - {name}: {param.dtype}")
106110
break # Just check the first parameter
107111

108-
# Create minimal tokenizer files
109-
tokenizer_config = {
110-
"tokenizer_class": "LlamaTokenizer",
111-
"vocab_size": 32768,
112-
"bos_token": "<s>",
113-
"eos_token": "</s>",
114-
"pad_token": "<pad>",
115-
"unk_token": "<unk>",
116-
}
117-
118112
model_dir.mkdir(parents=True, exist_ok=True)
119-
with open(model_dir / "tokenizer_config.json", "w") as f:
120-
json.dump(tokenizer_config, f, indent=2)
113+
114+
# Save a valid tokenizer artifact so both Transformers 5.8 and 5.12 can reload it.
115+
backend_tokenizer = Tokenizer(WordLevel({"<unk>": 0, "<s>": 1, "</s>": 2, "<pad>": 3}, unk_token="<unk>"))
116+
backend_tokenizer.pre_tokenizer = Whitespace()
117+
tokenizer = PreTrainedTokenizerFast(
118+
tokenizer_object=backend_tokenizer,
119+
unk_token="<unk>",
120+
bos_token="<s>",
121+
eos_token="</s>",
122+
pad_token="<pad>",
123+
)
124+
tokenizer.save_pretrained(model_dir)
121125

122126
# Save model and config to directory
123127
model.save_pretrained(model_dir, safe_serialization=True)

tests/unit_tests/models/qwen_audio/test_qwen2_audio_provider.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
from megatron.bridge.models.qwen_audio import Qwen2AudioModelProvider
16+
from megatron.bridge.models.qwen_audio.modeling_qwen2_audio import _QWEN2_AUDIO_MERGE_METHOD
1617

1718

1819
class TestQwen2AudioModelProvider:
@@ -30,6 +31,10 @@ def test_initialization(self):
3031
assert provider.hidden_size == 4096
3132
assert provider.num_attention_heads == 32
3233

34+
def test_hf_audio_merge_method_is_available(self):
35+
"""Test that the installed Transformers version exposes the audio merge helper."""
36+
assert _QWEN2_AUDIO_MERGE_METHOD is not None
37+
3338
def test_audio_specific_defaults(self):
3439
"""Test Qwen2AudioModelProvider audio-specific default configuration."""
3540
provider = Qwen2AudioModelProvider(

uv.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)