Add multimodel support to ollama run
in noninteractive mopde (#2317)
This commit is contained in:
parent
38296ab352
commit
e135167484
2 changed files with 56 additions and 49 deletions
101
cmd/cmd.go
101
cmd/cmd.go
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
"github.com/jmorganca/ollama/api"
|
"github.com/jmorganca/ollama/api"
|
||||||
|
@ -147,7 +148,7 @@ func RunHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
// check if the model exists on the server
|
// check if the model exists on the server
|
||||||
_, err = client.Show(cmd.Context(), &api.ShowRequest{Name: name})
|
show, err := client.Show(cmd.Context(), &api.ShowRequest{Name: name})
|
||||||
var statusError api.StatusError
|
var statusError api.StatusError
|
||||||
switch {
|
switch {
|
||||||
case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound:
|
case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound:
|
||||||
|
@ -158,7 +159,50 @@ func RunHandler(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return RunGenerate(cmd, args)
|
interactive := true
|
||||||
|
|
||||||
|
opts := runOptions{
|
||||||
|
Model: args[0],
|
||||||
|
WordWrap: os.Getenv("TERM") == "xterm-256color",
|
||||||
|
Options: map[string]interface{}{},
|
||||||
|
MultiModal: slices.Contains(show.Details.Families, "clip"),
|
||||||
|
ParentModel: show.Details.ParentModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
format, err := cmd.Flags().GetString("format")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.Format = format
|
||||||
|
|
||||||
|
prompts := args[1:]
|
||||||
|
// prepend stdin to the prompt if provided
|
||||||
|
if !term.IsTerminal(int(os.Stdin.Fd())) {
|
||||||
|
in, err := io.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
prompts = append([]string{string(in)}, prompts...)
|
||||||
|
opts.WordWrap = false
|
||||||
|
interactive = false
|
||||||
|
}
|
||||||
|
opts.Prompt = strings.Join(prompts, " ")
|
||||||
|
if len(prompts) > 0 {
|
||||||
|
interactive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
nowrap, err := cmd.Flags().GetBool("nowordwrap")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.WordWrap = !nowrap
|
||||||
|
|
||||||
|
if !interactive {
|
||||||
|
return generate(cmd, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateInteractive(cmd, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PushHandler(cmd *cobra.Command, args []string) error {
|
func PushHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -410,51 +454,6 @@ func PullHandler(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunGenerate(cmd *cobra.Command, args []string) error {
|
|
||||||
interactive := true
|
|
||||||
|
|
||||||
opts := runOptions{
|
|
||||||
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:]
|
|
||||||
// prepend stdin to the prompt if provided
|
|
||||||
if !term.IsTerminal(int(os.Stdin.Fd())) {
|
|
||||||
in, err := io.ReadAll(os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
prompts = append([]string{string(in)}, prompts...)
|
|
||||||
opts.WordWrap = false
|
|
||||||
interactive = false
|
|
||||||
}
|
|
||||||
opts.Prompt = strings.Join(prompts, " ")
|
|
||||||
if len(prompts) > 0 {
|
|
||||||
interactive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
nowrap, err := cmd.Flags().GetBool("nowordwrap")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
opts.WordWrap = !nowrap
|
|
||||||
|
|
||||||
if !interactive {
|
|
||||||
return generate(cmd, opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return generateInteractive(cmd, opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
type generateContextKey string
|
type generateContextKey string
|
||||||
|
|
||||||
type runOptions struct {
|
type runOptions struct {
|
||||||
|
@ -630,10 +629,18 @@ func generate(cmd *cobra.Command, opts runOptions) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.MultiModal {
|
||||||
|
opts.Prompt, opts.Images, err = extractFileData(opts.Prompt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
request := api.GenerateRequest{
|
request := api.GenerateRequest{
|
||||||
Model: opts.Model,
|
Model: opts.Model,
|
||||||
Prompt: opts.Prompt,
|
Prompt: opts.Prompt,
|
||||||
Context: generateContext,
|
Context: generateContext,
|
||||||
|
Images: opts.Images,
|
||||||
Format: opts.Format,
|
Format: opts.Format,
|
||||||
System: opts.System,
|
System: opts.System,
|
||||||
Template: opts.Template,
|
Template: opts.Template,
|
||||||
|
|
|
@ -601,10 +601,10 @@ func extractFileData(input string) (string, []api.ImageData, error) {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Printf("Couldn't process image: %q\n", err)
|
fmt.Fprintf(os.Stderr, "Couldn't process image: %q\n", err)
|
||||||
return "", imgs, err
|
return "", imgs, err
|
||||||
}
|
}
|
||||||
fmt.Printf("Added image '%s'\n", nfp)
|
fmt.Fprintf(os.Stderr, "Added image '%s'\n", nfp)
|
||||||
input = strings.ReplaceAll(input, fp, "")
|
input = strings.ReplaceAll(input, fp, "")
|
||||||
imgs = append(imgs, data)
|
imgs = append(imgs, data)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue