Files
ollama/compatmigrate/laguna.go
Daniel Hiltgen 75b952780f llama-server: prepare to remove compatibility patch
Add manifest-list storage so runner-specific manifests can coexist under one tag while preserving existing v1 tags as best-effort downgrade anchors. Show/list/copy/remove/pull/push now understand runner and digest selection and transfer referenced child manifests and layers.

Add lazy local compatibility migration for legacy Ollama GGUFs into llama.cpp-compatible children, covering the patched model families and preserving parser/renderer, templates, projectors, media metadata, split GGUFs, and MTP/draft tensors where applicable.

Extend create/import/conversion paths for the same compatibility rules, harden manifest-list combine validation, and add focused manifest, migration, transfer, and integration coverage for first-load conversion plus chat/tools/vision/audio/embedding behavior.
2026-09-24 19:25:52 -07:00

63 lines
1.7 KiB
Go

package compatmigrate
import (
"strings"
)
type lagunaMigrator struct{}
// Mirrors detect_ollama_laguna in llama/compat/llama-ollama-compat.cpp; keep the two in sync.
func (lagunaMigrator) NeedsMigration(src *SourceModel) bool {
if src.GGUF.KeyValue("general.architecture").String() != "laguna" {
return false
}
return rawGGUFKeyExists(src.GGUF, "laguna.rope.swa.dimension_count") ||
rawGGUFKeyExists(src.GGUF, "laguna.rope.swa.freq_base") ||
sourceTensorExists(src, "blk.0.attn_g.weight")
}
func (lagunaMigrator) Migrate(src *SourceModel) (*Result, error) {
tensors, err := readAllSourceTensors(src)
if err != nil {
return nil, err
}
modelTensors := make([]*outTensor, 0, len(tensors))
for _, tensor := range tensors {
modelTensors = append(modelTensors, copyTensor(lagunaTensorName(tensor.name), tensor))
}
modelKV := outKV{}
for _, keyValue := range src.GGUF.KeyValues() {
if !keyValue.Valid() {
continue
}
key := keyValue.Key
value := normalizeGGUFValue(keyValue.Any())
switch {
case key == "laguna.rope.swa.dimension_count":
modelKV["laguna.rope.dimension_count_swa"] = value
case key == "laguna.rope.swa.freq_base":
modelKV["laguna.rope.freq_base_swa"] = value
case strings.HasPrefix(key, "general."), strings.HasPrefix(key, "tokenizer."), strings.HasPrefix(key, "laguna."):
modelKV[key] = value
}
}
if _, ok := modelKV["general.architecture"]; !ok {
modelKV["general.architecture"] = "laguna"
}
return &Result{
ModelKV: modelKV,
ModelTensors: modelTensors,
}, nil
}
func lagunaTensorName(name string) string {
if base, ok := strings.CutSuffix(name, ".attn_g.weight"); ok {
return base + ".attn_gate.weight"
}
return name
}