diff --git a/go.mod b/go.mod index 2df15bfd..834ba8ef 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,10 @@ require ( github.com/spf13/cobra v1.7.0 ) -require github.com/rivo/uniseg v0.2.0 // indirect +require ( + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect +) require ( dario.cat/mergo v1.0.0 diff --git a/go.sum b/go.sum index 0dd32085..855c75e5 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,8 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/server/images.go b/server/images.go index 17478fd2..f3fc6dfb 100644 --- a/server/images.go +++ b/server/images.go @@ -19,6 +19,7 @@ import ( "github.com/jmorganca/ollama/api" "github.com/jmorganca/ollama/parser" + "github.com/mitchellh/mapstructure" ) type RegistryOptions struct { @@ -32,7 +33,7 @@ type Model struct { ModelPath string Template string System string - Digest string + Digest string Options api.Options } @@ -135,7 +136,7 @@ func GetModel(name string) (*Model, error) { } model := &Model{ - Name: mp.GetFullTagname(), + Name: mp.GetFullTagname(), Digest: manifest.Config.Digest, } @@ -176,12 +177,17 @@ func GetModel(name string) (*Model, error) { } defer params.Close() - var opts api.Options + // parse model options parameters into a map so that we can see which fields have been specified explicitly + // TODO: once there are no modelfiles in the wild that do not have default options populated this can be removed + var opts map[string]interface{} if err = json.NewDecoder(params).Decode(&opts); err != nil { return nil, err } - model.Options = opts + // update the default options on the model with the options that have been specified + if err := mapstructure.Decode(opts, &model.Options); err != nil { + return nil, err + } } } @@ -494,7 +500,13 @@ func paramsToReader(params map[string][]string) (io.ReadSeeker, error) { } } - bts, err := json.Marshal(opts) + // convert opts to map so that zero fields are not omitted + out := make(map[string]interface{}) + if err := mapstructure.Decode(opts, &out); err != nil { + return nil, err + } + + bts, err := json.Marshal(out) if err != nil { return nil, err } diff --git a/server/routes.go b/server/routes.go index a7d25357..e16de072 100644 --- a/server/routes.go +++ b/server/routes.go @@ -59,12 +59,7 @@ func GenerateHandler(c *gin.Context) { loaded.llm = nil } - opts := api.DefaultOptions() - if err := mergo.Merge(&opts, model.Options, mergo.WithOverride); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) - return - } - + opts := model.Options if err := mergo.Merge(&opts, req.Options, mergo.WithOverride); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return