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
b7a87a22
Unverified
Commit
b7a87a22
authored
May 03, 2024
by
Michael Yang
Committed by
GitHub
May 03, 2024
Browse files
Merge pull request #4059 from ollama/mxyng/parser-2
rename parser to model/file
parents
e8aaea03
8acb2336
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
151 additions
and
124 deletions
+151
-124
cmd/cmd.go
cmd/cmd.go
+9
-10
server/images.go
server/images.go
+42
-15
server/routes.go
server/routes.go
+13
-24
server/routes_test.go
server/routes_test.go
+4
-4
types/model/file.go
types/model/file.go
+38
-32
types/model/file_test.go
types/model/file_test.go
+45
-39
No files found.
cmd/cmd.go
View file @
b7a87a22
...
@@ -34,7 +34,6 @@ import (
...
@@ -34,7 +34,6 @@ import (
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/auth"
"github.com/ollama/ollama/auth"
"github.com/ollama/ollama/format"
"github.com/ollama/ollama/format"
"github.com/ollama/ollama/parser"
"github.com/ollama/ollama/progress"
"github.com/ollama/ollama/progress"
"github.com/ollama/ollama/server"
"github.com/ollama/ollama/server"
"github.com/ollama/ollama/types/errtypes"
"github.com/ollama/ollama/types/errtypes"
...
@@ -57,13 +56,13 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
...
@@ -57,13 +56,13 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
p
:=
progress
.
NewProgress
(
os
.
Stderr
)
p
:=
progress
.
NewProgress
(
os
.
Stderr
)
defer
p
.
Stop
()
defer
p
.
Stop
()
modelfile
,
err
:=
os
.
Open
(
filename
)
f
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
defer
modelfile
.
Close
()
defer
f
.
Close
()
commands
,
err
:=
parser
.
Parse
(
modelf
ile
)
modelfile
,
err
:=
model
.
ParseF
ile
(
f
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -77,10 +76,10 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
...
@@ -77,10 +76,10 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
spinner
:=
progress
.
NewSpinner
(
status
)
spinner
:=
progress
.
NewSpinner
(
status
)
p
.
Add
(
status
,
spinner
)
p
.
Add
(
status
,
spinner
)
for
i
:=
range
c
ommands
{
for
i
:=
range
modelfile
.
C
ommands
{
switch
c
ommands
[
i
]
.
Name
{
switch
modelfile
.
C
ommands
[
i
]
.
Name
{
case
"model"
,
"adapter"
:
case
"model"
,
"adapter"
:
path
:=
c
ommands
[
i
]
.
Args
path
:=
modelfile
.
C
ommands
[
i
]
.
Args
if
path
==
"~"
{
if
path
==
"~"
{
path
=
home
path
=
home
}
else
if
strings
.
HasPrefix
(
path
,
"~/"
)
{
}
else
if
strings
.
HasPrefix
(
path
,
"~/"
)
{
...
@@ -92,7 +91,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
...
@@ -92,7 +91,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
}
}
fi
,
err
:=
os
.
Stat
(
path
)
fi
,
err
:=
os
.
Stat
(
path
)
if
errors
.
Is
(
err
,
os
.
ErrNotExist
)
&&
c
ommands
[
i
]
.
Name
==
"model"
{
if
errors
.
Is
(
err
,
os
.
ErrNotExist
)
&&
modelfile
.
C
ommands
[
i
]
.
Name
==
"model"
{
continue
continue
}
else
if
err
!=
nil
{
}
else
if
err
!=
nil
{
return
err
return
err
...
@@ -115,7 +114,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
...
@@ -115,7 +114,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
return
err
return
err
}
}
c
ommands
[
i
]
.
Args
=
"@"
+
digest
modelfile
.
C
ommands
[
i
]
.
Args
=
"@"
+
digest
}
}
}
}
...
@@ -145,7 +144,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
...
@@ -145,7 +144,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
quantization
,
_
:=
cmd
.
Flags
()
.
GetString
(
"quantization"
)
quantization
,
_
:=
cmd
.
Flags
()
.
GetString
(
"quantization"
)
request
:=
api
.
CreateRequest
{
Name
:
args
[
0
],
Modelfile
:
parser
.
Format
(
commands
),
Quantization
:
quantization
}
request
:=
api
.
CreateRequest
{
Name
:
args
[
0
],
Modelfile
:
modelfile
.
String
(
),
Quantization
:
quantization
}
if
err
:=
client
.
Create
(
cmd
.
Context
(),
&
request
,
fn
);
err
!=
nil
{
if
err
:=
client
.
Create
(
cmd
.
Context
(),
&
request
,
fn
);
err
!=
nil
{
return
err
return
err
}
}
...
...
server/images.go
View file @
b7a87a22
...
@@ -29,7 +29,6 @@ import (
...
@@ -29,7 +29,6 @@ import (
"github.com/ollama/ollama/convert"
"github.com/ollama/ollama/convert"
"github.com/ollama/ollama/format"
"github.com/ollama/ollama/format"
"github.com/ollama/ollama/llm"
"github.com/ollama/ollama/llm"
"github.com/ollama/ollama/parser"
"github.com/ollama/ollama/types/errtypes"
"github.com/ollama/ollama/types/errtypes"
"github.com/ollama/ollama/types/model"
"github.com/ollama/ollama/types/model"
"github.com/ollama/ollama/version"
"github.com/ollama/ollama/version"
...
@@ -63,46 +62,74 @@ func (m *Model) IsEmbedding() bool {
...
@@ -63,46 +62,74 @@ func (m *Model) IsEmbedding() bool {
return
slices
.
Contains
(
m
.
Config
.
ModelFamilies
,
"bert"
)
||
slices
.
Contains
(
m
.
Config
.
ModelFamilies
,
"nomic-bert"
)
return
slices
.
Contains
(
m
.
Config
.
ModelFamilies
,
"bert"
)
||
slices
.
Contains
(
m
.
Config
.
ModelFamilies
,
"nomic-bert"
)
}
}
func
(
m
*
Model
)
Commands
()
(
cmds
[]
parser
.
Command
)
{
func
(
m
*
Model
)
String
()
string
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"model"
,
Args
:
m
.
ModelPath
})
var
modelfile
model
.
File
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"model"
,
Args
:
m
.
ModelPath
,
})
if
m
.
Template
!=
""
{
if
m
.
Template
!=
""
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"template"
,
Args
:
m
.
Template
})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"template"
,
Args
:
m
.
Template
,
})
}
}
if
m
.
System
!=
""
{
if
m
.
System
!=
""
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"system"
,
Args
:
m
.
System
})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"system"
,
Args
:
m
.
System
,
})
}
}
for
_
,
adapter
:=
range
m
.
AdapterPaths
{
for
_
,
adapter
:=
range
m
.
AdapterPaths
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"adapter"
,
Args
:
adapter
})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"adapter"
,
Args
:
adapter
,
})
}
}
for
_
,
projector
:=
range
m
.
ProjectorPaths
{
for
_
,
projector
:=
range
m
.
ProjectorPaths
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"projector"
,
Args
:
projector
})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"projector"
,
Args
:
projector
,
})
}
}
for
k
,
v
:=
range
m
.
Options
{
for
k
,
v
:=
range
m
.
Options
{
switch
v
:=
v
.
(
type
)
{
switch
v
:=
v
.
(
type
)
{
case
[]
any
:
case
[]
any
:
for
_
,
s
:=
range
v
{
for
_
,
s
:=
range
v
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
k
,
Args
:
fmt
.
Sprintf
(
"%v"
,
s
)})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
k
,
Args
:
fmt
.
Sprintf
(
"%v"
,
s
),
})
}
}
default
:
default
:
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
k
,
Args
:
fmt
.
Sprintf
(
"%v"
,
v
)})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
k
,
Args
:
fmt
.
Sprintf
(
"%v"
,
v
),
})
}
}
}
}
for
_
,
license
:=
range
m
.
License
{
for
_
,
license
:=
range
m
.
License
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"license"
,
Args
:
license
})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"license"
,
Args
:
license
,
})
}
}
for
_
,
msg
:=
range
m
.
Messages
{
for
_
,
msg
:=
range
m
.
Messages
{
cmds
=
append
(
cmds
,
parser
.
Command
{
Name
:
"message"
,
Args
:
fmt
.
Sprintf
(
"%s %s"
,
msg
.
Role
,
msg
.
Content
)})
modelfile
.
Commands
=
append
(
modelfile
.
Commands
,
model
.
Command
{
Name
:
"message"
,
Args
:
fmt
.
Sprintf
(
"%s %s"
,
msg
.
Role
,
msg
.
Content
),
})
}
}
return
cmds
return
modelfile
.
String
()
}
}
type
Message
struct
{
type
Message
struct
{
...
@@ -329,7 +356,7 @@ func realpath(mfDir, from string) string {
...
@@ -329,7 +356,7 @@ func realpath(mfDir, from string) string {
return
abspath
return
abspath
}
}
func
CreateModel
(
ctx
context
.
Context
,
name
,
modelFileDir
,
quantization
string
,
commands
[]
parser
.
Command
,
fn
func
(
resp
api
.
ProgressResponse
))
error
{
func
CreateModel
(
ctx
context
.
Context
,
name
,
modelFileDir
,
quantization
string
,
modelfile
*
model
.
File
,
fn
func
(
resp
api
.
ProgressResponse
))
error
{
deleteMap
:=
make
(
map
[
string
]
struct
{})
deleteMap
:=
make
(
map
[
string
]
struct
{})
if
manifest
,
_
,
err
:=
GetManifest
(
ParseModelPath
(
name
));
err
==
nil
{
if
manifest
,
_
,
err
:=
GetManifest
(
ParseModelPath
(
name
));
err
==
nil
{
for
_
,
layer
:=
range
append
(
manifest
.
Layers
,
manifest
.
Config
)
{
for
_
,
layer
:=
range
append
(
manifest
.
Layers
,
manifest
.
Config
)
{
...
@@ -351,7 +378,7 @@ func CreateModel(ctx context.Context, name, modelFileDir, quantization string, c
...
@@ -351,7 +378,7 @@ func CreateModel(ctx context.Context, name, modelFileDir, quantization string, c
params
:=
make
(
map
[
string
][]
string
)
params
:=
make
(
map
[
string
][]
string
)
fromParams
:=
make
(
map
[
string
]
any
)
fromParams
:=
make
(
map
[
string
]
any
)
for
_
,
c
:=
range
c
ommands
{
for
_
,
c
:=
range
modelfile
.
C
ommands
{
mediatype
:=
fmt
.
Sprintf
(
"application/vnd.ollama.image.%s"
,
c
.
Name
)
mediatype
:=
fmt
.
Sprintf
(
"application/vnd.ollama.image.%s"
,
c
.
Name
)
switch
c
.
Name
{
switch
c
.
Name
{
...
...
server/routes.go
View file @
b7a87a22
package
server
package
server
import
(
import
(
"cmp"
"context"
"context"
"encoding/json"
"encoding/json"
"errors"
"errors"
...
@@ -28,7 +29,6 @@ import (
...
@@ -28,7 +29,6 @@ import (
"github.com/ollama/ollama/gpu"
"github.com/ollama/ollama/gpu"
"github.com/ollama/ollama/llm"
"github.com/ollama/ollama/llm"
"github.com/ollama/ollama/openai"
"github.com/ollama/ollama/openai"
"github.com/ollama/ollama/parser"
"github.com/ollama/ollama/types/model"
"github.com/ollama/ollama/types/model"
"github.com/ollama/ollama/version"
"github.com/ollama/ollama/version"
)
)
...
@@ -522,28 +522,17 @@ func (s *Server) PushModelHandler(c *gin.Context) {
...
@@ -522,28 +522,17 @@ func (s *Server) PushModelHandler(c *gin.Context) {
func
(
s
*
Server
)
CreateModelHandler
(
c
*
gin
.
Context
)
{
func
(
s
*
Server
)
CreateModelHandler
(
c
*
gin
.
Context
)
{
var
req
api
.
CreateRequest
var
req
api
.
CreateRequest
err
:=
c
.
ShouldBindJSON
(
&
req
)
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
errors
.
Is
(
err
,
io
.
EOF
)
{
switch
{
case
errors
.
Is
(
err
,
io
.
EOF
)
:
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
"missing request body"
})
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
"missing request body"
})
return
return
case
err
!=
nil
:
}
else
if
err
!=
nil
{
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
return
}
}
var
model
string
name
:=
model
.
ParseName
(
cmp
.
Or
(
req
.
Model
,
req
.
Name
))
if
req
.
Model
!=
""
{
if
!
name
.
IsValid
()
{
model
=
req
.
Model
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
"invalid model name"
})
}
else
if
req
.
Name
!=
""
{
model
=
req
.
Name
}
else
{
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
"model is required"
})
return
}
if
err
:=
ParseModelPath
(
model
)
.
Validate
();
err
!=
nil
{
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
return
}
}
...
@@ -552,19 +541,19 @@ func (s *Server) CreateModelHandler(c *gin.Context) {
...
@@ -552,19 +541,19 @@ func (s *Server) CreateModelHandler(c *gin.Context) {
return
return
}
}
var
modelfile
io
.
Reader
=
strings
.
NewReader
(
req
.
Modelfile
)
var
r
io
.
Reader
=
strings
.
NewReader
(
req
.
Modelfile
)
if
req
.
Path
!=
""
&&
req
.
Modelfile
==
""
{
if
req
.
Path
!=
""
&&
req
.
Modelfile
==
""
{
m
f
,
err
:=
os
.
Open
(
req
.
Path
)
f
,
err
:=
os
.
Open
(
req
.
Path
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
fmt
.
Sprintf
(
"error reading modelfile: %s"
,
err
)})
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
fmt
.
Sprintf
(
"error reading modelfile: %s"
,
err
)})
return
return
}
}
defer
m
f
.
Close
()
defer
f
.
Close
()
modelfile
=
m
f
r
=
f
}
}
commands
,
err
:=
parser
.
Parse
(
modelf
ile
)
modelfile
,
err
:=
model
.
ParseF
ile
(
r
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
c
.
AbortWithStatusJSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
return
...
@@ -580,7 +569,7 @@ func (s *Server) CreateModelHandler(c *gin.Context) {
...
@@ -580,7 +569,7 @@ func (s *Server) CreateModelHandler(c *gin.Context) {
ctx
,
cancel
:=
context
.
WithCancel
(
c
.
Request
.
Context
())
ctx
,
cancel
:=
context
.
WithCancel
(
c
.
Request
.
Context
())
defer
cancel
()
defer
cancel
()
if
err
:=
CreateModel
(
ctx
,
model
,
filepath
.
Dir
(
req
.
Path
),
req
.
Quantization
,
commands
,
fn
);
err
!=
nil
{
if
err
:=
CreateModel
(
ctx
,
name
.
String
()
,
filepath
.
Dir
(
req
.
Path
),
req
.
Quantization
,
modelfile
,
fn
);
err
!=
nil
{
ch
<-
gin
.
H
{
"error"
:
err
.
Error
()}
ch
<-
gin
.
H
{
"error"
:
err
.
Error
()}
}
}
}()
}()
...
@@ -732,7 +721,7 @@ func GetModelInfo(req api.ShowRequest) (*api.ShowResponse, error) {
...
@@ -732,7 +721,7 @@ func GetModelInfo(req api.ShowRequest) (*api.ShowResponse, error) {
fmt
.
Fprintln
(
&
sb
,
"# Modelfile generate by
\"
ollama show
\"
"
)
fmt
.
Fprintln
(
&
sb
,
"# Modelfile generate by
\"
ollama show
\"
"
)
fmt
.
Fprintln
(
&
sb
,
"# To build a new Modelfile based on this, replace FROM with:"
)
fmt
.
Fprintln
(
&
sb
,
"# To build a new Modelfile based on this, replace FROM with:"
)
fmt
.
Fprintf
(
&
sb
,
"# FROM %s
\n\n
"
,
model
.
ShortName
)
fmt
.
Fprintf
(
&
sb
,
"# FROM %s
\n\n
"
,
model
.
ShortName
)
fmt
.
Fprint
(
&
sb
,
parser
.
Format
(
model
.
Commands
()
))
fmt
.
Fprint
(
&
sb
,
model
.
String
(
))
resp
.
Modelfile
=
sb
.
String
()
resp
.
Modelfile
=
sb
.
String
()
return
resp
,
nil
return
resp
,
nil
...
...
server/routes_test.go
View file @
b7a87a22
...
@@ -17,7 +17,7 @@ import (
...
@@ -17,7 +17,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/assert"
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/
parser
"
"github.com/ollama/ollama/
types/model
"
"github.com/ollama/ollama/version"
"github.com/ollama/ollama/version"
)
)
...
@@ -55,13 +55,13 @@ func Test_Routes(t *testing.T) {
...
@@ -55,13 +55,13 @@ func Test_Routes(t *testing.T) {
createTestModel
:=
func
(
t
*
testing
.
T
,
name
string
)
{
createTestModel
:=
func
(
t
*
testing
.
T
,
name
string
)
{
fname
:=
createTestFile
(
t
,
"ollama-model"
)
fname
:=
createTestFile
(
t
,
"ollama-model"
)
modelfile
:=
strings
.
NewReader
(
fmt
.
Sprintf
(
"FROM %s
\n
PARAMETER seed 42
\n
PARAMETER top_p 0.9
\n
PARAMETER stop foo
\n
PARAMETER stop bar"
,
fname
))
r
:=
strings
.
NewReader
(
fmt
.
Sprintf
(
"FROM %s
\n
PARAMETER seed 42
\n
PARAMETER top_p 0.9
\n
PARAMETER stop foo
\n
PARAMETER stop bar"
,
fname
))
commands
,
err
:=
parser
.
Parse
(
modelf
ile
)
modelfile
,
err
:=
model
.
ParseF
ile
(
r
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
fn
:=
func
(
resp
api
.
ProgressResponse
)
{
fn
:=
func
(
resp
api
.
ProgressResponse
)
{
t
.
Logf
(
"Status: %s"
,
resp
.
Status
)
t
.
Logf
(
"Status: %s"
,
resp
.
Status
)
}
}
err
=
CreateModel
(
context
.
TODO
(),
name
,
""
,
""
,
commands
,
fn
)
err
=
CreateModel
(
context
.
TODO
(),
name
,
""
,
""
,
modelfile
,
fn
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
}
}
...
...
parser/parser
.go
→
types/model/file
.go
View file @
b7a87a22
package
parser
package
model
import
(
import
(
"bufio"
"bufio"
...
@@ -10,11 +10,41 @@ import (
...
@@ -10,11 +10,41 @@ import (
"strings"
"strings"
)
)
type
File
struct
{
Commands
[]
Command
}
func
(
f
File
)
String
()
string
{
var
sb
strings
.
Builder
for
_
,
cmd
:=
range
f
.
Commands
{
fmt
.
Fprintln
(
&
sb
,
cmd
.
String
())
}
return
sb
.
String
()
}
type
Command
struct
{
type
Command
struct
{
Name
string
Name
string
Args
string
Args
string
}
}
func
(
c
Command
)
String
()
string
{
var
sb
strings
.
Builder
switch
c
.
Name
{
case
"model"
:
fmt
.
Fprintf
(
&
sb
,
"FROM %s"
,
c
.
Args
)
case
"license"
,
"template"
,
"system"
,
"adapter"
:
fmt
.
Fprintf
(
&
sb
,
"%s %s"
,
strings
.
ToUpper
(
c
.
Name
),
quote
(
c
.
Args
))
case
"message"
:
role
,
message
,
_
:=
strings
.
Cut
(
c
.
Args
,
": "
)
fmt
.
Fprintf
(
&
sb
,
"MESSAGE %s %s"
,
role
,
quote
(
message
))
default
:
fmt
.
Fprintf
(
&
sb
,
"PARAMETER %s %s"
,
c
.
Name
,
quote
(
c
.
Args
))
}
return
sb
.
String
()
}
type
state
int
type
state
int
const
(
const
(
...
@@ -32,38 +62,14 @@ var (
...
@@ -32,38 +62,14 @@ var (
errInvalidCommand
=
errors
.
New
(
"command must be one of
\"
from
\"
,
\"
license
\"
,
\"
template
\"
,
\"
system
\"
,
\"
adapter
\"
,
\"
parameter
\"
, or
\"
message
\"
"
)
errInvalidCommand
=
errors
.
New
(
"command must be one of
\"
from
\"
,
\"
license
\"
,
\"
template
\"
,
\"
system
\"
,
\"
adapter
\"
,
\"
parameter
\"
, or
\"
message
\"
"
)
)
)
func
Format
(
cmds
[]
Command
)
string
{
func
ParseFile
(
r
io
.
Reader
)
(
*
File
,
error
)
{
var
sb
strings
.
Builder
for
_
,
cmd
:=
range
cmds
{
name
:=
cmd
.
Name
args
:=
cmd
.
Args
switch
cmd
.
Name
{
case
"model"
:
name
=
"from"
args
=
cmd
.
Args
case
"license"
,
"template"
,
"system"
,
"adapter"
:
args
=
quote
(
args
)
case
"message"
:
role
,
message
,
_
:=
strings
.
Cut
(
cmd
.
Args
,
": "
)
args
=
role
+
" "
+
quote
(
message
)
default
:
name
=
"parameter"
args
=
cmd
.
Name
+
" "
+
quote
(
cmd
.
Args
)
}
fmt
.
Fprintln
(
&
sb
,
strings
.
ToUpper
(
name
),
args
)
}
return
sb
.
String
()
}
func
Parse
(
r
io
.
Reader
)
(
cmds
[]
Command
,
err
error
)
{
var
cmd
Command
var
cmd
Command
var
curr
state
var
curr
state
var
b
bytes
.
Buffer
var
b
bytes
.
Buffer
var
role
string
var
role
string
var
f
File
br
:=
bufio
.
NewReader
(
r
)
br
:=
bufio
.
NewReader
(
r
)
for
{
for
{
r
,
_
,
err
:=
br
.
ReadRune
()
r
,
_
,
err
:=
br
.
ReadRune
()
...
@@ -128,7 +134,7 @@ func Parse(r io.Reader) (cmds []Command, err error) {
...
@@ -128,7 +134,7 @@ func Parse(r io.Reader) (cmds []Command, err error) {
}
}
cmd
.
Args
=
s
cmd
.
Args
=
s
cm
ds
=
append
(
cm
ds
,
cmd
)
f
.
Comman
ds
=
append
(
f
.
Comman
ds
,
cmd
)
}
}
b
.
Reset
()
b
.
Reset
()
...
@@ -157,14 +163,14 @@ func Parse(r io.Reader) (cmds []Command, err error) {
...
@@ -157,14 +163,14 @@ func Parse(r io.Reader) (cmds []Command, err error) {
}
}
cmd
.
Args
=
s
cmd
.
Args
=
s
cm
ds
=
append
(
cm
ds
,
cmd
)
f
.
Comman
ds
=
append
(
f
.
Comman
ds
,
cmd
)
default
:
default
:
return
nil
,
io
.
ErrUnexpectedEOF
return
nil
,
io
.
ErrUnexpectedEOF
}
}
for
_
,
cmd
:=
range
cm
ds
{
for
_
,
cmd
:=
range
f
.
Comman
ds
{
if
cmd
.
Name
==
"model"
{
if
cmd
.
Name
==
"model"
{
return
cmds
,
nil
return
&
f
,
nil
}
}
}
}
...
...
parser/parser
_test.go
→
types/model/file
_test.go
View file @
b7a87a22
package
parser
package
model
import
(
import
(
"bytes"
"bytes"
...
@@ -10,7 +10,7 @@ import (
...
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/assert"
)
)
func
TestParse
r
(
t
*
testing
.
T
)
{
func
TestParse
FileFile
(
t
*
testing
.
T
)
{
input
:=
`
input
:=
`
FROM model1
FROM model1
ADAPTER adapter1
ADAPTER adapter1
...
@@ -22,8 +22,8 @@ TEMPLATE template1
...
@@ -22,8 +22,8 @@ TEMPLATE template1
reader
:=
strings
.
NewReader
(
input
)
reader
:=
strings
.
NewReader
(
input
)
commands
,
err
:=
Parse
(
reader
)
modelfile
,
err
:=
Parse
File
(
reader
)
assert
.
N
il
(
t
,
err
)
assert
.
N
oError
(
t
,
err
)
expectedCommands
:=
[]
Command
{
expectedCommands
:=
[]
Command
{
{
Name
:
"model"
,
Args
:
"model1"
},
{
Name
:
"model"
,
Args
:
"model1"
},
...
@@ -34,10 +34,10 @@ TEMPLATE template1
...
@@ -34,10 +34,10 @@ TEMPLATE template1
{
Name
:
"template"
,
Args
:
"template1"
},
{
Name
:
"template"
,
Args
:
"template1"
},
}
}
assert
.
Equal
(
t
,
expectedCommands
,
c
ommands
)
assert
.
Equal
(
t
,
expectedCommands
,
modelfile
.
C
ommands
)
}
}
func
TestParse
r
From
(
t
*
testing
.
T
)
{
func
TestParse
File
From
(
t
*
testing
.
T
)
{
var
cases
=
[]
struct
{
var
cases
=
[]
struct
{
input
string
input
string
expected
[]
Command
expected
[]
Command
...
@@ -85,14 +85,16 @@ func TestParserFrom(t *testing.T) {
...
@@ -85,14 +85,16 @@ func TestParserFrom(t *testing.T) {
for
_
,
c
:=
range
cases
{
for
_
,
c
:=
range
cases
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
commands
,
err
:=
Parse
(
strings
.
NewReader
(
c
.
input
))
modelfile
,
err
:=
Parse
File
(
strings
.
NewReader
(
c
.
input
))
assert
.
ErrorIs
(
t
,
err
,
c
.
err
)
assert
.
ErrorIs
(
t
,
err
,
c
.
err
)
assert
.
Equal
(
t
,
c
.
expected
,
commands
)
if
modelfile
!=
nil
{
assert
.
Equal
(
t
,
c
.
expected
,
modelfile
.
Commands
)
}
})
})
}
}
}
}
func
TestParse
r
ParametersMissingValue
(
t
*
testing
.
T
)
{
func
TestParse
File
ParametersMissingValue
(
t
*
testing
.
T
)
{
input
:=
`
input
:=
`
FROM foo
FROM foo
PARAMETER param1
PARAMETER param1
...
@@ -100,21 +102,21 @@ PARAMETER param1
...
@@ -100,21 +102,21 @@ PARAMETER param1
reader
:=
strings
.
NewReader
(
input
)
reader
:=
strings
.
NewReader
(
input
)
_
,
err
:=
Parse
(
reader
)
_
,
err
:=
Parse
File
(
reader
)
assert
.
ErrorIs
(
t
,
err
,
io
.
ErrUnexpectedEOF
)
assert
.
ErrorIs
(
t
,
err
,
io
.
ErrUnexpectedEOF
)
}
}
func
TestParse
r
BadCommand
(
t
*
testing
.
T
)
{
func
TestParse
File
BadCommand
(
t
*
testing
.
T
)
{
input
:=
`
input
:=
`
FROM foo
FROM foo
BADCOMMAND param1 value1
BADCOMMAND param1 value1
`
`
_
,
err
:=
Parse
(
strings
.
NewReader
(
input
))
_
,
err
:=
Parse
File
(
strings
.
NewReader
(
input
))
assert
.
ErrorIs
(
t
,
err
,
errInvalidCommand
)
assert
.
ErrorIs
(
t
,
err
,
errInvalidCommand
)
}
}
func
TestParse
r
Messages
(
t
*
testing
.
T
)
{
func
TestParse
File
Messages
(
t
*
testing
.
T
)
{
var
cases
=
[]
struct
{
var
cases
=
[]
struct
{
input
string
input
string
expected
[]
Command
expected
[]
Command
...
@@ -123,34 +125,34 @@ func TestParserMessages(t *testing.T) {
...
@@ -123,34 +125,34 @@ func TestParserMessages(t *testing.T) {
{
{
`
`
FROM foo
FROM foo
MESSAGE system You are a
P
arser. Always
P
arse things.
MESSAGE system You are a
file p
arser. Always
p
arse things.
`
,
`
,
[]
Command
{
[]
Command
{
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"message"
,
Args
:
"system: You are a
P
arser. Always
P
arse things."
},
{
Name
:
"message"
,
Args
:
"system: You are a
file p
arser. Always
p
arse things."
},
},
},
nil
,
nil
,
},
},
{
{
`
`
FROM foo
FROM foo
MESSAGE system You are a
P
arser. Always
P
arse things.`
,
MESSAGE system You are a
file p
arser. Always
p
arse things.`
,
[]
Command
{
[]
Command
{
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"message"
,
Args
:
"system: You are a
P
arser. Always
P
arse things."
},
{
Name
:
"message"
,
Args
:
"system: You are a
file p
arser. Always
p
arse things."
},
},
},
nil
,
nil
,
},
},
{
{
`
`
FROM foo
FROM foo
MESSAGE system You are a
P
arser. Always
P
arse things.
MESSAGE system You are a
file p
arser. Always
p
arse things.
MESSAGE user Hey there!
MESSAGE user Hey there!
MESSAGE assistant Hello, I want to parse all the things!
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
P
arser. Always
P
arse things."
},
{
Name
:
"message"
,
Args
:
"system: You are a
file p
arser. Always
p
arse things."
},
{
Name
:
"message"
,
Args
:
"user: Hey there!"
},
{
Name
:
"message"
,
Args
:
"user: Hey there!"
},
{
Name
:
"message"
,
Args
:
"assistant: Hello, I want to parse all the things!"
},
{
Name
:
"message"
,
Args
:
"assistant: Hello, I want to parse all the things!"
},
},
},
...
@@ -160,12 +162,12 @@ MESSAGE assistant Hello, I want to parse all the things!
...
@@ -160,12 +162,12 @@ MESSAGE assistant Hello, I want to parse all the things!
`
`
FROM foo
FROM foo
MESSAGE system """
MESSAGE system """
You are a multiline
P
arser. Always
P
arse things.
You are a multiline
file p
arser. Always
p
arse things.
"""
"""
`
,
`
,
[]
Command
{
[]
Command
{
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"message"
,
Args
:
"system:
\n
You are a multiline
P
arser. Always
P
arse things.
\n
"
},
{
Name
:
"message"
,
Args
:
"system:
\n
You are a multiline
file p
arser. Always
p
arse things.
\n
"
},
},
},
nil
,
nil
,
},
},
...
@@ -196,14 +198,16 @@ MESSAGE system`,
...
@@ -196,14 +198,16 @@ MESSAGE system`,
for
_
,
c
:=
range
cases
{
for
_
,
c
:=
range
cases
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
commands
,
err
:=
Parse
(
strings
.
NewReader
(
c
.
input
))
modelfile
,
err
:=
Parse
File
(
strings
.
NewReader
(
c
.
input
))
assert
.
ErrorIs
(
t
,
err
,
c
.
err
)
assert
.
ErrorIs
(
t
,
err
,
c
.
err
)
assert
.
Equal
(
t
,
c
.
expected
,
commands
)
if
modelfile
!=
nil
{
assert
.
Equal
(
t
,
c
.
expected
,
modelfile
.
Commands
)
}
})
})
}
}
}
}
func
TestParse
r
Quoted
(
t
*
testing
.
T
)
{
func
TestParse
File
Quoted
(
t
*
testing
.
T
)
{
var
cases
=
[]
struct
{
var
cases
=
[]
struct
{
multiline
string
multiline
string
expected
[]
Command
expected
[]
Command
...
@@ -348,14 +352,16 @@ TEMPLATE """
...
@@ -348,14 +352,16 @@ TEMPLATE """
for
_
,
c
:=
range
cases
{
for
_
,
c
:=
range
cases
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
commands
,
err
:=
Parse
(
strings
.
NewReader
(
c
.
multiline
))
modelfile
,
err
:=
Parse
File
(
strings
.
NewReader
(
c
.
multiline
))
assert
.
ErrorIs
(
t
,
err
,
c
.
err
)
assert
.
ErrorIs
(
t
,
err
,
c
.
err
)
assert
.
Equal
(
t
,
c
.
expected
,
commands
)
if
modelfile
!=
nil
{
assert
.
Equal
(
t
,
c
.
expected
,
modelfile
.
Commands
)
}
})
})
}
}
}
}
func
TestParse
r
Parameters
(
t
*
testing
.
T
)
{
func
TestParse
File
Parameters
(
t
*
testing
.
T
)
{
var
cases
=
map
[
string
]
struct
{
var
cases
=
map
[
string
]
struct
{
name
,
value
string
name
,
value
string
}{
}{
...
@@ -404,18 +410,18 @@ func TestParserParameters(t *testing.T) {
...
@@ -404,18 +410,18 @@ func TestParserParameters(t *testing.T) {
var
b
bytes
.
Buffer
var
b
bytes
.
Buffer
fmt
.
Fprintln
(
&
b
,
"FROM foo"
)
fmt
.
Fprintln
(
&
b
,
"FROM foo"
)
fmt
.
Fprintln
(
&
b
,
"PARAMETER"
,
k
)
fmt
.
Fprintln
(
&
b
,
"PARAMETER"
,
k
)
commands
,
err
:=
Parse
(
&
b
)
modelfile
,
err
:=
Parse
File
(
&
b
)
assert
.
N
il
(
t
,
err
)
assert
.
N
oError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
Command
{
assert
.
Equal
(
t
,
[]
Command
{
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
"model"
,
Args
:
"foo"
},
{
Name
:
v
.
name
,
Args
:
v
.
value
},
{
Name
:
v
.
name
,
Args
:
v
.
value
},
},
c
ommands
)
},
modelfile
.
C
ommands
)
})
})
}
}
}
}
func
TestParse
r
Comments
(
t
*
testing
.
T
)
{
func
TestParse
File
Comments
(
t
*
testing
.
T
)
{
var
cases
=
[]
struct
{
var
cases
=
[]
struct
{
input
string
input
string
expected
[]
Command
expected
[]
Command
...
@@ -433,14 +439,14 @@ FROM foo
...
@@ -433,14 +439,14 @@ FROM foo
for
_
,
c
:=
range
cases
{
for
_
,
c
:=
range
cases
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
commands
,
err
:=
Parse
(
strings
.
NewReader
(
c
.
input
))
modelfile
,
err
:=
Parse
File
(
strings
.
NewReader
(
c
.
input
))
assert
.
N
il
(
t
,
err
)
assert
.
N
oError
(
t
,
err
)
assert
.
Equal
(
t
,
c
.
expected
,
c
ommands
)
assert
.
Equal
(
t
,
c
.
expected
,
modelfile
.
C
ommands
)
})
})
}
}
}
}
func
TestParseFormatParse
(
t
*
testing
.
T
)
{
func
TestParseF
ileF
ormatParse
File
(
t
*
testing
.
T
)
{
var
cases
=
[]
string
{
var
cases
=
[]
string
{
`
`
FROM foo
FROM foo
...
@@ -449,7 +455,7 @@ LICENSE MIT
...
@@ -449,7 +455,7 @@ LICENSE MIT
PARAMETER param1 value1
PARAMETER param1 value1
PARAMETER param2 value2
PARAMETER param2 value2
TEMPLATE template1
TEMPLATE template1
MESSAGE system You are a
P
arser. Always
P
arse things.
MESSAGE system You are a
file p
arser. Always
p
arse things.
MESSAGE user Hey there!
MESSAGE user Hey there!
MESSAGE assistant Hello, I want to parse all the things!
MESSAGE assistant Hello, I want to parse all the things!
`
,
`
,
...
@@ -488,13 +494,13 @@ MESSAGE assistant Hello, I want to parse all the things!
...
@@ -488,13 +494,13 @@ MESSAGE assistant Hello, I want to parse all the things!
for
_
,
c
:=
range
cases
{
for
_
,
c
:=
range
cases
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
""
,
func
(
t
*
testing
.
T
)
{
commands
,
err
:=
Parse
(
strings
.
NewReader
(
c
))
modelfile
,
err
:=
Parse
File
(
strings
.
NewReader
(
c
))
assert
.
NoError
(
t
,
err
)
assert
.
NoError
(
t
,
err
)
commands
2
,
err
:=
Parse
(
strings
.
NewReader
(
Format
(
commands
)))
modelfile
2
,
err
:=
Parse
File
(
strings
.
NewReader
(
modelfile
.
String
(
)))
assert
.
NoError
(
t
,
err
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
commands
,
commands
2
)
assert
.
Equal
(
t
,
modelfile
,
modelfile
2
)
})
})
}
}
...
...
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