From 6e0f686afa90c379535e78606851be7078150fd6 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Tue, 14 Nov 2023 10:22:03 -0500 Subject: [PATCH 1/4] `--format json` should work in interactive mode --- cmd/cmd.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index bc70095c..5f2afb0d 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -542,7 +542,11 @@ func generateInteractive(cmd *cobra.Command, model string) error { return err } - var format string + format, err := cmd.Flags().GetString("format") + if err != nil { + return err + } + var wordWrap bool termType := os.Getenv("TERM") if termType == "xterm-256color" { From 4e612a2e92deddf3bdaef688e178c28f49276ccc Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Tue, 14 Nov 2023 16:09:09 -0500 Subject: [PATCH 2/4] use stdout fd for terminal size (#1125) --- cmd/cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 5f2afb0d..9561b81c 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -398,7 +398,7 @@ func generate(cmd *cobra.Command, model, prompt string, wordWrap bool, format st generateContext = []int{} } - termWidth, _, err := term.GetSize(int(0)) + termWidth, _, err := term.GetSize(int(os.Stdout.Fd())) if err != nil { wordWrap = false } From df18486c35559f135639682488710218c30385e2 Mon Sep 17 00:00:00 2001 From: Bruce MacDonald Date: Tue, 14 Nov 2023 16:12:30 -0500 Subject: [PATCH 3/4] Move /generate format to optional parameters (#1127) This field is optional and should be under the `Advanced parameters` header --- docs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index e214ad7a..08402266 100644 --- a/docs/api.md +++ b/docs/api.md @@ -38,10 +38,10 @@ Generate a response for a given prompt with a provided model. This is a streamin - `model`: (required) the [model name](#model-names) - `prompt`: the prompt to generate a response for -- `format`: the format to return a response in. Currently the only accepted value is `json` Advanced parameters (optional): +- `format`: the format to return a response in. Currently the only accepted value is `json` - `options`: additional model parameters listed in the documentation for the [Modelfile](./modelfile.md#valid-parameters-and-values) such as `temperature` - `system`: system prompt to (overrides what is defined in the `Modelfile`) - `template`: the full prompt or prompt template (overrides what is defined in the `Modelfile`) From 423862042a09154873b00549420341c951e2e35d Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Tue, 14 Nov 2023 16:42:21 -0500 Subject: [PATCH 4/4] treat `ollama run model < file` as entire prompt, not prompt-per-line (#1126) Previously, `ollama run` treated a non-terminal stdin (such as `ollama run model < file`) as containing one prompt per line. To run inference on a multi-line prompt, the only non-API workaround was to run `ollama run` interactively and wrap the prompt in `"""..."""`. Now, `ollama run` treats a non-terminal stdin as containing a single prompt. For example, if `myprompt.txt` is a multi-line file, then `ollama run model < myprompt.txt` would treat `myprompt.txt`'s entire contents as the prompt. Co-authored-by: Quinn Slack --- cmd/cmd.go | 82 +++++++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 53 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 9561b81c..d7839558 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,7 +1,6 @@ package cmd import ( - "bufio" "context" "crypto/ed25519" "crypto/rand" @@ -350,34 +349,44 @@ func pull(model string, insecure bool) error { } func RunGenerate(cmd *cobra.Command, args []string) error { - if len(args) > 1 { - // join all args into a single prompt - wordWrap := false - if term.IsTerminal(int(os.Stdout.Fd())) { - wordWrap = true - } + format, err := cmd.Flags().GetString("format") + if err != nil { + return err + } - nowrap, err := cmd.Flags().GetBool("nowordwrap") - if err != nil { - return err - } - if nowrap { - wordWrap = false - } + prompts := args[1:] - format, err := cmd.Flags().GetString("format") + // 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 } - return generate(cmd, args[0], strings.Join(args[1:], " "), wordWrap, format) + prompts = append([]string{string(in)}, prompts...) } - if readline.IsTerminal(int(os.Stdin.Fd())) { - return generateInteractive(cmd, args[0]) + // output is being piped + if !term.IsTerminal(int(os.Stdout.Fd())) { + return generate(cmd, args[0], strings.Join(prompts, " "), false, format) } - return generateBatch(cmd, args[0]) + wordWrap := os.Getenv("TERM") == "xterm-256color" + + nowrap, err := cmd.Flags().GetBool("nowordwrap") + if err != nil { + return err + } + if nowrap { + wordWrap = false + } + + // 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) + } + + return generateInteractive(cmd, args[0], wordWrap, format) } type generateContextKey string @@ -490,7 +499,7 @@ func generate(cmd *cobra.Command, model, prompt string, wordWrap bool, format st return nil } -func generateInteractive(cmd *cobra.Command, model string) error { +func generateInteractive(cmd *cobra.Command, model string, wordWrap bool, format string) error { // load the model if err := generate(cmd, model, "", false, ""); err != nil { return err @@ -542,26 +551,6 @@ func generateInteractive(cmd *cobra.Command, model string) error { return err } - format, err := cmd.Flags().GetString("format") - if err != nil { - return err - } - - var wordWrap bool - termType := os.Getenv("TERM") - if termType == "xterm-256color" { - wordWrap = true - } - - // override wrapping if the user turned it off - nowrap, err := cmd.Flags().GetBool("nowordwrap") - if err != nil { - return err - } - if nowrap { - wordWrap = false - } - fmt.Print(readline.StartBracketedPaste) defer fmt.Printf(readline.EndBracketedPaste) @@ -715,19 +704,6 @@ func generateInteractive(cmd *cobra.Command, model string) error { } } -func generateBatch(cmd *cobra.Command, model string) error { - scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - prompt := scanner.Text() - fmt.Printf(">>> %s\n", prompt) - if err := generate(cmd, model, prompt, false, ""); err != nil { - return err - } - } - - return nil -} - func RunServer(cmd *cobra.Command, _ []string) error { host, port, err := net.SplitHostPort(os.Getenv("OLLAMA_HOST")) if err != nil {