fix: share tied embeddings with the quantized LM head in ModelBuilder - #2692
Open
Yuri Khrustalev (ykhrustalev) wants to merge 3 commits into
Open
Yuri Khrustalev (ykhrustalev) wants to merge 3 commits into
Yuri Khrustalev (ykhrustalev) wants to merge 3 commits into
Conversation
patched_make_embedding wrote a dense Gather for every embedding Olive had not quantized, bypassing the builder's shared_embeddings path, so tied INT4 models also stored the table in FP32/FP16. LFM2.5-1.2B-Instruct CPU INT4 drops from 1.4 GB to 0.9 GB with the same accuracy.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Copilot started reviewing on behalf of
Yuri Khrustalev (ykhrustalev)
September 26, 2026 05:16
View session
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The embedding fallback can be invoked when the native method is unavailable, causing non-quantized builds to fail.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Fixes tied INT4 embedding export by reusing the native builder’s shared-embedding behavior.
Changes:
- Delegates unquantized embeddings to the native builder.
- Preserves the original embedding method across repeated patching.
- Adds tied and untied INT4 embedding tests.
| File | Summary |
|---|---|
test/passes/onnx/test_model_builder.py |
Adds regression coverage for tied embeddings and repeated patching. |
olive/passes/onnx/model_builder.py |
Updates embedding delegation; requires a callable fallback when the native method is unavailable. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The builder reshapes the quantized LM head to hidden_size columns for tied embeddings, which fails at runtime when hidden_size isn't a multiple of the int4 block size (microsoft/onnxruntime-genai#2628). The test sets block_size through extra_options because onnxruntime-genai 0.17 ignores the int4_ aliases.
Every onnxruntime-genai release defines Model.make_embedding, so the None default only hid a missing method until the first embedding. The fake-module test left its stub stored on the patch, so a real build that ran after it in the same process emitted no embedding.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
patched_make_embeddingwrites its own table for every embedding Olive didn't quantize, bypassing the builder'sshared_embeddingspath (on by default for tied models). Tied models built at INT4 therefore store a second embedding table next to the quantized LM head: full precision underk_quant, which leavesGatherunquantized, and INT4 otherwise.Solution
make_embeddingfor embeddings Olive didn't quantize, aspatched_make_packed_matmul_int4already doesmaybe_patch_quantruns more than onceshared_embeddings: falseinextra_optionskeeps the separate tableTesting
test_model_builder_int4_embeddingscovers tied, untied and padded-block tiny Llama; the tied case fails without the fixblock_size: 256(hidden size 896) keeps its table and matches the previous build exactlyRefs microsoft/onnxruntime-genai#2628