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
790d24eb
Unverified
Commit
790d24eb
authored
Sep 06, 2023
by
Patrick Devine
Committed by
GitHub
Sep 06, 2023
Browse files
add show command (#474)
parent
7de30085
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
299 additions
and
50 deletions
+299
-50
api/client.go
api/client.go
+8
-0
api/types.go
api/types.go
+12
-0
cmd/cmd.go
cmd/cmd.go
+108
-41
server/images.go
server/images.go
+98
-9
server/routes.go
server/routes.go
+73
-0
No files found.
api/client.go
View file @
790d24eb
...
@@ -255,6 +255,14 @@ func (c *Client) Delete(ctx context.Context, req *DeleteRequest) error {
...
@@ -255,6 +255,14 @@ func (c *Client) Delete(ctx context.Context, req *DeleteRequest) error {
return
nil
return
nil
}
}
func
(
c
*
Client
)
Show
(
ctx
context
.
Context
,
req
*
ShowRequest
)
(
*
ShowResponse
,
error
)
{
var
resp
ShowResponse
if
err
:=
c
.
do
(
ctx
,
http
.
MethodPost
,
"/api/show"
,
req
,
&
resp
);
err
!=
nil
{
return
nil
,
err
}
return
&
resp
,
nil
}
func
(
c
*
Client
)
Heartbeat
(
ctx
context
.
Context
)
error
{
func
(
c
*
Client
)
Heartbeat
(
ctx
context
.
Context
)
error
{
if
err
:=
c
.
do
(
ctx
,
http
.
MethodHead
,
"/"
,
nil
,
nil
);
err
!=
nil
{
if
err
:=
c
.
do
(
ctx
,
http
.
MethodHead
,
"/"
,
nil
,
nil
);
err
!=
nil
{
return
err
return
err
...
...
api/types.go
View file @
790d24eb
...
@@ -61,6 +61,18 @@ type DeleteRequest struct {
...
@@ -61,6 +61,18 @@ type DeleteRequest struct {
Name
string
`json:"name"`
Name
string
`json:"name"`
}
}
type
ShowRequest
struct
{
Name
string
`json:"name"`
}
type
ShowResponse
struct
{
License
string
`json:"license,omitempty"`
Modelfile
string
`json:"modelfile,omitempty"`
Parameters
string
`json:"parameters,omitempty"`
Template
string
`json:"template,omitempty"`
System
string
`json:"system,omitempty"`
}
type
CopyRequest
struct
{
type
CopyRequest
struct
{
Source
string
`json:"source"`
Source
string
`json:"source"`
Destination
string
`json:"destination"`
Destination
string
`json:"destination"`
...
...
cmd/cmd.go
View file @
790d24eb
...
@@ -230,6 +230,84 @@ func DeleteHandler(cmd *cobra.Command, args []string) error {
...
@@ -230,6 +230,84 @@ func DeleteHandler(cmd *cobra.Command, args []string) error {
return
nil
return
nil
}
}
func
ShowHandler
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
client
,
err
:=
api
.
FromEnv
()
if
err
!=
nil
{
return
err
}
if
len
(
args
)
!=
1
{
return
errors
.
New
(
"missing model name"
)
}
license
,
errLicense
:=
cmd
.
Flags
()
.
GetBool
(
"license"
)
modelfile
,
errModelfile
:=
cmd
.
Flags
()
.
GetBool
(
"modelfile"
)
parameters
,
errParams
:=
cmd
.
Flags
()
.
GetBool
(
"parameters"
)
system
,
errSystem
:=
cmd
.
Flags
()
.
GetBool
(
"system"
)
template
,
errTemplate
:=
cmd
.
Flags
()
.
GetBool
(
"template"
)
for
_
,
boolErr
:=
range
[]
error
{
errLicense
,
errModelfile
,
errParams
,
errSystem
,
errTemplate
}
{
if
boolErr
!=
nil
{
return
errors
.
New
(
"error retrieving flags"
)
}
}
flagsSet
:=
0
showType
:=
""
if
license
{
flagsSet
++
showType
=
"license"
}
if
modelfile
{
flagsSet
++
showType
=
"modelfile"
}
if
parameters
{
flagsSet
++
showType
=
"parameters"
}
if
system
{
flagsSet
++
showType
=
"system"
}
if
template
{
flagsSet
++
showType
=
"template"
}
if
flagsSet
>
1
{
return
errors
.
New
(
"only one of 'license', 'modelfile', 'parameters', 'system', or 'template' can be set"
)
}
else
if
flagsSet
==
0
{
return
errors
.
New
(
"one of 'license', 'modelfile', 'parameters', 'system', or 'template' must be set"
)
}
req
:=
api
.
ShowRequest
{
Name
:
args
[
0
]}
resp
,
err
:=
client
.
Show
(
context
.
Background
(),
&
req
)
if
err
!=
nil
{
return
err
}
switch
showType
{
case
"license"
:
fmt
.
Println
(
resp
.
License
)
case
"modelfile"
:
fmt
.
Println
(
resp
.
Modelfile
)
case
"parameters"
:
fmt
.
Println
(
resp
.
Parameters
)
case
"system"
:
fmt
.
Println
(
resp
.
System
)
case
"template"
:
fmt
.
Println
(
resp
.
Template
)
}
return
nil
}
func
CopyHandler
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
func
CopyHandler
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
client
,
err
:=
api
.
FromEnv
()
client
,
err
:=
api
.
FromEnv
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -377,20 +455,6 @@ func generate(cmd *cobra.Command, model, prompt string) error {
...
@@ -377,20 +455,6 @@ func generate(cmd *cobra.Command, model, prompt string) error {
return
nil
return
nil
}
}
func
showLayer
(
l
*
server
.
Layer
)
{
filename
,
err
:=
server
.
GetBlobsPath
(
l
.
Digest
)
if
err
!=
nil
{
fmt
.
Println
(
"Couldn't get layer's path"
)
return
}
bts
,
err
:=
os
.
ReadFile
(
filename
)
if
err
!=
nil
{
fmt
.
Println
(
"Couldn't read layer"
)
return
}
fmt
.
Println
(
string
(
bts
))
}
func
generateInteractive
(
cmd
*
cobra
.
Command
,
model
string
)
error
{
func
generateInteractive
(
cmd
*
cobra
.
Command
,
model
string
)
error
{
home
,
err
:=
os
.
UserHomeDir
()
home
,
err
:=
os
.
UserHomeDir
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -413,6 +477,8 @@ func generateInteractive(cmd *cobra.Command, model string) error {
...
@@ -413,6 +477,8 @@ func generateInteractive(cmd *cobra.Command, model string) error {
),
),
readline
.
PcItem
(
"/show"
,
readline
.
PcItem
(
"/show"
,
readline
.
PcItem
(
"license"
),
readline
.
PcItem
(
"license"
),
readline
.
PcItem
(
"modelfile"
),
readline
.
PcItem
(
"parameters"
),
readline
.
PcItem
(
"system"
),
readline
.
PcItem
(
"system"
),
readline
.
PcItem
(
"template"
),
readline
.
PcItem
(
"template"
),
),
),
...
@@ -522,42 +588,28 @@ func generateInteractive(cmd *cobra.Command, model string) error {
...
@@ -522,42 +588,28 @@ func generateInteractive(cmd *cobra.Command, model string) error {
case
strings
.
HasPrefix
(
line
,
"/show"
)
:
case
strings
.
HasPrefix
(
line
,
"/show"
)
:
args
:=
strings
.
Fields
(
line
)
args
:=
strings
.
Fields
(
line
)
if
len
(
args
)
>
1
{
if
len
(
args
)
>
1
{
mp
:=
server
.
Parse
Model
Path
(
model
)
resp
,
err
:=
server
.
Get
Model
Info
(
model
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
fmt
.
Println
(
"error: couldn't get model"
)
}
manifest
,
_
,
err
:=
server
.
GetManifest
(
mp
)
if
err
!=
nil
{
fmt
.
Println
(
"error: couldn't get a manifest for this model"
)
continue
continue
}
}
switch
args
[
1
]
{
switch
args
[
1
]
{
case
"license"
:
case
"license"
:
for
_
,
l
:=
range
manifest
.
Layers
{
fmt
.
Println
(
resp
.
License
)
if
l
.
MediaType
==
"application/vnd.ollama.image.license"
{
case
"modelfile"
:
showLayer
(
l
)
fmt
.
Println
(
resp
.
Modelfile
)
}
case
"parameters"
:
}
fmt
.
Println
(
resp
.
Parameters
)
continue
case
"system"
:
case
"system"
:
for
_
,
l
:=
range
manifest
.
Layers
{
fmt
.
Println
(
resp
.
System
)
if
l
.
MediaType
==
"application/vnd.ollama.image.system"
{
showLayer
(
l
)
}
}
continue
case
"template"
:
case
"template"
:
for
_
,
l
:=
range
manifest
.
Layers
{
fmt
.
Println
(
resp
.
Template
)
if
l
.
MediaType
==
"application/vnd.ollama.image.template"
{
showLayer
(
l
)
}
}
continue
default
:
default
:
usage
()
fmt
.
Println
(
"error: unknown command"
)
continue
}
}
continue
}
else
{
}
else
{
usage
()
usage
()
continue
continue
...
@@ -749,6 +801,20 @@ func NewCLI() *cobra.Command {
...
@@ -749,6 +801,20 @@ func NewCLI() *cobra.Command {
createCmd
.
Flags
()
.
StringP
(
"file"
,
"f"
,
"Modelfile"
,
"Name of the Modelfile (default
\"
Modelfile
\"
)"
)
createCmd
.
Flags
()
.
StringP
(
"file"
,
"f"
,
"Modelfile"
,
"Name of the Modelfile (default
\"
Modelfile
\"
)"
)
showCmd
:=
&
cobra
.
Command
{
Use
:
"show MODEL"
,
Short
:
"Show information for a model"
,
Args
:
cobra
.
MinimumNArgs
(
1
),
PreRunE
:
checkServerHeartbeat
,
RunE
:
ShowHandler
,
}
showCmd
.
Flags
()
.
Bool
(
"license"
,
false
,
"Show license of a model"
)
showCmd
.
Flags
()
.
Bool
(
"modelfile"
,
false
,
"Show Modelfile of a model"
)
showCmd
.
Flags
()
.
Bool
(
"parameters"
,
false
,
"Show parameters of a model"
)
showCmd
.
Flags
()
.
Bool
(
"template"
,
false
,
"Show template of a model"
)
showCmd
.
Flags
()
.
Bool
(
"system"
,
false
,
"Show system prompt of a model"
)
runCmd
:=
&
cobra
.
Command
{
runCmd
:=
&
cobra
.
Command
{
Use
:
"run MODEL [PROMPT]"
,
Use
:
"run MODEL [PROMPT]"
,
Short
:
"Run a model"
,
Short
:
"Run a model"
,
...
@@ -814,6 +880,7 @@ func NewCLI() *cobra.Command {
...
@@ -814,6 +880,7 @@ func NewCLI() *cobra.Command {
rootCmd
.
AddCommand
(
rootCmd
.
AddCommand
(
serveCmd
,
serveCmd
,
createCmd
,
createCmd
,
showCmd
,
runCmd
,
runCmd
,
pullCmd
,
pullCmd
,
pushCmd
,
pushCmd
,
...
...
server/images.go
View file @
790d24eb
...
@@ -41,15 +41,18 @@ type RegistryOptions struct {
...
@@ -41,15 +41,18 @@ type RegistryOptions struct {
}
}
type
Model
struct
{
type
Model
struct
{
Name
string
`json:"name"`
Name
string
`json:"name"`
ModelPath
string
ShortName
string
AdapterPaths
[]
string
ModelPath
string
Template
string
OriginalModel
string
System
string
AdapterPaths
[]
string
Digest
string
Template
string
ConfigDigest
string
System
string
Options
map
[
string
]
interface
{}
License
[]
string
Embeddings
[]
vector
.
Embedding
Digest
string
ConfigDigest
string
Options
map
[
string
]
interface
{}
Embeddings
[]
vector
.
Embedding
}
}
func
(
m
*
Model
)
Prompt
(
request
api
.
GenerateRequest
,
embedding
string
)
(
string
,
error
)
{
func
(
m
*
Model
)
Prompt
(
request
api
.
GenerateRequest
,
embedding
string
)
(
string
,
error
)
{
...
@@ -171,9 +174,11 @@ func GetModel(name string) (*Model, error) {
...
@@ -171,9 +174,11 @@ func GetModel(name string) (*Model, error) {
model
:=
&
Model
{
model
:=
&
Model
{
Name
:
mp
.
GetFullTagname
(),
Name
:
mp
.
GetFullTagname
(),
ShortName
:
mp
.
GetShortTagname
(),
Digest
:
digest
,
Digest
:
digest
,
ConfigDigest
:
manifest
.
Config
.
Digest
,
ConfigDigest
:
manifest
.
Config
.
Digest
,
Template
:
"{{ .Prompt }}"
,
Template
:
"{{ .Prompt }}"
,
License
:
[]
string
{},
}
}
for
_
,
layer
:=
range
manifest
.
Layers
{
for
_
,
layer
:=
range
manifest
.
Layers
{
...
@@ -185,6 +190,7 @@ func GetModel(name string) (*Model, error) {
...
@@ -185,6 +190,7 @@ 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
model
.
OriginalModel
=
layer
.
From
case
"application/vnd.ollama.image.embed"
:
case
"application/vnd.ollama.image.embed"
:
file
,
err
:=
os
.
Open
(
filename
)
file
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -229,6 +235,12 @@ func GetModel(name string) (*Model, error) {
...
@@ -229,6 +235,12 @@ func GetModel(name string) (*Model, error) {
if
err
=
json
.
NewDecoder
(
params
)
.
Decode
(
&
model
.
Options
);
err
!=
nil
{
if
err
=
json
.
NewDecoder
(
params
)
.
Decode
(
&
model
.
Options
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
case
"application/vnd.ollama.image.license"
:
bts
,
err
:=
os
.
ReadFile
(
filename
)
if
err
!=
nil
{
return
nil
,
err
}
model
.
License
=
append
(
model
.
License
,
string
(
bts
))
}
}
}
}
...
@@ -933,6 +945,83 @@ func DeleteModel(name string) error {
...
@@ -933,6 +945,83 @@ func DeleteModel(name string) error {
return
nil
return
nil
}
}
func
ShowModelfile
(
model
*
Model
)
(
string
,
error
)
{
type
modelTemplate
struct
{
*
Model
From
string
Params
string
}
var
params
[]
string
for
k
,
v
:=
range
model
.
Options
{
switch
val
:=
v
.
(
type
)
{
case
string
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
val
))
case
int
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
strconv
.
Itoa
(
val
)))
case
float64
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
strconv
.
FormatFloat
(
val
,
'f'
,
0
,
64
)))
case
bool
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
strconv
.
FormatBool
(
val
)))
case
[]
interface
{}
:
for
_
,
nv
:=
range
val
{
switch
nval
:=
nv
.
(
type
)
{
case
string
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
nval
))
case
int
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
strconv
.
Itoa
(
nval
)))
case
float64
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
strconv
.
FormatFloat
(
nval
,
'f'
,
0
,
64
)))
case
bool
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"PARAMETER %s %s"
,
k
,
strconv
.
FormatBool
(
nval
)))
default
:
log
.
Printf
(
"unknown type: %s"
,
reflect
.
TypeOf
(
nv
)
.
String
())
}
}
default
:
log
.
Printf
(
"unknown type: %s"
,
reflect
.
TypeOf
(
v
)
.
String
())
}
}
mt
:=
modelTemplate
{
Model
:
model
,
From
:
model
.
OriginalModel
,
Params
:
strings
.
Join
(
params
,
"
\n
"
),
}
if
mt
.
From
==
""
{
mt
.
From
=
model
.
ModelPath
}
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 }}"""
SYSTEM """{{ .System }}"""
{{ .Params }}
`
for
_
,
l
:=
range
mt
.
Model
.
AdapterPaths
{
modelFile
+=
fmt
.
Sprintf
(
"ADAPTER %s
\n
"
,
l
)
}
tmpl
,
err
:=
template
.
New
(
""
)
.
Parse
(
modelFile
)
if
err
!=
nil
{
log
.
Printf
(
"error parsing template: %q"
,
err
)
return
""
,
err
}
var
buf
bytes
.
Buffer
if
err
=
tmpl
.
Execute
(
&
buf
,
mt
);
err
!=
nil
{
log
.
Printf
(
"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
{
func
PushModel
(
ctx
context
.
Context
,
name
string
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
mp
:=
ParseModelPath
(
name
)
mp
:=
ParseModelPath
(
name
)
fn
(
api
.
ProgressResponse
{
Status
:
"retrieving manifest"
})
fn
(
api
.
ProgressResponse
{
Status
:
"retrieving manifest"
})
...
...
server/routes.go
View file @
790d24eb
...
@@ -12,6 +12,7 @@ import (
...
@@ -12,6 +12,7 @@ import (
"os/signal"
"os/signal"
"path/filepath"
"path/filepath"
"reflect"
"reflect"
"strconv"
"strings"
"strings"
"sync"
"sync"
"syscall"
"syscall"
...
@@ -364,6 +365,77 @@ func DeleteModelHandler(c *gin.Context) {
...
@@ -364,6 +365,77 @@ func DeleteModelHandler(c *gin.Context) {
}
}
}
}
func
ShowModelHandler
(
c
*
gin
.
Context
)
{
var
req
api
.
ShowRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
c
.
JSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
}
resp
,
err
:=
GetModelInfo
(
req
.
Name
)
if
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
c
.
JSON
(
http
.
StatusNotFound
,
gin
.
H
{
"error"
:
fmt
.
Sprintf
(
"model '%s' not found"
,
req
.
Name
)})
}
else
{
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"error"
:
err
.
Error
()})
}
return
}
c
.
JSON
(
http
.
StatusOK
,
resp
)
}
func
GetModelInfo
(
name
string
)
(
*
api
.
ShowResponse
,
error
)
{
model
,
err
:=
GetModel
(
name
)
if
err
!=
nil
{
return
nil
,
err
}
resp
:=
&
api
.
ShowResponse
{
License
:
strings
.
Join
(
model
.
License
,
"
\n
"
),
System
:
model
.
System
,
Template
:
model
.
Template
,
}
mf
,
err
:=
ShowModelfile
(
model
)
if
err
!=
nil
{
return
nil
,
err
}
resp
.
Modelfile
=
mf
var
params
[]
string
cs
:=
30
for
k
,
v
:=
range
model
.
Options
{
switch
val
:=
v
.
(
type
)
{
case
string
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
val
))
case
int
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
strconv
.
Itoa
(
val
)))
case
float64
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
strconv
.
FormatFloat
(
val
,
'f'
,
0
,
64
)))
case
bool
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
strconv
.
FormatBool
(
val
)))
case
[]
interface
{}
:
for
_
,
nv
:=
range
val
{
switch
nval
:=
nv
.
(
type
)
{
case
string
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
nval
))
case
int
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
strconv
.
Itoa
(
nval
)))
case
float64
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
strconv
.
FormatFloat
(
nval
,
'f'
,
0
,
64
)))
case
bool
:
params
=
append
(
params
,
fmt
.
Sprintf
(
"%-*s %s"
,
cs
,
k
,
strconv
.
FormatBool
(
nval
)))
}
}
}
}
resp
.
Parameters
=
strings
.
Join
(
params
,
"
\n
"
)
return
resp
,
nil
}
func
ListModelsHandler
(
c
*
gin
.
Context
)
{
func
ListModelsHandler
(
c
*
gin
.
Context
)
{
var
models
[]
api
.
ModelResponse
var
models
[]
api
.
ModelResponse
fp
,
err
:=
GetManifestPath
()
fp
,
err
:=
GetManifestPath
()
...
@@ -457,6 +529,7 @@ func Serve(ln net.Listener, origins []string) error {
...
@@ -457,6 +529,7 @@ func Serve(ln net.Listener, origins []string) error {
r
.
POST
(
"/api/copy"
,
CopyModelHandler
)
r
.
POST
(
"/api/copy"
,
CopyModelHandler
)
r
.
GET
(
"/api/tags"
,
ListModelsHandler
)
r
.
GET
(
"/api/tags"
,
ListModelsHandler
)
r
.
DELETE
(
"/api/delete"
,
DeleteModelHandler
)
r
.
DELETE
(
"/api/delete"
,
DeleteModelHandler
)
r
.
POST
(
"/api/show"
,
ShowModelHandler
)
log
.
Printf
(
"Listening on %s"
,
ln
.
Addr
())
log
.
Printf
(
"Listening on %s"
,
ln
.
Addr
())
s
:=
&
http
.
Server
{
s
:=
&
http
.
Server
{
...
...
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