|
@@ -21,7 +21,6 @@ import (
|
|
|
"runtime"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
- "text/template"
|
|
|
|
|
|
"golang.org/x/exp/slices"
|
|
|
|
|
@@ -64,6 +63,48 @@ func (m *Model) IsEmbedding() bool {
|
|
|
return slices.Contains(m.Config.ModelFamilies, "bert") || slices.Contains(m.Config.ModelFamilies, "nomic-bert")
|
|
|
}
|
|
|
|
|
|
+func (m *Model) Commands() (cmds []parser.Command) {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "model", Args: m.ModelPath})
|
|
|
+
|
|
|
+ if m.Template != "" {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "template", Args: m.Template})
|
|
|
+ }
|
|
|
+
|
|
|
+ if m.System != "" {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "system", Args: m.System})
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, adapter := range m.AdapterPaths {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "adapter", Args: adapter})
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, projector := range m.ProjectorPaths {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "projector", Args: projector})
|
|
|
+ }
|
|
|
+
|
|
|
+ for k, v := range m.Options {
|
|
|
+ switch v := v.(type) {
|
|
|
+ case []any:
|
|
|
+ for _, s := range v {
|
|
|
+ cmds = append(cmds, parser.Command{Name: k, Args: fmt.Sprintf("%v", s)})
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ cmds = append(cmds, parser.Command{Name: k, Args: fmt.Sprintf("%v", v)})
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, license := range m.License {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "license", Args: license})
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, msg := range m.Messages {
|
|
|
+ cmds = append(cmds, parser.Command{Name: "message", Args: fmt.Sprintf("%s %s", msg.Role, msg.Content)})
|
|
|
+ }
|
|
|
+
|
|
|
+ return cmds
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
type Message struct {
|
|
|
Role string `json:"role"`
|
|
|
Content string `json:"content"`
|
|
@@ -901,67 +942,6 @@ func DeleteModel(name string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func ShowModelfile(model *Model) (string, error) {
|
|
|
- var mt struct {
|
|
|
- *Model
|
|
|
- From string
|
|
|
- Parameters map[string][]any
|
|
|
- }
|
|
|
-
|
|
|
- mt.Parameters = make(map[string][]any)
|
|
|
- for k, v := range model.Options {
|
|
|
- if s, ok := v.([]any); ok {
|
|
|
- mt.Parameters[k] = s
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- mt.Parameters[k] = []any{v}
|
|
|
- }
|
|
|
-
|
|
|
- mt.Model = model
|
|
|
- mt.From = model.ModelPath
|
|
|
-
|
|
|
- if model.ParentModel != "" {
|
|
|
- mt.From = model.ParentModel
|
|
|
- }
|
|
|
-
|
|
|
- modelFile := `# Modelfile generated by "ollama show"
|
|
|
-# To build a new Modelfile based on this one, replace the FROM line with:
|
|
|
-# FROM {{ .ShortName }}
|
|
|
-
|
|
|
-FROM {{ .From }}
|
|
|
-TEMPLATE """{{ .Template }}"""
|
|
|
-
|
|
|
-{{- if .System }}
|
|
|
-SYSTEM """{{ .System }}"""
|
|
|
-{{- end }}
|
|
|
-
|
|
|
-{{- range $adapter := .AdapterPaths }}
|
|
|
-ADAPTER {{ $adapter }}
|
|
|
-{{- end }}
|
|
|
-
|
|
|
-{{- range $k, $v := .Parameters }}
|
|
|
-{{- range $parameter := $v }}
|
|
|
-PARAMETER {{ $k }} {{ printf "%#v" $parameter }}
|
|
|
-{{- end }}
|
|
|
-{{- end }}`
|
|
|
-
|
|
|
- tmpl, err := template.New("").Parse(modelFile)
|
|
|
- if err != nil {
|
|
|
- slog.Info(fmt.Sprintf("error parsing template: %q", err))
|
|
|
- return "", err
|
|
|
- }
|
|
|
-
|
|
|
- var buf bytes.Buffer
|
|
|
-
|
|
|
- if err = tmpl.Execute(&buf, mt); err != nil {
|
|
|
- slog.Info(fmt.Sprintf("error executing template: %q", err))
|
|
|
- return "", err
|
|
|
- }
|
|
|
-
|
|
|
- return buf.String(), nil
|
|
|
-}
|
|
|
-
|
|
|
func PushModel(ctx context.Context, name string, regOpts *registryOptions, fn func(api.ProgressResponse)) error {
|
|
|
mp := ParseModelPath(name)
|
|
|
fn(api.ProgressResponse{Status: "retrieving manifest"})
|