Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"export": {
"opset_version": 17,
"batch_size": 1,
"export_params": true,
"do_constant_folding": true,
"verbose": false,
"dynamo": false,
"enable_hierarchy_tags": true,
"clean_onnx": false,
"hierarchy_tag_format": "full",
"input_tensors": [
{
"name": "input_values",
"dtype": "float32",
"shape": [
1,
16000
],
"value_range": [
-1,
1
]
}
],
"output_tensors": [
{
"name": "logits"
}
]
},
"optim": {},
"quant": {
"mode": "fp16",
"samples": 10,
"calibration_method": "minmax",
"weight_type": "uint8",
"activation_type": "uint8",
"per_channel": false,
"symmetric": false,
"weight_symmetric": null,
"activation_symmetric": null,
"save_calibration": false,
"distribution": "uniform",
"seed": null,
"calibration_load_path": null,
"calibration_save_path": null,
"op_types_to_quantize": null,
"nodes_to_exclude": null,
"fp16_keep_io_types": true,
"fp16_op_block_list": null
},
"compile": null,
"loader": {
"task": "automatic-speech-recognition",
"model_class": "AutoModelForCTC",
"model_type": "wav2vec2",
"trust_remote_code": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"export": {
"opset_version": 17,
"batch_size": 1,
"export_params": true,
"do_constant_folding": true,
"verbose": false,
"dynamo": false,
"enable_hierarchy_tags": true,
"clean_onnx": false,
"hierarchy_tag_format": "full",
"input_tensors": [
{
"name": "input_values",
"dtype": "float32",
"shape": [
1,
16000
],
"value_range": [
-1,
1
]
}
],
"output_tensors": [
{
"name": "logits"
}
]
},
"optim": {},
"quant": null,
"compile": null,
"loader": {
"task": "automatic-speech-recognition",
"model_class": "AutoModelForCTC",
"model_type": "wav2vec2",
"trust_remote_code": true
}
}
8 changes: 6 additions & 2 deletions src/winml/modelkit/loader/resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,9 @@ def resolve_task(
) or _get_custom_model_class(model_type_norm, normalized)
if resolved is None:
try:
resolved = TasksManager.get_model_class_for_task(normalized, framework="pt")
resolved = TasksManager.get_model_class_for_task(
normalized, framework="pt", model_type=model_type_norm or 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.

Please pass the raw model_type to TasksManager here rather than model_type_norm. The normalization is needed for WinML's internal mapping keys, but Optimum registers some model types with underscores. For example, speech_to_text is a supported Transformers model type; converting it to speech-to-text prevents Optimum from matching AutoModelForSpeechSeq2Seq, so explicit ASR resolution raises instead of resolving the class. The Stage 2 call added by this PR has the same issue. Please keep model_type_norm for _get_custom_model_class, pass model_type to both TasksManager calls, and add an underscore-containing regression case.

)
except KeyError as e:
if composite is not None:
# Pure composite (e.g. table-question-answering): no single model class
Expand Down Expand Up @@ -644,7 +646,9 @@ def resolve_task(
resolved = _get_custom_model_class(model_type_norm, opt_task)
if resolved is None:
try:
resolved = TasksManager.get_model_class_for_task(opt_task, framework="pt")
resolved = TasksManager.get_model_class_for_task(
opt_task, framework="pt", model_type=model_type_norm or None
Comment thread
xieofxie marked this conversation as resolved.
)
except Exception:
resolved = _resolve_model_class_from_config(config) # arch fallback

Expand Down
47 changes: 47 additions & 0 deletions tests/unit/loader/test_config_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,50 @@ def test_model_type_normalization(
f"Expected {expected_class_name} for model_type='{raw_model_type}', "
f"got {r.model_class.__name__}. model_type normalization may be broken."
)


class TestExplicitTaskWithModelType:
"""Explicit task without model_class must still use model_type for disambiguation.

Regression: when task is supplied but model_class is not, the USER_TASK branch
must pass model_type to get_model_class_for_task so that architectures sharing
a task (e.g. Wav2Vec2 CTC vs Whisper Seq2Seq for automatic-speech-recognition)
resolve to the correct model class.
"""

@pytest.mark.parametrize(
"model_type,arch,task,expected_class",
[
pytest.param(
"wav2vec2",
"Wav2Vec2ForCTC",
"automatic-speech-recognition",
"AutoModelForCTC",
id="wav2vec2-asr-resolves-to-ctc",
),
pytest.param(
"whisper",
"WhisperForConditionalGeneration",
"automatic-speech-recognition",
"AutoModelForSpeechSeq2Seq",
id="whisper-asr-resolves-to-seq2seq",
),
],
)
def test_explicit_task_respects_model_type(
self,
model_type: str,
arch: str,
task: str,
expected_class: str,
make_mock_config,
) -> None:
"""Explicit task + model_type resolves the model-type-specific class."""
config = make_mock_config(model_type, [arch])

r = resolve_task(config, task=task)

assert r.model_class.__name__ == expected_class, (
f"Expected {expected_class} for model_type='{model_type}' with task='{task}', "
f"got {r.model_class.__name__}. USER_TASK branch may not be passing model_type."
)
Loading