create: inherit FROM model's renderer/parser

On main, the `RENDERER` and `PARSER` fields from the `Modelfile` don't
get propagated to a new model created with a `req.From` parameter. This
is easily triggered via `ollama run qwen3-coder`, then running some save
command like `/save qwen3-coder-custom`.

Added a regression test for this, and then open the config for the
"from" model in order to use its renderer/parser as a default for the
new model. This will fix the CLI and also API-based creates.

Fixes: https://github.com/ollama/ollama/issues/12792
This commit is contained in:
Devon Rifkin
2025-10-27 15:14:19 -07:00
parent ad6f6a1d29
commit 1bdd816910
2 changed files with 87 additions and 0 deletions

View File

@@ -188,6 +188,72 @@ func TestCreateFromModel(t *testing.T) {
})
}
func TestCreateFromModelInheritsRendererParser(t *testing.T) {
gin.SetMode(gin.TestMode)
p := t.TempDir()
t.Setenv("OLLAMA_MODELS", p)
var s Server
const (
renderer = "custom-renderer"
parser = "custom-parser"
)
_, digest := createBinFile(t, nil, nil)
w := createRequest(t, s.CreateHandler, api.CreateRequest{
Name: "base",
Files: map[string]string{"base.gguf": digest},
Renderer: renderer,
Parser: parser,
Stream: &stream,
})
if w.Code != http.StatusOK {
t.Fatalf("expected status code 200, actual %d", w.Code)
}
w = createRequest(t, s.CreateHandler, api.CreateRequest{
Name: "child",
From: "base",
Stream: &stream,
})
if w.Code != http.StatusOK {
t.Fatalf("expected status code 200, actual %d", w.Code)
}
manifest, err := ParseNamedManifest(model.ParseName("child"))
if err != nil {
t.Fatalf("parse manifest: %v", err)
}
if manifest.Config.Digest == "" {
t.Fatalf("unexpected empty config digest for child manifest")
}
configPath, err := GetBlobsPath(manifest.Config.Digest)
if err != nil {
t.Fatalf("config blob path: %v", err)
}
cfgFile, err := os.Open(configPath)
if err != nil {
t.Fatalf("open config blob: %v", err)
}
defer cfgFile.Close()
var cfg ConfigV2
if err := json.NewDecoder(cfgFile).Decode(&cfg); err != nil {
t.Fatalf("decode config: %v", err)
}
if cfg.Renderer != renderer {
t.Fatalf("expected renderer %q, got %q", renderer, cfg.Renderer)
}
if cfg.Parser != parser {
t.Fatalf("expected parser %q, got %q", parser, cfg.Parser)
}
}
func TestCreateRemovesLayers(t *testing.T) {
gin.SetMode(gin.TestMode)