Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
df146c41
Commit
df146c41
authored
Jul 17, 2023
by
Michael Yang
Browse files
separate prompt into template and system
parent
2d305fa9
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
113 additions
and
85 deletions
+113
-85
parser/parser.go
parser/parser.go
+58
-43
server/images.go
server/images.go
+53
-32
server/routes.go
server/routes.go
+2
-10
No files found.
parser/parser.go
View file @
df146c41
...
@@ -2,76 +2,91 @@ package parser
...
@@ -2,76 +2,91 @@ package parser
import
(
import
(
"bufio"
"bufio"
"bytes"
"errors"
"fmt"
"fmt"
"io"
"io"
"strings"
)
)
type
Command
struct
{
type
Command
struct
{
Name
string
Name
string
Arg
string
Args
string
}
func
(
c
*
Command
)
Reset
()
{
c
.
Name
=
""
c
.
Args
=
""
}
}
func
Parse
(
reader
io
.
Reader
)
([]
Command
,
error
)
{
func
Parse
(
reader
io
.
Reader
)
([]
Command
,
error
)
{
var
commands
[]
Command
var
commands
[]
Command
var
foundModel
bool
var
command
,
modelCommand
Command
scanner
:=
bufio
.
NewScanner
(
reader
)
scanner
:=
bufio
.
NewScanner
(
reader
)
multiline
:=
false
scanner
.
Split
(
scanModelfile
)
var
multilineCommand
*
Command
for
scanner
.
Scan
()
{
for
scanner
.
Scan
()
{
line
:=
scanner
.
Text
()
line
:=
scanner
.
Bytes
()
if
multiline
{
// If we're in a multiline string and the line is """, end the multiline string.
fields
:=
bytes
.
SplitN
(
line
,
[]
byte
(
" "
),
2
)
if
strings
.
TrimSpace
(
line
)
==
`"""`
{
multiline
=
false
commands
=
append
(
commands
,
*
multilineCommand
)
}
else
{
// Otherwise, append the line to the multiline string.
multilineCommand
.
Arg
+=
"
\n
"
+
line
}
continue
}
fields
:=
strings
.
Fields
(
line
)
if
len
(
fields
)
==
0
{
if
len
(
fields
)
==
0
{
continue
continue
}
}
command
:=
Command
{}
switch
string
(
bytes
.
ToUpper
(
fields
[
0
]))
{
switch
strings
.
ToUpper
(
fields
[
0
])
{
case
"FROM"
:
case
"FROM"
:
command
.
Name
=
"model"
command
.
Name
=
"model"
command
.
Arg
=
fields
[
1
]
command
.
Args
=
string
(
fields
[
1
])
if
command
.
Arg
==
""
{
// copy command for validation
return
nil
,
fmt
.
Errorf
(
"no model specified in FROM line"
)
modelCommand
=
command
}
case
"LICENSE"
,
"TEMPLATE"
,
"SYSTEM"
:
foundModel
=
true
command
.
Name
=
string
(
bytes
.
ToLower
(
fields
[
0
]))
case
"PROMPT"
,
"LICENSE"
:
command
.
Args
=
string
(
fields
[
1
])
command
.
Name
=
strings
.
ToLower
(
fields
[
0
])
if
fields
[
1
]
==
`"""`
{
multiline
=
true
multilineCommand
=
&
command
multilineCommand
.
Arg
=
""
}
else
{
command
.
Arg
=
strings
.
Join
(
fields
[
1
:
],
" "
)
}
case
"PARAMETER"
:
case
"PARAMETER"
:
command
.
Name
=
fields
[
1
]
fields
=
bytes
.
SplitN
(
fields
[
1
],
[]
byte
(
" "
),
2
)
command
.
Arg
=
strings
.
Join
(
fields
[
2
:
],
" "
)
command
.
Name
=
string
(
fields
[
0
])
command
.
Args
=
string
(
fields
[
1
])
default
:
default
:
continue
continue
}
}
if
!
multiline
{
commands
=
append
(
commands
,
command
)
commands
=
append
(
commands
,
command
)
}
command
.
Reset
()
}
}
if
!
foundModel
{
if
modelCommand
.
Args
==
""
{
return
nil
,
fmt
.
Errorf
(
"no FROM line for the model was specified"
)
return
nil
,
fmt
.
Errorf
(
"no FROM line for the model was specified"
)
}
}
if
multiline
{
return
nil
,
fmt
.
Errorf
(
"unclosed multiline string"
)
}
return
commands
,
scanner
.
Err
()
return
commands
,
scanner
.
Err
()
}
}
func
scanModelfile
(
data
[]
byte
,
atEOF
bool
)
(
advance
int
,
token
[]
byte
,
err
error
)
{
if
atEOF
||
len
(
data
)
==
0
{
return
0
,
nil
,
nil
}
newline
:=
bytes
.
IndexByte
(
data
,
'\n'
)
if
start
:=
bytes
.
Index
(
data
,
[]
byte
(
`"""`
));
start
>=
0
&&
start
<
newline
{
end
:=
bytes
.
Index
(
data
[
start
+
3
:
],
[]
byte
(
`"""`
))
if
end
<
0
{
return
0
,
nil
,
errors
.
New
(
`unterminated multiline string: """`
)
}
n
:=
start
+
3
+
end
+
3
return
n
,
bytes
.
Replace
(
data
[
:
n
],
[]
byte
(
`"""`
),
[]
byte
(
""
),
2
),
nil
}
if
start
:=
bytes
.
Index
(
data
,
[]
byte
(
`'''`
));
start
>=
0
&&
start
<
newline
{
end
:=
bytes
.
Index
(
data
[
start
+
3
:
],
[]
byte
(
`'''`
))
if
end
<
0
{
return
0
,
nil
,
errors
.
New
(
"unterminated multiline string: '''"
)
}
n
:=
start
+
3
+
end
+
3
return
n
,
bytes
.
Replace
(
data
[
:
n
],
[]
byte
(
"'''"
),
[]
byte
(
""
),
2
),
nil
}
return
bufio
.
ScanLines
(
data
,
atEOF
)
}
server/images.go
View file @
df146c41
...
@@ -16,6 +16,7 @@ import (
...
@@ -16,6 +16,7 @@ import (
"reflect"
"reflect"
"strconv"
"strconv"
"strings"
"strings"
"text/template"
"github.com/jmorganca/ollama/api"
"github.com/jmorganca/ollama/api"
"github.com/jmorganca/ollama/parser"
"github.com/jmorganca/ollama/parser"
...
@@ -24,10 +25,33 @@ import (
...
@@ -24,10 +25,33 @@ import (
type
Model
struct
{
type
Model
struct
{
Name
string
`json:"name"`
Name
string
`json:"name"`
ModelPath
string
ModelPath
string
Prompt
string
Template
string
System
string
Options
api
.
Options
Options
api
.
Options
}
}
func
(
m
*
Model
)
Prompt
(
request
api
.
GenerateRequest
)
(
string
,
error
)
{
tmpl
,
err
:=
template
.
New
(
""
)
.
Parse
(
m
.
Template
)
if
err
!=
nil
{
return
""
,
err
}
var
vars
struct
{
System
string
Prompt
string
}
vars
.
System
=
m
.
System
vars
.
Prompt
=
request
.
Prompt
var
sb
strings
.
Builder
if
err
:=
tmpl
.
Execute
(
&
sb
,
vars
);
err
!=
nil
{
return
""
,
err
}
return
sb
.
String
(),
nil
}
type
ManifestV2
struct
{
type
ManifestV2
struct
{
SchemaVersion
int
`json:"schemaVersion"`
SchemaVersion
int
`json:"schemaVersion"`
MediaType
string
`json:"mediaType"`
MediaType
string
`json:"mediaType"`
...
@@ -71,20 +95,19 @@ func GetManifest(mp ModelPath) (*ManifestV2, error) {
...
@@ -71,20 +95,19 @@ func GetManifest(mp ModelPath) (*ManifestV2, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
_
,
err
=
os
.
Stat
(
fp
);
err
!=
nil
&&
!
errors
.
Is
(
err
,
os
.
ErrNotExist
)
{
if
_
,
err
=
os
.
Stat
(
fp
);
err
!=
nil
&&
!
errors
.
Is
(
err
,
os
.
ErrNotExist
)
{
return
nil
,
fmt
.
Errorf
(
"couldn't find model '%s'"
,
mp
.
GetShortTagname
())
return
nil
,
fmt
.
Errorf
(
"couldn't find model '%s'"
,
mp
.
GetShortTagname
())
}
}
var
manifest
*
ManifestV2
var
manifest
*
ManifestV2
f
,
err
:=
os
.
Open
(
fp
)
bts
,
err
:=
os
.
ReadFile
(
fp
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"couldn't open file '%s'"
,
fp
)
return
nil
,
fmt
.
Errorf
(
"couldn't open file '%s'"
,
fp
)
}
}
decoder
:=
json
.
NewDecoder
(
f
)
if
err
:=
json
.
Unmarshal
(
bts
,
&
manifest
);
err
!=
nil
{
err
=
decoder
.
Decode
(
&
manifest
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -112,12 +135,20 @@ func GetModel(name string) (*Model, error) {
...
@@ -112,12 +135,20 @@ func GetModel(name string) (*Model, error) {
switch
layer
.
MediaType
{
switch
layer
.
MediaType
{
case
"application/vnd.ollama.image.model"
:
case
"application/vnd.ollama.image.model"
:
model
.
ModelPath
=
filename
model
.
ModelPath
=
filename
case
"application/vnd.ollama.image.prompt"
:
case
"application/vnd.ollama.image.template"
:
data
,
err
:=
os
.
ReadFile
(
filename
)
bts
,
err
:=
os
.
ReadFile
(
filename
)
if
err
!=
nil
{
return
nil
,
err
}
model
.
Template
=
string
(
bts
)
case
"application/vnd.ollama.image.system"
:
bts
,
err
:=
os
.
ReadFile
(
filename
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
model
.
Prompt
=
string
(
data
)
model
.
System
=
string
(
bts
)
case
"application/vnd.ollama.image.params"
:
case
"application/vnd.ollama.image.params"
:
params
,
err
:=
os
.
Open
(
filename
)
params
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -156,13 +187,13 @@ func CreateModel(name string, path string, fn func(status string)) error {
...
@@ -156,13 +187,13 @@ func CreateModel(name string, path string, fn func(status string)) error {
params
:=
make
(
map
[
string
]
string
)
params
:=
make
(
map
[
string
]
string
)
for
_
,
c
:=
range
commands
{
for
_
,
c
:=
range
commands
{
log
.
Printf
(
"[%s] - %s
\n
"
,
c
.
Name
,
c
.
Arg
)
log
.
Printf
(
"[%s] - %s
\n
"
,
c
.
Name
,
c
.
Arg
s
)
switch
c
.
Name
{
switch
c
.
Name
{
case
"model"
:
case
"model"
:
fn
(
"looking for model"
)
fn
(
"looking for model"
)
mf
,
err
:=
GetManifest
(
ParseModelPath
(
c
.
Arg
))
mf
,
err
:=
GetManifest
(
ParseModelPath
(
c
.
Arg
s
))
if
err
!=
nil
{
if
err
!=
nil
{
fp
:=
c
.
Arg
fp
:=
c
.
Arg
s
// If filePath starts with ~/, replace it with the user's home directory.
// If filePath starts with ~/, replace it with the user's home directory.
if
strings
.
HasPrefix
(
fp
,
"~/"
)
{
if
strings
.
HasPrefix
(
fp
,
"~/"
)
{
...
@@ -183,7 +214,7 @@ func CreateModel(name string, path string, fn func(status string)) error {
...
@@ -183,7 +214,7 @@ func CreateModel(name string, path string, fn func(status string)) error {
fn
(
"creating model layer"
)
fn
(
"creating model layer"
)
file
,
err
:=
os
.
Open
(
fp
)
file
,
err
:=
os
.
Open
(
fp
)
if
err
!=
nil
{
if
err
!=
nil
{
fn
(
fmt
.
Sprintf
(
"couldn't find model '%s'"
,
c
.
Arg
))
fn
(
fmt
.
Sprintf
(
"couldn't find model '%s'"
,
c
.
Arg
s
))
return
fmt
.
Errorf
(
"failed to open file: %v"
,
err
)
return
fmt
.
Errorf
(
"failed to open file: %v"
,
err
)
}
}
defer
file
.
Close
()
defer
file
.
Close
()
...
@@ -206,31 +237,21 @@ func CreateModel(name string, path string, fn func(status string)) error {
...
@@ -206,31 +237,21 @@ func CreateModel(name string, path string, fn func(status string)) error {
layers
=
append
(
layers
,
newLayer
)
layers
=
append
(
layers
,
newLayer
)
}
}
}
}
case
"
prompt
"
:
case
"
license"
,
"template"
,
"system
"
:
fn
(
"creating
prompt
layer"
)
fn
(
fmt
.
Sprintf
(
"creating
%s
layer"
,
c
.
Name
)
)
// remove the prompt layer if one exists
// remove the prompt layer if one exists
layers
=
removeLayerFromLayers
(
layers
,
"application/vnd.ollama.image.prompt"
)
mediaType
:=
fmt
.
Sprintf
(
"application/vnd.ollama.image.%s"
,
c
.
Name
)
layers
=
removeLayerFromLayers
(
layers
,
mediaType
)
prompt
:=
strings
.
NewReader
(
c
.
Arg
)
layer
,
err
:=
CreateLayer
(
strings
.
NewReader
(
c
.
Args
))
l
,
err
:=
CreateLayer
(
prompt
)
if
err
!=
nil
{
if
err
!=
nil
{
fn
(
fmt
.
Sprintf
(
"couldn't create prompt layer: %v"
,
err
))
return
err
return
fmt
.
Errorf
(
"failed to create layer: %v"
,
err
)
}
l
.
MediaType
=
"application/vnd.ollama.image.prompt"
layers
=
append
(
layers
,
l
)
case
"license"
:
fn
(
"creating license layer"
)
license
:=
strings
.
NewReader
(
c
.
Arg
)
l
,
err
:=
CreateLayer
(
license
)
if
err
!=
nil
{
fn
(
fmt
.
Sprintf
(
"couldn't create license layer: %v"
,
err
))
return
fmt
.
Errorf
(
"failed to create layer: %v"
,
err
)
}
}
l
.
MediaType
=
"application/vnd.ollama.image.license"
layers
=
append
(
layers
,
l
)
layer
.
MediaType
=
mediaType
layers
=
append
(
layers
,
layer
)
default
:
default
:
params
[
c
.
Name
]
=
c
.
Arg
params
[
c
.
Name
]
=
c
.
Arg
s
}
}
}
}
...
...
server/routes.go
View file @
df146c41
...
@@ -9,7 +9,6 @@ import (
...
@@ -9,7 +9,6 @@ import (
"os"
"os"
"path/filepath"
"path/filepath"
"strings"
"strings"
"text/template"
"time"
"time"
"dario.cat/mergo"
"dario.cat/mergo"
...
@@ -54,19 +53,12 @@ func generate(c *gin.Context) {
...
@@ -54,19 +53,12 @@ func generate(c *gin.Context) {
return
return
}
}
te
mp
l
,
err
:=
template
.
New
(
""
)
.
Parse
(
model
.
Prompt
)
pro
mp
t
,
err
:=
model
.
Prompt
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"error"
:
err
.
Error
()})
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
return
}
}
var
sb
strings
.
Builder
if
err
=
templ
.
Execute
(
&
sb
,
req
);
err
!=
nil
{
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
}
req
.
Prompt
=
sb
.
String
()
llm
,
err
:=
llama
.
New
(
model
.
ModelPath
,
opts
)
llm
,
err
:=
llama
.
New
(
model
.
ModelPath
,
opts
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"error"
:
err
.
Error
()})
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"error"
:
err
.
Error
()})
...
@@ -77,7 +69,7 @@ func generate(c *gin.Context) {
...
@@ -77,7 +69,7 @@ func generate(c *gin.Context) {
ch
:=
make
(
chan
any
)
ch
:=
make
(
chan
any
)
go
func
()
{
go
func
()
{
defer
close
(
ch
)
defer
close
(
ch
)
llm
.
Predict
(
req
.
Context
,
req
.
P
rompt
,
func
(
r
api
.
GenerateResponse
)
{
llm
.
Predict
(
req
.
Context
,
p
rompt
,
func
(
r
api
.
GenerateResponse
)
{
r
.
Model
=
req
.
Model
r
.
Model
=
req
.
Model
r
.
CreatedAt
=
time
.
Now
()
.
UTC
()
r
.
CreatedAt
=
time
.
Now
()
.
UTC
()
if
r
.
Done
{
if
r
.
Done
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment