Skip to content

Commit bc6363d

Browse files
committed
fix: correct conv1d dimension squeeze for SSM architectures
After reverseShape, PyTorch conv1d [out, 1, kernel] becomes GGML [kernel, 1, out]. The squeeze was checking dims[2]==1 (out_channels, never 1) instead of dims[1]==1, causing 3D tensors that trigger GGML_ASSERT(ggml_is_matrix) in llama.cpp. Made-with: Cursor
1 parent fd0267b commit bc6363d

File tree

3 files changed

+14
-14
lines changed

3 files changed

+14
-14
lines changed

internal/convert/arch_hybrid.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ func (c *hybridConverter) ConvertTensors(w *ggufWriter, sources []tensorSource,
7171
srcCopy := src
7272
idx := i
7373

74-
// Conv1d squeeze for SSM layers
75-
if strings.Contains(hfName, "conv1d") && len(dims) == 3 && dims[2] == 1 {
76-
dims = dims[:2]
74+
// Conv1d squeeze for SSM layers. PyTorch [out, 1, k] → GGML [k, 1, out] → [k, out].
75+
if strings.Contains(hfName, "conv1d") && len(dims) == 3 && dims[1] == 1 {
76+
dims = []uint64{dims[0], dims[2]}
7777
}
7878

7979
ggufName := nameMapper(hfName)

internal/convert/arch_mamba.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ func (c *mambaConverter) ConvertTensors(w *ggufWriter, sources []tensorSource, c
8282
continue
8383
}
8484

85-
// Conv1d squeeze
86-
if strings.Contains(ggufName, "ssm_conv1d") && len(dims) == 3 && dims[2] == 1 {
87-
dims = dims[:2]
85+
// Conv1d squeeze. PyTorch [out, 1, k] → GGML [k, 1, out] → [k, out].
86+
if strings.Contains(ggufName, "ssm_conv1d") && len(dims) == 3 && dims[1] == 1 {
87+
dims = []uint64{dims[0], dims[2]}
8888
}
8989

9090
outputType := chooseOutputTypeForSSM(ggufName, ggmlType, len(src.shape))
@@ -215,9 +215,9 @@ func (c *mamba2Converter) ConvertTensors(w *ggufWriter, sources []tensorSource,
215215
dims := reverseShape(src.shape)
216216
ggufName := nameMapper(hfName)
217217

218-
// Conv1d squeeze
219-
if strings.Contains(ggufName, "ssm_conv1d") && len(dims) == 3 && dims[2] == 1 {
220-
dims = dims[:2]
218+
// Conv1d squeeze. PyTorch [out, 1, k] → GGML [k, 1, out] → [k, out].
219+
if strings.Contains(ggufName, "ssm_conv1d") && len(dims) == 3 && dims[1] == 1 {
220+
dims = []uint64{dims[0], dims[2]}
221221
}
222222

223223
// SSM_A and SSM_D: unsqueeze (add trailing dim=1)
@@ -353,8 +353,8 @@ func (c *jambaConverter) ConvertTensors(w *ggufWriter, sources []tensorSource, c
353353
dims := reverseShape(src.shape)
354354
ggufName := nameMapper(hfName)
355355

356-
if strings.Contains(ggufName, "ssm_conv1d") && len(dims) == 3 && dims[2] == 1 {
357-
dims = dims[:2]
356+
if strings.Contains(ggufName, "ssm_conv1d") && len(dims) == 3 && dims[1] == 1 {
357+
dims = []uint64{dims[0], dims[2]}
358358
}
359359

360360
outputType := chooseOutputTypeForSSM(ggufName, ggmlType, len(src.shape))

internal/convert/arch_qwen35.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ func (c *qwen35Converter) ConvertTensors(w *ggufWriter, sources []tensorSource,
3434
srcCopy := src
3535
idx := i
3636

37-
// Conv1d weights: squeeze trailing dim=1.
38-
if strings.Contains(hfName, "conv1d") && len(dims) == 3 && dims[2] == 1 {
39-
dims = dims[:2]
37+
// Conv1d weights: squeeze middle dim=1. PyTorch [out, 1, k] → GGML [k, 1, out] → [k, out].
38+
if strings.Contains(hfName, "conv1d") && len(dims) == 3 && dims[1] == 1 {
39+
dims = []uint64{dims[0], dims[2]}
4040
}
4141

4242
ggufName := nameMapper(hfName)

0 commit comments

Comments
 (0)