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
cde31cb2
Unverified
Commit
cde31cb2
authored
Nov 29, 2023
by
Patrick Devine
Committed by
GitHub
Nov 29, 2023
Browse files
Allow setting parameters in the REPL (#1294)
parent
63097607
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
153 additions
and
86 deletions
+153
-86
api/types.go
api/types.go
+61
-0
cmd/cmd.go
cmd/cmd.go
+91
-26
server/images.go
server/images.go
+1
-60
No files found.
api/types.go
View file @
cde31cb2
...
...
@@ -6,6 +6,7 @@ import (
"math"
"os"
"reflect"
"strconv"
"strings"
"time"
)
...
...
@@ -360,3 +361,63 @@ func (d *Duration) UnmarshalJSON(b []byte) (err error) {
return
nil
}
// FormatParams converts specified parameter options to their correct types
func
FormatParams
(
params
map
[
string
][]
string
)
(
map
[
string
]
interface
{},
error
)
{
opts
:=
Options
{}
valueOpts
:=
reflect
.
ValueOf
(
&
opts
)
.
Elem
()
// names of the fields in the options struct
typeOpts
:=
reflect
.
TypeOf
(
opts
)
// types of the fields in the options struct
// build map of json struct tags to their types
jsonOpts
:=
make
(
map
[
string
]
reflect
.
StructField
)
for
_
,
field
:=
range
reflect
.
VisibleFields
(
typeOpts
)
{
jsonTag
:=
strings
.
Split
(
field
.
Tag
.
Get
(
"json"
),
","
)[
0
]
if
jsonTag
!=
""
{
jsonOpts
[
jsonTag
]
=
field
}
}
out
:=
make
(
map
[
string
]
interface
{})
// iterate params and set values based on json struct tags
for
key
,
vals
:=
range
params
{
if
opt
,
ok
:=
jsonOpts
[
key
];
!
ok
{
return
nil
,
fmt
.
Errorf
(
"unknown parameter '%s'"
,
key
)
}
else
{
field
:=
valueOpts
.
FieldByName
(
opt
.
Name
)
if
field
.
IsValid
()
&&
field
.
CanSet
()
{
switch
field
.
Kind
()
{
case
reflect
.
Float32
:
floatVal
,
err
:=
strconv
.
ParseFloat
(
vals
[
0
],
32
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid float value %s"
,
vals
)
}
out
[
key
]
=
float32
(
floatVal
)
case
reflect
.
Int
:
intVal
,
err
:=
strconv
.
ParseInt
(
vals
[
0
],
10
,
64
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid int value %s"
,
vals
)
}
out
[
key
]
=
intVal
case
reflect
.
Bool
:
boolVal
,
err
:=
strconv
.
ParseBool
(
vals
[
0
])
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid bool value %s"
,
vals
)
}
out
[
key
]
=
boolVal
case
reflect
.
String
:
out
[
key
]
=
vals
[
0
]
case
reflect
.
Slice
:
// TODO: only string slices are supported right now
out
[
key
]
=
vals
default
:
return
nil
,
fmt
.
Errorf
(
"unknown type %s for %s"
,
field
.
Kind
(),
key
)
}
}
}
}
return
out
,
nil
}
cmd/cmd.go
View file @
cde31cb2
...
...
@@ -412,10 +412,19 @@ func PullHandler(cmd *cobra.Command, args []string) error {
}
func
RunGenerate
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
interactive
:=
true
opts
:=
generateOptions
{
Model
:
args
[
0
],
WordWrap
:
os
.
Getenv
(
"TERM"
)
==
"xterm-256color"
,
Options
:
map
[
string
]
interface
{}{},
}
format
,
err
:=
cmd
.
Flags
()
.
GetString
(
"format"
)
if
err
!=
nil
{
return
err
}
opts
.
Format
=
format
prompts
:=
args
[
1
:
]
...
...
@@ -427,34 +436,38 @@ func RunGenerate(cmd *cobra.Command, args []string) error {
}
prompts
=
append
([]
string
{
string
(
in
)},
prompts
...
)
opts
.
WordWrap
=
false
interactive
=
false
}
// output is being piped
if
!
term
.
IsTerminal
(
int
(
os
.
Stdout
.
Fd
()))
{
return
generate
(
cmd
,
args
[
0
],
strings
.
Join
(
prompts
,
" "
),
false
,
format
)
opts
.
Prompt
=
strings
.
Join
(
prompts
,
" "
)
if
len
(
prompts
)
>
0
{
interactive
=
false
}
wordWrap
:=
os
.
Getenv
(
"TERM"
)
==
"xterm-256color"
nowrap
,
err
:=
cmd
.
Flags
()
.
GetBool
(
"nowordwrap"
)
if
err
!=
nil
{
return
err
}
if
nowrap
{
wordWrap
=
false
}
opts
.
WordWrap
=
!
nowrap
// prompts are provided via stdin or args so don't enter interactive mode
if
len
(
prompts
)
>
0
{
return
generate
(
cmd
,
args
[
0
],
strings
.
Join
(
prompts
,
" "
),
wordWrap
,
format
)
if
!
interactive
{
return
generate
(
cmd
,
opts
)
}
return
generateInteractive
(
cmd
,
args
[
0
],
wordWrap
,
format
)
return
generateInteractive
(
cmd
,
opts
)
}
type
generateContextKey
string
func
generate
(
cmd
*
cobra
.
Command
,
model
,
prompt
string
,
wordWrap
bool
,
format
string
)
error
{
type
generateOptions
struct
{
Model
string
Prompt
string
WordWrap
bool
Format
string
Options
map
[
string
]
interface
{}
}
func
generate
(
cmd
*
cobra
.
Command
,
opts
generateOptions
)
error
{
client
,
err
:=
api
.
ClientFromEnvironment
()
if
err
!=
nil
{
return
err
...
...
@@ -475,7 +488,7 @@ func generate(cmd *cobra.Command, model, prompt string, wordWrap bool, format st
termWidth
,
_
,
err
:=
term
.
GetSize
(
int
(
os
.
Stdout
.
Fd
()))
if
err
!=
nil
{
w
ordWrap
=
false
opts
.
W
ordWrap
=
false
}
cancelCtx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
...
...
@@ -494,13 +507,19 @@ func generate(cmd *cobra.Command, model, prompt string, wordWrap bool, format st
var
currentLineLength
int
var
wordBuffer
string
request
:=
api
.
GenerateRequest
{
Model
:
model
,
Prompt
:
prompt
,
Context
:
generateContext
,
Format
:
format
}
request
:=
api
.
GenerateRequest
{
Model
:
opts
.
Model
,
Prompt
:
opts
.
Prompt
,
Context
:
generateContext
,
Format
:
opts
.
Format
,
Options
:
opts
.
Options
,
}
fn
:=
func
(
response
api
.
GenerateResponse
)
error
{
p
.
StopAndClear
()
latest
=
response
if
w
ordWrap
{
if
opts
.
W
ordWrap
{
for
_
,
ch
:=
range
response
.
Response
{
if
currentLineLength
+
1
>
termWidth
-
5
{
// backtrack the length of the last word and clear to the end of the line
...
...
@@ -534,7 +553,7 @@ func generate(cmd *cobra.Command, model, prompt string, wordWrap bool, format st
}
return
err
}
if
p
rompt
!=
""
{
if
opts
.
P
rompt
!=
""
{
fmt
.
Println
()
fmt
.
Println
()
}
...
...
@@ -562,9 +581,13 @@ func generate(cmd *cobra.Command, model, prompt string, wordWrap bool, format st
return
nil
}
func
generateInteractive
(
cmd
*
cobra
.
Command
,
model
string
,
wordWrap
bool
,
format
string
)
error
{
func
generateInteractive
(
cmd
*
cobra
.
Command
,
opts
generateOptions
)
error
{
// load the model
if
err
:=
generate
(
cmd
,
model
,
""
,
false
,
""
);
err
!=
nil
{
loadOpts
:=
generateOptions
{
Model
:
opts
.
Model
,
Prompt
:
""
,
}
if
err
:=
generate
(
cmd
,
loadOpts
);
err
!=
nil
{
return
err
}
...
...
@@ -581,6 +604,7 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
usageSet
:=
func
()
{
fmt
.
Fprintln
(
os
.
Stderr
,
"Available Commands:"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter Set a parameter"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set history Enable history"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set nohistory Disable history"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set wordwrap Enable wordwrap"
)
...
...
@@ -602,6 +626,22 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
fmt
.
Fprintln
(
os
.
Stderr
,
""
)
}
// only list out the most common parameters
usageParameters
:=
func
()
{
fmt
.
Fprintln
(
os
.
Stderr
,
"Available Parameters:"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter seed <int> Random number seed"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter num_predict <int> Max number of tokens to predict"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter top_k <int> Pick from top k num of tokens"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter top_p <float> Pick token based on sum of probabilities"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter num_ctx <int> Set the context size"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter temperature <float> Set creativity level"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter repeat_penalty <float> How strongly to penalize repetitions"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter repeat_last_n <int> Set how far back to look for repetitions"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter num_gpu <int> The number of layers to send to the GPU"
)
fmt
.
Fprintln
(
os
.
Stderr
,
" /set parameter stop
\"
<string>
\"
, ... Set the stop parameters"
)
fmt
.
Fprintln
(
os
.
Stderr
,
""
)
}
scanner
,
err
:=
readline
.
New
(
readline
.
Prompt
{
Prompt
:
">>> "
,
AltPrompt
:
"... "
,
...
...
@@ -670,10 +710,10 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
case
"nohistory"
:
scanner
.
HistoryDisable
()
case
"wordwrap"
:
w
ordWrap
=
true
opts
.
W
ordWrap
=
true
fmt
.
Println
(
"Set 'wordwrap' mode."
)
case
"nowordwrap"
:
w
ordWrap
=
false
opts
.
W
ordWrap
=
false
fmt
.
Println
(
"Set 'nowordwrap' mode."
)
case
"verbose"
:
cmd
.
Flags
()
.
Set
(
"verbose"
,
"true"
)
...
...
@@ -685,12 +725,28 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
if
len
(
args
)
<
3
||
args
[
2
]
!=
"json"
{
fmt
.
Println
(
"Invalid or missing format. For 'json' mode use '/set format json'"
)
}
else
{
f
ormat
=
args
[
2
]
opts
.
F
ormat
=
args
[
2
]
fmt
.
Printf
(
"Set format to '%s' mode.
\n
"
,
args
[
2
])
}
case
"noformat"
:
f
ormat
=
""
opts
.
F
ormat
=
""
fmt
.
Println
(
"Disabled format."
)
case
"parameter"
:
if
len
(
args
)
<
4
{
usageParameters
()
continue
}
var
params
[]
string
for
_
,
p
:=
range
args
[
3
:
]
{
params
=
append
(
params
,
p
)
}
fp
,
err
:=
api
.
FormatParams
(
map
[
string
][]
string
{
args
[
2
]
:
params
})
if
err
!=
nil
{
fmt
.
Printf
(
"Couldn't set parameter: %q
\n\n
"
,
err
)
continue
}
fmt
.
Printf
(
"Set parameter '%s' to '%s'
\n\n
"
,
args
[
2
],
strings
.
Join
(
params
,
", "
))
opts
.
Options
[
args
[
2
]]
=
fp
[
args
[
2
]]
default
:
fmt
.
Printf
(
"Unknown command '/set %s'. Type /? for help
\n
"
,
args
[
1
])
}
...
...
@@ -705,7 +761,7 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
fmt
.
Println
(
"error: couldn't connect to ollama server"
)
return
err
}
resp
,
err
:=
client
.
Show
(
cmd
.
Context
(),
&
api
.
ShowRequest
{
Name
:
m
odel
})
resp
,
err
:=
client
.
Show
(
cmd
.
Context
(),
&
api
.
ShowRequest
{
Name
:
opts
.
M
odel
})
if
err
!=
nil
{
fmt
.
Println
(
"error: couldn't get model"
)
return
err
...
...
@@ -724,6 +780,14 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
if
resp
.
Parameters
==
""
{
fmt
.
Print
(
"No parameters were specified for this model.
\n\n
"
)
}
else
{
if
len
(
opts
.
Options
)
>
0
{
fmt
.
Println
(
"User defined parameters:"
)
for
k
,
v
:=
range
opts
.
Options
{
fmt
.
Printf
(
"%-*s %v
\n
"
,
30
,
k
,
v
)
}
fmt
.
Println
()
}
fmt
.
Println
(
"Model defined parameters:"
)
fmt
.
Println
(
resp
.
Parameters
)
}
case
"system"
:
...
...
@@ -767,7 +831,8 @@ func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format
}
if
len
(
prompt
)
>
0
&&
prompt
[
0
]
!=
'/'
{
if
err
:=
generate
(
cmd
,
model
,
prompt
,
wordWrap
,
format
);
err
!=
nil
{
opts
.
Prompt
=
prompt
if
err
:=
generate
(
cmd
,
opts
);
err
!=
nil
{
return
err
}
...
...
server/images.go
View file @
cde31cb2
...
...
@@ -14,7 +14,6 @@ import (
"net/url"
"os"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
...
...
@@ -426,7 +425,7 @@ func CreateModel(ctx context.Context, name, modelFileDir string, commands []pars
if
len
(
params
)
>
0
{
fn
(
api
.
ProgressResponse
{
Status
:
"creating parameters layer"
})
formattedParams
,
err
:=
f
ormatParams
(
params
)
formattedParams
,
err
:=
api
.
F
ormatParams
(
params
)
if
err
!=
nil
{
return
err
}
...
...
@@ -581,64 +580,6 @@ func GetLayerWithBufferFromLayer(layer *Layer) (*LayerReader, error) {
return
newLayer
,
nil
}
// formatParams converts specified parameter options to their correct types
func
formatParams
(
params
map
[
string
][]
string
)
(
map
[
string
]
interface
{},
error
)
{
opts
:=
api
.
Options
{}
valueOpts
:=
reflect
.
ValueOf
(
&
opts
)
.
Elem
()
// names of the fields in the options struct
typeOpts
:=
reflect
.
TypeOf
(
opts
)
// types of the fields in the options struct
// build map of json struct tags to their types
jsonOpts
:=
make
(
map
[
string
]
reflect
.
StructField
)
for
_
,
field
:=
range
reflect
.
VisibleFields
(
typeOpts
)
{
jsonTag
:=
strings
.
Split
(
field
.
Tag
.
Get
(
"json"
),
","
)[
0
]
if
jsonTag
!=
""
{
jsonOpts
[
jsonTag
]
=
field
}
}
out
:=
make
(
map
[
string
]
interface
{})
// iterate params and set values based on json struct tags
for
key
,
vals
:=
range
params
{
if
opt
,
ok
:=
jsonOpts
[
key
];
ok
{
field
:=
valueOpts
.
FieldByName
(
opt
.
Name
)
if
field
.
IsValid
()
&&
field
.
CanSet
()
{
switch
field
.
Kind
()
{
case
reflect
.
Float32
:
floatVal
,
err
:=
strconv
.
ParseFloat
(
vals
[
0
],
32
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid float value %s"
,
vals
)
}
out
[
key
]
=
float32
(
floatVal
)
case
reflect
.
Int
:
intVal
,
err
:=
strconv
.
ParseInt
(
vals
[
0
],
10
,
64
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid int value %s"
,
vals
)
}
out
[
key
]
=
intVal
case
reflect
.
Bool
:
boolVal
,
err
:=
strconv
.
ParseBool
(
vals
[
0
])
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid bool value %s"
,
vals
)
}
out
[
key
]
=
boolVal
case
reflect
.
String
:
out
[
key
]
=
vals
[
0
]
case
reflect
.
Slice
:
// TODO: only string slices are supported right now
out
[
key
]
=
vals
default
:
return
nil
,
fmt
.
Errorf
(
"unknown type %s for %s"
,
field
.
Kind
(),
key
)
}
}
}
}
return
out
,
nil
}
func
getLayerDigests
(
layers
[]
*
LayerReader
)
([]
string
,
error
)
{
var
digests
[]
string
for
_
,
l
:=
range
layers
{
...
...
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