From 89e31cc808f7c228171d28d78c164d311e6e69b5 Mon Sep 17 00:00:00 2001 From: Kyle Romero Date: Wed, 17 Jun 2026 21:10:08 +0000 Subject: [PATCH 1/3] Forward ARN sequence lengths from QairtPipelinePass to QairtEncapsulation QairtEncapsulation uses sequence_lengths from model_attributes to compute max_length in genai_config.json. QairtGenAIBuilder populates this via its own config, but QairtPipelinePass had no equivalent path. Extract the arn list from the genai_builder.transform_options in the YAML recipe and pass it through model_attributes so QairtEncapsulation can pick it up. --- olive/passes/qairt/pipeline.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/olive/passes/qairt/pipeline.py b/olive/passes/qairt/pipeline.py index ca630774e..23745d560 100644 --- a/olive/passes/qairt/pipeline.py +++ b/olive/passes/qairt/pipeline.py @@ -154,4 +154,8 @@ def _run_for_config( if src.exists() and not dst.exists(): shutil.copy2(src, dst) - return QairtModelHandler(model_path=output_model_path) + # Forward AR decode lengths to QairtEncapsulation so it can compute max_length correctly. + # arn in the pipeline recipe is the equivalent of sequence_lengths in QairtGenAIBuilder. + arn = recipe_data.get("stages", {}).get("genai_builder", {}).get("transform_options", {}).get("arn") + model_attrs = {"sequence_lengths": arn} if arn else {} + return QairtModelHandler(model_path=output_model_path, model_attributes=model_attrs) From 2cd2fb07eec68b965f1f2205429c22d561a55a72 Mon Sep 17 00:00:00 2001 From: Kyle Romero Date: Tue, 23 Jun 2026 19:56:39 +0000 Subject: [PATCH 2/3] Add unit tests for ARN forwarding in QairtPipelinePass Covers the case where arn is present in genai_builder.transform_options and forwarded as sequence_lengths in model_attributes, and the case where arn is absent and sequence_lengths is not set. --- test/passes/qairt/test_pipeline_pass.py | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/passes/qairt/test_pipeline_pass.py b/test/passes/qairt/test_pipeline_pass.py index 09ab4c096..0083809b5 100644 --- a/test/passes/qairt/test_pipeline_pass.py +++ b/test/passes/qairt/test_pipeline_pass.py @@ -228,6 +228,52 @@ def test_pipeline_pass_missing_recipe_file(tmp_path, mock_hf_model, mock_pipelin pipeline_pass.run(mock_hf_model, str(output_path)) +def test_pipeline_pass_forwards_arn_as_sequence_lengths(tmp_path, mock_hf_model, recipe_file, mock_pipeline_modules): + """ARN from genai_builder.transform_options is forwarded as sequence_lengths in model_attributes.""" + output_path = tmp_path / "output" + + mock_pipeline_modules["Recipe"].from_file.return_value = { + "stages": { + "genai_builder": { + "transform_options": { + "arn": [128, 1024, 4096], + } + } + } + } + + pipeline_pass = create_pass_from_dict( + QairtPipelinePass, + {"recipe": str(recipe_file)}, + disable_search=True, + ) + + result = pipeline_pass.run(mock_hf_model, str(output_path)) + + assert isinstance(result, QairtModelHandler) + assert result.model_attributes == {"sequence_lengths": [128, 1024, 4096]} + + +def test_pipeline_pass_no_arn_yields_empty_model_attributes( + tmp_path, mock_hf_model, recipe_file, mock_pipeline_modules +): + """When genai_builder.transform_options has no arn, sequence_lengths is not set in model_attributes.""" + output_path = tmp_path / "output" + + mock_pipeline_modules["Recipe"].from_file.return_value = {"stages": {"genai_builder": {"transform_options": {}}}} + + pipeline_pass = create_pass_from_dict( + QairtPipelinePass, + {"recipe": str(recipe_file)}, + disable_search=True, + ) + + result = pipeline_pass.run(mock_hf_model, str(output_path)) + + assert isinstance(result, QairtModelHandler) + assert "sequence_lengths" not in (result.model_attributes or {}) + + def test_pipeline_pass_import_error(tmp_path, mock_hf_model, recipe_file): """Test that ImportError is raised if qairt cannot be imported.""" From a6f38a21204456983aff12504e496e2201fa3a68 Mon Sep 17 00:00:00 2001 From: Kyle Romero Date: Tue, 23 Jun 2026 20:06:56 +0000 Subject: [PATCH 3/3] Validate arn type in QairtPipelinePass before forwarding to QairtEncapsulation QairtEncapsulation calls min(sequence_lengths) on the forwarded value, so a malformed YAML arn (string, bare int, empty list, mixed types) would fail with an opaque error. Raise a clear ValueError at the pipeline pass boundary instead. --- olive/passes/qairt/pipeline.py | 4 ++++ test/passes/qairt/test_pipeline_pass.py | 27 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/olive/passes/qairt/pipeline.py b/olive/passes/qairt/pipeline.py index 23745d560..d012072cc 100644 --- a/olive/passes/qairt/pipeline.py +++ b/olive/passes/qairt/pipeline.py @@ -157,5 +157,9 @@ def _run_for_config( # Forward AR decode lengths to QairtEncapsulation so it can compute max_length correctly. # arn in the pipeline recipe is the equivalent of sequence_lengths in QairtGenAIBuilder. arn = recipe_data.get("stages", {}).get("genai_builder", {}).get("transform_options", {}).get("arn") + if arn is not None and (not isinstance(arn, list) or not arn or not all(isinstance(v, int) for v in arn)): + raise ValueError( + f"stages.genai_builder.transform_options.arn must be a non-empty list of integers, got: {arn!r}" + ) model_attrs = {"sequence_lengths": arn} if arn else {} return QairtModelHandler(model_path=output_model_path, model_attributes=model_attrs) diff --git a/test/passes/qairt/test_pipeline_pass.py b/test/passes/qairt/test_pipeline_pass.py index 0083809b5..b4ae1b60a 100644 --- a/test/passes/qairt/test_pipeline_pass.py +++ b/test/passes/qairt/test_pipeline_pass.py @@ -254,6 +254,33 @@ def test_pipeline_pass_forwards_arn_as_sequence_lengths(tmp_path, mock_hf_model, assert result.model_attributes == {"sequence_lengths": [128, 1024, 4096]} +@pytest.mark.parametrize( + "bad_arn", + [ + "128,1024", # string instead of list + 1024, # bare int + [], # empty list + [128, "1024"], # list with non-int element + ], +) +def test_pipeline_pass_invalid_arn_raises(tmp_path, mock_hf_model, recipe_file, mock_pipeline_modules, bad_arn): + """A malformed arn value raises ValueError with a clear message before propagating downstream.""" + output_path = tmp_path / "output" + + mock_pipeline_modules["Recipe"].from_file.return_value = { + "stages": {"genai_builder": {"transform_options": {"arn": bad_arn}}} + } + + pipeline_pass = create_pass_from_dict( + QairtPipelinePass, + {"recipe": str(recipe_file)}, + disable_search=True, + ) + + with pytest.raises(ValueError, match="must be a non-empty list of integers"): + pipeline_pass.run(mock_hf_model, str(output_path)) + + def test_pipeline_pass_no_arn_yields_empty_model_attributes( tmp_path, mock_hf_model, recipe_file, mock_pipeline_modules ):