mirror of
https://github.com/ollama/ollama.git
synced 2026-01-23 15:02:09 -05:00
Compare commits
1 Commits
parth/decr
...
pdevine/pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c10a40db99 |
110
parser/parser.go
110
parser/parser.go
@@ -62,14 +62,15 @@ func (f Modelfile) CreateRequest(relativeDir string) (*api.CreateRequest, error)
|
|||||||
for _, c := range f.Commands {
|
for _, c := range f.Commands {
|
||||||
switch c.Name {
|
switch c.Name {
|
||||||
case "model":
|
case "model":
|
||||||
path, err := expandPath(c.Args, relativeDir)
|
name := c.Args.(string)
|
||||||
|
path, err := expandPath(name, relativeDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
digestMap, err := fileDigestMap(path)
|
digestMap, err := fileDigestMap(path)
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
req.From = c.Args
|
req.From = name
|
||||||
continue
|
continue
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -83,7 +84,8 @@ func (f Modelfile) CreateRequest(relativeDir string) (*api.CreateRequest, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "adapter":
|
case "adapter":
|
||||||
path, err := expandPath(c.Args, relativeDir)
|
adapter := c.Args.(string)
|
||||||
|
path, err := expandPath(adapter, relativeDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -95,21 +97,25 @@ func (f Modelfile) CreateRequest(relativeDir string) (*api.CreateRequest, error)
|
|||||||
|
|
||||||
req.Adapters = digestMap
|
req.Adapters = digestMap
|
||||||
case "template":
|
case "template":
|
||||||
req.Template = c.Args
|
template := c.Args.(string)
|
||||||
|
req.Template = template
|
||||||
case "system":
|
case "system":
|
||||||
req.System = c.Args
|
system := c.Args.(string)
|
||||||
|
req.System = system
|
||||||
case "license":
|
case "license":
|
||||||
licenses = append(licenses, c.Args)
|
license := c.Args.(string)
|
||||||
|
licenses = append(licenses, license)
|
||||||
case "message":
|
case "message":
|
||||||
role, msg, _ := strings.Cut(c.Args, ": ")
|
msg := c.Args.(*Message)
|
||||||
messages = append(messages, api.Message{Role: role, Content: msg})
|
messages = append(messages, api.Message{Role: msg.Role, Content: msg.Content})
|
||||||
default:
|
case "parameter":
|
||||||
if slices.Contains(deprecatedParameters, c.Name) {
|
if slices.Contains(deprecatedParameters, c.Name) {
|
||||||
fmt.Printf("warning: parameter %s is deprecated\n", c.Name)
|
fmt.Printf("warning: parameter '%s' is deprecated\n", c.Name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
ps, err := api.FormatParams(map[string][]string{c.Name: {c.Args}})
|
param := c.Args.(*Parameter)
|
||||||
|
ps, err := api.FormatParams(map[string][]string{param.Name: {param.Value}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -123,6 +129,8 @@ func (f Modelfile) CreateRequest(relativeDir string) (*api.CreateRequest, error)
|
|||||||
params[k] = v
|
params[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("warning: unknown command '%s'", c.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +320,17 @@ func filesForModel(path string) ([]string, error) {
|
|||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Name string
|
Name string
|
||||||
Args string
|
Args any
|
||||||
|
}
|
||||||
|
|
||||||
|
type Parameter struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
Role string
|
||||||
|
Content string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Command) String() string {
|
func (c Command) String() string {
|
||||||
@@ -321,12 +339,16 @@ func (c Command) String() string {
|
|||||||
case "model":
|
case "model":
|
||||||
fmt.Fprintf(&sb, "FROM %s", c.Args)
|
fmt.Fprintf(&sb, "FROM %s", c.Args)
|
||||||
case "license", "template", "system", "adapter":
|
case "license", "template", "system", "adapter":
|
||||||
fmt.Fprintf(&sb, "%s %s", strings.ToUpper(c.Name), quote(c.Args))
|
data := c.Args.(string)
|
||||||
|
fmt.Fprintf(&sb, "%s %s", strings.ToUpper(c.Name), quote(data))
|
||||||
case "message":
|
case "message":
|
||||||
role, message, _ := strings.Cut(c.Args, ": ")
|
data := c.Args.(*Message)
|
||||||
fmt.Fprintf(&sb, "MESSAGE %s %s", role, quote(message))
|
fmt.Fprintf(&sb, "MESSAGE %s %s", data.Role, quote(data.Content))
|
||||||
|
case "parameter":
|
||||||
|
data := c.Args.(*Parameter)
|
||||||
|
fmt.Fprintf(&sb, "PARAMETER %s %s", data.Name, quote(data.Value))
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(&sb, "PARAMETER %s %s", c.Name, quote(c.Args))
|
fmt.Printf("unknown command '%s'\n", c.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.String()
|
return sb.String()
|
||||||
@@ -366,7 +388,6 @@ func ParseFile(r io.Reader) (*Modelfile, error) {
|
|||||||
var curr state
|
var curr state
|
||||||
var currLine int = 1
|
var currLine int = 1
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
var role string
|
|
||||||
|
|
||||||
var f Modelfile
|
var f Modelfile
|
||||||
|
|
||||||
@@ -413,6 +434,7 @@ func ParseFile(r io.Reader) (*Modelfile, error) {
|
|||||||
case "parameter":
|
case "parameter":
|
||||||
// transition to stateParameter which sets command name
|
// transition to stateParameter which sets command name
|
||||||
next = stateParameter
|
next = stateParameter
|
||||||
|
cmd.Name = s
|
||||||
case "message":
|
case "message":
|
||||||
// transition to stateMessage which validates the message role
|
// transition to stateMessage which validates the message role
|
||||||
next = stateMessage
|
next = stateMessage
|
||||||
@@ -421,16 +443,37 @@ func ParseFile(r io.Reader) (*Modelfile, error) {
|
|||||||
cmd.Name = s
|
cmd.Name = s
|
||||||
}
|
}
|
||||||
case stateParameter:
|
case stateParameter:
|
||||||
cmd.Name = b.String()
|
s, ok := unquote(strings.TrimSpace(b.String()))
|
||||||
|
if !ok || isSpace(r) {
|
||||||
|
if _, err := b.WriteRune(r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd.Args = &Parameter{
|
||||||
|
Name: s,
|
||||||
|
}
|
||||||
case stateMessage:
|
case stateMessage:
|
||||||
if !isValidMessageRole(b.String()) {
|
s, ok := unquote(strings.TrimSpace(b.String()))
|
||||||
|
if !ok || isSpace(r) {
|
||||||
|
if _, err := b.WriteRune(r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isValidMessageRole(s) {
|
||||||
return nil, &ParserError{
|
return nil, &ParserError{
|
||||||
LineNumber: currLine,
|
LineNumber: currLine,
|
||||||
Msg: errInvalidMessageRole.Error(),
|
Msg: errInvalidMessageRole.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
role = b.String()
|
cmd.Args = &Message{
|
||||||
|
Role: s,
|
||||||
|
}
|
||||||
case stateComment, stateNil:
|
case stateComment, stateNil:
|
||||||
// pass
|
// pass
|
||||||
case stateValue:
|
case stateValue:
|
||||||
@@ -443,12 +486,16 @@ func ParseFile(r io.Reader) (*Modelfile, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if role != "" {
|
switch cmd.Name {
|
||||||
s = role + ": " + s
|
case "parameter":
|
||||||
role = ""
|
p := cmd.Args.(*Parameter)
|
||||||
|
p.Value = s
|
||||||
|
case "message":
|
||||||
|
m := cmd.Args.(*Message)
|
||||||
|
m.Content = s
|
||||||
|
default:
|
||||||
|
cmd.Args = s
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Args = s
|
|
||||||
f.Commands = append(f.Commands, cmd)
|
f.Commands = append(f.Commands, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,11 +520,16 @@ func ParseFile(r io.Reader) (*Modelfile, error) {
|
|||||||
return nil, io.ErrUnexpectedEOF
|
return nil, io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
if role != "" {
|
switch cmd.Name {
|
||||||
s = role + ": " + s
|
case "parameter":
|
||||||
|
c := cmd.Args.(*Parameter)
|
||||||
|
c.Value = s
|
||||||
|
case "message":
|
||||||
|
c := cmd.Args.(*Message)
|
||||||
|
c.Content = s
|
||||||
|
default:
|
||||||
|
cmd.Args = s
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Args = s
|
|
||||||
f.Commands = append(f.Commands, cmd)
|
f.Commands = append(f.Commands, cmd)
|
||||||
default:
|
default:
|
||||||
return nil, io.ErrUnexpectedEOF
|
return nil, io.ErrUnexpectedEOF
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|>
|
|||||||
{Name: "model", Args: "model1"},
|
{Name: "model", Args: "model1"},
|
||||||
{Name: "adapter", Args: "adapter1"},
|
{Name: "adapter", Args: "adapter1"},
|
||||||
{Name: "license", Args: "MIT"},
|
{Name: "license", Args: "MIT"},
|
||||||
{Name: "param1", Args: "value1"},
|
{Name: "parameter", Args: &Parameter{"param1", "value1"}},
|
||||||
{Name: "param2", Args: "value2"},
|
{Name: "parameter", Args: &Parameter{"param2", "value2"}},
|
||||||
{Name: "template", Args: "{{ if .System }}<|start_header_id|>system<|end_header_id|>\n\n{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>\n\n{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>\n\n{{ .Response }}<|eot_id|>"},
|
{Name: "template", Args: "{{ if .System }}<|start_header_id|>system<|end_header_id|>\n\n{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>\n\n{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>\n\n{{ .Response }}<|eot_id|>"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +80,8 @@ TEMPLATE """ {{ if .System }}<|start_header_id|>system<|end_header_id|>
|
|||||||
{Name: "model", Args: " model 1"},
|
{Name: "model", Args: " model 1"},
|
||||||
{Name: "adapter", Args: "adapter3"},
|
{Name: "adapter", Args: "adapter3"},
|
||||||
{Name: "license", Args: "MIT "},
|
{Name: "license", Args: "MIT "},
|
||||||
{Name: "param1", Args: "value1"},
|
{Name: "parameter", Args: &Parameter{"param1", "value1"}},
|
||||||
{Name: "param2", Args: "value2"},
|
{Name: "parameter", Args: &Parameter{"param2", "value2"}},
|
||||||
{Name: "template", Args: " {{ if .System }}<|start_header_id|>system<|end_header_id|>\n\n{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>\n\n{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>\n\n{{ .Response }}<|eot_id|> "},
|
{Name: "template", Args: " {{ if .System }}<|start_header_id|>system<|end_header_id|>\n\n{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>\n\n{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>\n\n{{ .Response }}<|eot_id|> "},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ func TestParseFileFrom(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FROM \"FOO BAR\"\nPARAMETER param1 value1",
|
"FROM \"FOO BAR\"\nPARAMETER param1 value1",
|
||||||
[]Command{{Name: "model", Args: "FOO BAR"}, {Name: "param1", Args: "value1"}},
|
[]Command{{Name: "model", Args: "FOO BAR"}, {Name: "parameter", Args: &Parameter{"param1", "value1"}}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -149,12 +149,12 @@ func TestParseFileFrom(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PARAMETER param1 value1\nFROM foo",
|
"PARAMETER param1 value1\nFROM foo",
|
||||||
[]Command{{Name: "param1", Args: "value1"}, {Name: "model", Args: "foo"}},
|
[]Command{{Name: "parameter", Args: &Parameter{"param1", "value1"}}, {Name: "model", Args: "foo"}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PARAMETER what the \nFROM lemons make lemonade ",
|
"PARAMETER what the \nFROM lemons make lemonade ",
|
||||||
[]Command{{Name: "what", Args: "the"}, {Name: "model", Args: "lemons make lemonade"}},
|
[]Command{{Name: "parameter", Args: &Parameter{"what", "the"}}, {Name: "model", Args: "lemons make lemonade"}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ MESSAGE system You are a file parser. Always parse things.
|
|||||||
`,
|
`,
|
||||||
[]Command{
|
[]Command{
|
||||||
{Name: "model", Args: "foo"},
|
{Name: "model", Args: "foo"},
|
||||||
{Name: "message", Args: "system: You are a file parser. Always parse things."},
|
{Name: "message", Args: &Message{"system", "You are a file parser. Always parse things."}},
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
@@ -221,7 +221,7 @@ FROM foo
|
|||||||
MESSAGE system You are a file parser. Always parse things.`,
|
MESSAGE system You are a file parser. Always parse things.`,
|
||||||
[]Command{
|
[]Command{
|
||||||
{Name: "model", Args: "foo"},
|
{Name: "model", Args: "foo"},
|
||||||
{Name: "message", Args: "system: You are a file parser. Always parse things."},
|
{Name: "message", Args: &Message{"system", "You are a file parser. Always parse things."}},
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
@@ -234,9 +234,9 @@ MESSAGE assistant Hello, I want to parse all the things!
|
|||||||
`,
|
`,
|
||||||
[]Command{
|
[]Command{
|
||||||
{Name: "model", Args: "foo"},
|
{Name: "model", Args: "foo"},
|
||||||
{Name: "message", Args: "system: You are a file parser. Always parse things."},
|
{Name: "message", Args: &Message{"system", "You are a file parser. Always parse things."}},
|
||||||
{Name: "message", Args: "user: Hey there!"},
|
{Name: "message", Args: &Message{"user", "Hey there!"}},
|
||||||
{Name: "message", Args: "assistant: Hello, I want to parse all the things!"},
|
{Name: "message", Args: &Message{"assistant", "Hello, I want to parse all the things!"}},
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
@@ -244,12 +244,12 @@ MESSAGE assistant Hello, I want to parse all the things!
|
|||||||
`
|
`
|
||||||
FROM foo
|
FROM foo
|
||||||
MESSAGE system """
|
MESSAGE system """
|
||||||
You are a multiline file parser. Always parse things.
|
You are a multiline file "parser". Always parse things.
|
||||||
"""
|
"""
|
||||||
`,
|
`,
|
||||||
[]Command{
|
[]Command{
|
||||||
{Name: "model", Args: "foo"},
|
{Name: "model", Args: "foo"},
|
||||||
{Name: "message", Args: "system: \nYou are a multiline file parser. Always parse things.\n"},
|
{Name: "message", Args: &Message{"system", "\nYou are a multiline file \"parser\". Always parse things.\n"}},
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
@@ -514,7 +514,7 @@ func TestParseFileParameters(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, []Command{
|
assert.Equal(t, []Command{
|
||||||
{Name: "model", Args: "foo"},
|
{Name: "model", Args: "foo"},
|
||||||
{Name: v.name, Args: v.value},
|
{Name: "parameter", Args: &Parameter{v.name, v.value}},
|
||||||
}, modelfile.Commands)
|
}, modelfile.Commands)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -617,8 +617,8 @@ SYSTEM You are a utf16 file.
|
|||||||
|
|
||||||
expected := []Command{
|
expected := []Command{
|
||||||
{Name: "model", Args: "bob"},
|
{Name: "model", Args: "bob"},
|
||||||
{Name: "param1", Args: "1"},
|
{Name: "parameter", Args: &Parameter{"param1", "1"}},
|
||||||
{Name: "param2", Args: "4096"},
|
{Name: "parameter", Args: &Parameter{"param2", "4096"}},
|
||||||
{Name: "system", Args: "You are a utf16 file."},
|
{Name: "system", Args: "You are a utf16 file."},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user