mlx: "requires" in modelfile is being ignored for mlx based models (#16469)

This change fixes an issue in `ollama create --experimental` which
is currently ignoring the REQUIRES command in a Modelfile.
This commit is contained in:
Patrick Devine
2026-06-03 13:10:57 -07:00
committed by GitHub
parent 5f56a289b3
commit e5a38739b4
2 changed files with 61 additions and 1 deletions

View File

@@ -16,6 +16,8 @@ import (
"slices"
"strings"
"golang.org/x/mod/semver"
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/manifest"
modelparsers "github.com/ollama/ollama/model/parsers"
@@ -38,6 +40,7 @@ type ModelfileConfig struct {
Draft string
Parser string
Renderer string
Requires string
Parameters map[string]any
}
@@ -75,7 +78,20 @@ func ConfigFromModelfile(modelfile *parser.Modelfile) (string, *ModelfileConfig,
mfConfig.Parser = cmd.Args
case "renderer":
mfConfig.Renderer = cmd.Args
case "adapter", "message", "requires":
case "requires":
requires := cmd.Args
if !strings.HasPrefix(requires, "v") {
requires = "v" + requires
}
if !semver.IsValid(requires) {
return "", nil, fmt.Errorf("requires must be a valid semver (e.g. 0.14.0)")
}
minVersion := "v" + MinOllamaVersion
if semver.Compare(requires, minVersion) < 0 {
return "", nil, fmt.Errorf("requires %s is below the minimum supported version %s for safetensors models", strings.TrimPrefix(requires, "v"), MinOllamaVersion)
}
mfConfig.Requires = strings.TrimPrefix(requires, "v")
case "adapter", "message":
continue
default:
if slices.Contains(ignoredModelfileParameters, cmd.Name) {
@@ -518,6 +534,9 @@ func newManifestWriter(opts CreateOptions, capabilities []string, parserName, re
}
configData.Capabilities = caps
configData.Requires = MinOllamaVersion
if opts.Modelfile != nil && opts.Modelfile.Requires != "" {
configData.Requires = opts.Modelfile.Requires
}
configData.Parser = resolveParserName(opts.Modelfile, parserName)
configData.Renderer = resolveRendererName(opts.Modelfile, rendererName)
if opts.Modelfile != nil && opts.Modelfile.Draft != "" {

View File

@@ -46,6 +46,7 @@ func TestConfigFromModelfile(t *testing.T) {
FROM ./model
DRAFT ./assistant
TEMPLATE {{ .Prompt }}
REQUIRES 0.20.0
PARAMETER temperature 0.7
PARAMETER stop USER:
PARAMETER stop ASSISTANT:
@@ -71,6 +72,10 @@ PARAMETER stop ASSISTANT:
t.Fatalf("Draft = %q, want %q", mfConfig.Draft, "./assistant")
}
if mfConfig.Requires != "0.20.0" {
t.Fatalf("Requires = %q, want %q", mfConfig.Requires, "0.20.0")
}
if got := mfConfig.Parameters["temperature"]; got != float32(0.7) {
t.Fatalf("temperature = %#v, want %v", got, float32(0.7))
}
@@ -80,6 +85,42 @@ PARAMETER stop ASSISTANT:
}
}
func TestConfigFromModelfile_RequiresBelowMinimum(t *testing.T) {
modelfile, err := parser.ParseFile(strings.NewReader(`
FROM ./model
REQUIRES 0.14.0
`))
if err != nil {
t.Fatal(err)
}
_, _, err = ConfigFromModelfile(modelfile)
if err == nil {
t.Fatal("expected error for REQUIRES below minimum, got nil")
}
if !strings.Contains(err.Error(), "minimum supported version") {
t.Fatalf("error = %v, want error mentioning minimum supported version", err)
}
}
func TestConfigFromModelfile_RequiresInvalidSemver(t *testing.T) {
modelfile, err := parser.ParseFile(strings.NewReader(`
FROM ./model
REQUIRES not-a-version
`))
if err != nil {
t.Fatal(err)
}
_, _, err = ConfigFromModelfile(modelfile)
if err == nil {
t.Fatal("expected error for invalid semver, got nil")
}
if !strings.Contains(err.Error(), "valid semver") {
t.Fatalf("error = %v, want semver error", err)
}
}
func TestModelfileConfig_Empty(t *testing.T) {
config := &ModelfileConfig{}