Skip to content

Add genie_overrides to QairtEncapsulation for GenAIConfig customization#2469

Open
qti-kromero wants to merge 29 commits into
microsoft:mainfrom
CodeLinaro:dev/qti-kromero/qairt-encapsulation-genie-overrides
Open

Add genie_overrides to QairtEncapsulation for GenAIConfig customization#2469
qti-kromero wants to merge 29 commits into
microsoft:mainfrom
CodeLinaro:dev/qti-kromero/qairt-encapsulation-genie-overrides

Conversation

@qti-kromero

@qti-kromero qti-kromero commented May 20, 2026

Copy link
Copy Markdown
Contributor

Introduce a genie_overrides PassConfigParam that deep-merges user-supplied fields into the GenAIConfig before LLMContainer.export() bakes them into the Genie DLC. This allows callers to override any GenAIConfig field (engine config, positional encoding, etc.) without modifying QairtGenAIBuilder or QairtPipelinePass.

Nested dicts are merged recursively so only the specified keys are changed; all other values set by the upstream builder pass are preserved.

Describe your changes

Add a genie_overrides parameter to QairtEncapsulation. When provided, the value is deep-merged into the GenAIConfig dict just before LLMContainer.export() is called. The merge is recursive: nested dicts are merged key-by-key so callers only need to specify the fields they want to change. A helper _deep_merge utility handles the recursion and is unit-tested directly. Integration tests cover round-trip behavior with nested overrides and verify that unrelated config fields are left untouched.

Checklist before requesting a review

  • Add unit tests for this change.

  • Make sure all tests can pass.

  • Update documents if necessary.

  • Lint and apply fixes to your code by running lintrunner -a

  • Is this a user-facing change? If yes, give a description of this change to be included in the release notes.

    Release note: QairtEncapsulation now accepts genie_overrides, backend_extensions_overrides, and engine_config_overrides parameters that allow users to override the behavior of underlying Genie components when building Genie DLCs.

(Optional) Issue link

N/A

Introduce a genie_overrides PassConfigParam that deep-merges user-supplied
fields into the GenAIConfig before LLMContainer.export() bakes them into the
Genie DLC. This allows callers to override any GenAIConfig field (engine config,
positional encoding, etc.) without modifying QairtGenAIBuilder or QairtPipelinePass.

Nested dicts are merged recursively so only the specified keys are changed;
all other values set by the upstream builder pass are preserved.
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
…ensions customization

Adds a backend_extensions_override PassConfigParam that is deep-merged
into the LLMContainer's existing _backend_extensions_config before the
Genie DLC is produced. Uses the raw JSON key names (hyphens) as they
appear in backend_extensions.json. Nested dicts are merged recursively
so only specified keys are overridden; all other defaults set by the
builder are preserved. If the container has no existing backend
extensions config, the override becomes the entire config.

Includes 4 tests covering default config presence, merge into existing
config, merge from empty, and no-op when override is None. Also drops
one fragile identity assertion from the existing genie_overrides test.
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread olive/passes/qairt/encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
…apsulation

Aligns with qairt-dev's rename of HTPExecutionConfig → HTPEngineConfig wrapped
in EngineConfig (AISW-184594). The param now accepts a nested dict:
  {"n_threads": 0, "htp": {"cpu_mask": "0xe0", "poll": false, ...}}
Top-level keys map to EngineConfig, "htp" sub-dict maps to HTPEngineConfig.
…key deletion

- Lists of dicts are merged element-wise by index, allowing recipe overrides
  to target nested list entries (e.g. context[0], devices[0]) without
  replacing the entire list
- A None override value deletes the corresponding key from the result,
  enabling removal of builder-generated keys (e.g. "graphs": null)
…ain bug

- encapsulation.py: add # pylint: disable=protected-access on _gen_ai_config
  and _backend_extensions_config accesses
- test_encapsulation.py: rename htp_execution_overrides → engine_config_overrides
  throughout; fix docstring capitalization; fix pre-existing test_encapsulation_
  genie_overrides_applied failure caused by mock._gen_ai_config being replaced
  after model_validate() — capture original mock before running the pass
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Comment thread test/passes/qairt/test_encapsulation.py Fixed
Move _make_minimal_onnx and a mock_container fixture into conftest.py,
replace inline mock_save_func/save patches and dead mock_helper.make_*
stubs across all tests, parametrize the _default_config and
missing-required-file assertions, drop the redundant valid-version test,
and add coverage for EPContext node output, QAIRT_LOG_LEVEL env wiring,
and sequence_lengths plumbing into create_genai_config.
@qti-kromero qti-kromero marked this pull request as ready for review June 5, 2026 19:10
Copilot AI review requested due to automatic review settings June 5, 2026 19:10

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR extends the QAIRT encapsulation pass to support deep-merged override configs (GenAIConfig, backend extensions, and engine config), and refactors/expands the test suite to validate these behaviors.

Changes:

  • Added _deep_merge utility and new pass config params: genie_overrides, backend_extensions_overrides, engine_config_overrides.
  • Updated encapsulation execution to apply overrides and to optionally pass engine_config to LLMContainer.export() when supported.
  • Refactored tests to use shared fixtures and added new unit/integration tests for merge/override behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
olive/passes/qairt/encapsulation.py Adds deep-merge + override plumbing and conditional engine_config export support.
test/passes/qairt/conftest.py Introduces shared ONNX writer helper and a reusable mocked container fixture.
test/passes/qairt/test_encapsulation.py Refactors existing tests and adds coverage for overrides, deep merge, env var, and EPContext node validation.

Comment thread test/passes/qairt/test_encapsulation.py Outdated
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py
Comment thread test/passes/qairt/test_encapsulation.py Outdated
Comment thread test/passes/qairt/conftest.py Outdated
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 21:49

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread test/passes/qairt/utils.py Outdated
Comment thread olive/passes/qairt/encapsulation.py
Comment thread test/passes/qairt/test_encapsulation.py Outdated
Comment thread olive/passes/qairt/encapsulation.py
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 22:55

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

Comment thread test/passes/qairt/utils.py Outdated
Comment thread test/passes/qairt/utils.py Outdated
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py Outdated
Comment thread olive/passes/qairt/encapsulation.py
Comment thread test/passes/qairt/test_encapsulation.py Outdated
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 23:07

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread olive/passes/qairt/encapsulation.py
Comment thread test/passes/qairt/utils.py Outdated
Comment thread olive/passes/qairt/encapsulation.py Outdated
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 23:23

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread test/passes/qairt/test_encapsulation.py
Comment thread test/passes/qairt/test_encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 23:34

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

Comment thread test/passes/qairt/utils.py
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py Outdated
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 23:41

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

Comment thread test/passes/qairt/utils.py
Comment thread test/passes/qairt/utils.py
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py
@qti-kromero qti-kromero requested a review from Copilot June 8, 2026 23:49

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

Comment thread test/passes/qairt/utils.py Outdated
Comment thread test/passes/qairt/utils.py Outdated
Comment thread test/passes/qairt/utils.py
Comment thread olive/passes/qairt/encapsulation.py
@qti-kromero qti-kromero requested a review from Copilot June 9, 2026 17:05

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Comment thread olive/passes/qairt/encapsulation.py
Comment thread test/passes/qairt/utils.py
Comment thread test/passes/qairt/utils.py
@qti-kromero qti-kromero requested a review from Copilot June 9, 2026 17:18

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Comment thread test/passes/qairt/test_encapsulation.py
Comment thread olive/passes/qairt/encapsulation.py Outdated
@qti-kromero qti-kromero requested a review from Copilot June 9, 2026 18:09

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.

Comment on lines +23 to +26
input_tensor = onnx.helper.make_tensor_value_info("input_ids", TensorProto.INT32, ["batch_size", "sequence_length"])
output_tensor = onnx.helper.make_tensor_value_info(
"logits", TensorProto.FLOAT, ["batch_size", 1, "sequence_length"]
)
MAX_GENIE_CONTEXT_LENGTH = 4096


def _deep_merge(base: dict, overrides: dict) -> dict:
elements are appended. A ``None`` override value deletes the key from
the result. The returned dict shares no references with *base*.
"""
result = copy.deepcopy(base)
Comment on lines +42 to +43
elif k in result and isinstance(result[k], dict) and isinstance(v, dict):
result[k] = _deep_merge(result[k], v)
Comment on lines +155 to +156
export_kwargs = {"export_format": qairt.ExportFormat.LM_EXECUTOR}
if config.engine_config_overrides:
Comment on lines +165 to +169
overrides = dict(config.engine_config_overrides)
htp_overrides = overrides.pop("htp", None)
htp_cfg = qairt_genai.HTPEngineConfig(**(htp_overrides or {})) if htp_overrides is not None else None
engine_cfg = qairt_genai.EngineConfig(**overrides, htp=htp_cfg)
export_kwargs["engine_config"] = engine_cfg


def test_encapsulation_successful_execution(tmp_path, mock_qairt_model, mock_qairt_modules):
from test.passes.qairt.utils import make_minimal_onnx as _make_minimal_onnx
@qti-kromero

Copy link
Copy Markdown
Contributor Author

@xiaoyu-work @xieofxie @jambayk requesting human reviewer, copilot is wonking out and making circular suggestions

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.

3 participants