Skip to content

Commit fa12d2b

Browse files
committed
[NPUW] Model builder: name projection MatMuls optimum-style for dynamic LoRA
make_linear named the projection MatMul with the bare layer name ("model.layers.N.self_attn.q_proj"). optimum-exported models name it "<layer>/ov_ext::linear/MatMul". GenAI's dynamic-LoRA path builds its lora_state_* variable ids from the MatMul friendly name, and NPUW's ReshapeToStatic only pins the LoRA rank static for ids matching ".*MatMul\.(A|B|alpha)". With a bare name the rank stays dynamic and NPU compilation throws "to_shape was called on a dynamic shape". Append "/MatMul" to the MatMul friendly name so GenAI --lora --lora_mode dynamic compiles for builder-generated models. Add a unit test asserting projection MatMuls carry the /MatMul suffix.
1 parent 8379d9b commit fa12d2b

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

src/plugins/intel_npu/tests/functional/behavior/npuw/test_engine/models/model_builder.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ ov::Output<ov::Node> make_linear(const ov::Output<ov::Node>& input,
7272
auto weight_output = weight_fn(name + ".weight", ov::Shape{out_features, in_features}, precision);
7373

7474
auto matmul = std::make_shared<ov::opset11::MatMul>(input, weight_output, false, true);
75-
matmul->set_friendly_name(name);
75+
// Mirror optimum-exported naming ("<layer>/ov_ext::linear/MatMul"). GenAI's
76+
// dynamic-LoRA path derives its lora_state_* variable ids from this MatMul's
77+
// friendly name, and NPUW's ReshapeToStatic only pins the LoRA rank static for
78+
// ids matching ".*MatMul\\.(A|B|alpha)". A bare name (no "MatMul") leaves the
79+
// rank dynamic -> to_shape throws at compile. Keep the "MatMul" suffix.
80+
matmul->set_friendly_name(name + "/MatMul");
7681

7782
ov::Output<ov::Node> result = matmul->output(0);
7883

src/plugins/intel_npu/tests/unit/npuw/model_builder_lora_test.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,27 @@ TEST(ModelBuilderLoraTest, BuildLlmWithoutLoraHasNoLoraParameters) {
5353
EXPECT_FALSE(has_param(model, "lora_state_"));
5454
}
5555

56+
// Projection MatMuls must be named optimum-style ("<layer>/MatMul"). GenAI's
57+
// dynamic-LoRA path derives lora_state_* variable ids from the MatMul friendly
58+
// name, and NPUW's ReshapeToStatic only pins the LoRA rank static for ids
59+
// matching ".*MatMul\\.(A|B|alpha)". A bare name leaves the rank dynamic and
60+
// compilation throws "to_shape was called on a dynamic shape".
61+
TEST(ModelBuilderLoraTest, ProjectionMatMulsAreNamedOptimumStyle) {
62+
auto model = ov::test::npuw::build_llm_test_model();
63+
ASSERT_TRUE(model);
64+
bool found_qproj_matmul = false;
65+
for (const auto& op : model->get_ordered_ops()) {
66+
if (std::string(op->get_type_name()) != "MatMul") {
67+
continue;
68+
}
69+
const auto name = op->get_friendly_name();
70+
if (name.find("q_proj") != std::string::npos) {
71+
EXPECT_NE(name.find("/MatMul"), std::string::npos)
72+
<< "projection MatMul '" << name << "' must end in /MatMul";
73+
found_qproj_matmul = true;
74+
}
75+
}
76+
EXPECT_TRUE(found_qproj_matmul);
77+
}
78+
5679
} // namespace

0 commit comments

Comments
 (0)