Add validation to command line flags + update system prompt handling
Renamed `applyPromptFlags` to `applyGenerationFlags` and added `validateGenerationFlags`
This commit is contained in:
@@ -15,6 +15,10 @@ func ChatCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
Short: "Open the chat interface",
|
||||
Long: `Open the chat interface, optionally on a given conversation.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := validateGenerationFlags(ctx, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shortname := ""
|
||||
if len(args) == 1 {
|
||||
shortname = args[0]
|
||||
@@ -25,7 +29,7 @@ func ChatCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err := tui.Launch(ctx, shortname)
|
||||
err = tui.Launch(ctx, shortname)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error fetching LLM response: %v", err)
|
||||
}
|
||||
@@ -39,6 +43,6 @@ func ChatCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return ctx.Store.ConversationShortNameCompletions(toComplete), compMode
|
||||
},
|
||||
}
|
||||
applyPromptFlags(ctx, cmd)
|
||||
applyGenerationFlags(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.mlow.ca/mlow/lmcli/pkg/lmcli"
|
||||
@@ -37,27 +39,43 @@ func RootCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return root
|
||||
}
|
||||
|
||||
func applyPromptFlags(ctx *lmcli.Context, cmd *cobra.Command) {
|
||||
func applyGenerationFlags(ctx *lmcli.Context, cmd *cobra.Command) {
|
||||
f := cmd.Flags()
|
||||
|
||||
// -m, --model
|
||||
f.StringVarP(
|
||||
ctx.Config.Defaults.Model,
|
||||
"model", "m",
|
||||
*ctx.Config.Defaults.Model,
|
||||
"The model to generate a response with",
|
||||
ctx.Config.Defaults.Model, "model", "m",
|
||||
*ctx.Config.Defaults.Model, "Which model to generate a response with",
|
||||
)
|
||||
cmd.RegisterFlagCompletionFunc("model", func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||
return ctx.GetModels(), cobra.ShellCompDirectiveDefault
|
||||
})
|
||||
|
||||
// --max-length
|
||||
f.IntVar(ctx.Config.Defaults.MaxTokens, "max-length", *ctx.Config.Defaults.MaxTokens, "Maximum response tokens")
|
||||
// --temperature
|
||||
f.Float32VarP(ctx.Config.Defaults.Temperature, "temperature", "t", *ctx.Config.Defaults.Temperature, "Sampling temperature")
|
||||
|
||||
// --system-prompt
|
||||
f.StringVar(ctx.Config.Defaults.SystemPrompt, "system-prompt", *ctx.Config.Defaults.SystemPrompt, "System prompt")
|
||||
f.StringVar(&ctx.SystemPromptFile, "system-prompt-file", "", "A path to a file containing the system prompt")
|
||||
// --system-prompt-file
|
||||
f.StringVar(&ctx.Config.Defaults.SystemPromptFile, "system-prompt-file", ctx.Config.Defaults.SystemPromptFile, "A path to a file containing the system prompt")
|
||||
cmd.MarkFlagsMutuallyExclusive("system-prompt", "system-prompt-file")
|
||||
}
|
||||
|
||||
func validateGenerationFlags(ctx *lmcli.Context, cmd *cobra.Command) error {
|
||||
f := cmd.Flags()
|
||||
|
||||
model, err := f.GetString("model")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error parsing --model: %w", err)
|
||||
}
|
||||
if !slices.Contains(ctx.GetModels(), model) {
|
||||
return fmt.Errorf("Unknown model: %s", model)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// inputFromArgsOrEditor returns either the provided input from the args slice
|
||||
// (joined with spaces), or if len(args) is 0, opens an editor and returns
|
||||
// whatever input was provided there. placeholder is a string which populates
|
||||
|
||||
@@ -23,6 +23,11 @@ func ContinueCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := validateGenerationFlags(ctx, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
shortName := args[0]
|
||||
conversation := cmdutil.LookupConversation(ctx, shortName)
|
||||
|
||||
@@ -68,6 +73,6 @@ func ContinueCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return ctx.Store.ConversationShortNameCompletions(toComplete), compMode
|
||||
},
|
||||
}
|
||||
applyPromptFlags(ctx, cmd)
|
||||
applyGenerationFlags(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ func NewCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
Short: "Start a new conversation",
|
||||
Long: `Start a new conversation with the Large Language Model.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := validateGenerationFlags(ctx, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
input := inputFromArgsOrEditor(args, "# Start a new conversation below\n", "")
|
||||
if input == "" {
|
||||
return fmt.Errorf("No message was provided.")
|
||||
@@ -22,8 +27,7 @@ func NewCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
|
||||
var messages []api.Message
|
||||
|
||||
// TODO: probably just make this part of the conversation
|
||||
system := ctx.GetSystemPrompt()
|
||||
system := ctx.Config.GetSystemPrompt()
|
||||
if system != "" {
|
||||
messages = append(messages, api.Message{
|
||||
Role: api.MessageRoleSystem,
|
||||
@@ -57,6 +61,6 @@ func NewCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
applyPromptFlags(ctx, cmd)
|
||||
applyGenerationFlags(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ func PromptCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
Short: "Do a one-shot prompt",
|
||||
Long: `Prompt the Large Language Model and get a response.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := validateGenerationFlags(ctx, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
input := inputFromArgsOrEditor(args, "# Write your prompt below\n", "")
|
||||
if input == "" {
|
||||
return fmt.Errorf("No message was provided.")
|
||||
@@ -22,8 +27,7 @@ func PromptCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
|
||||
var messages []api.Message
|
||||
|
||||
// TODO: stop supplying system prompt as a message
|
||||
system := ctx.GetSystemPrompt()
|
||||
system := ctx.Config.GetSystemPrompt()
|
||||
if system != "" {
|
||||
messages = append(messages, api.Message{
|
||||
Role: api.MessageRoleSystem,
|
||||
@@ -36,7 +40,7 @@ func PromptCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
Content: input,
|
||||
})
|
||||
|
||||
_, err := cmdutil.Prompt(ctx, messages, nil)
|
||||
_, err = cmdutil.Prompt(ctx, messages, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error fetching LLM response: %v", err)
|
||||
}
|
||||
@@ -44,6 +48,6 @@ func PromptCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
applyPromptFlags(ctx, cmd)
|
||||
applyGenerationFlags(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ func ReplyCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := validateGenerationFlags(ctx, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
shortName := args[0]
|
||||
conversation := cmdutil.LookupConversation(ctx, shortName)
|
||||
|
||||
@@ -45,6 +50,6 @@ func ReplyCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
applyPromptFlags(ctx, cmd)
|
||||
applyGenerationFlags(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ func RetryCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := validateGenerationFlags(ctx, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
shortName := args[0]
|
||||
conversation := cmdutil.LookupConversation(ctx, shortName)
|
||||
|
||||
@@ -68,6 +73,6 @@ func RetryCmd(ctx *lmcli.Context) *cobra.Command {
|
||||
|
||||
cmd.Flags().Int("offset", 0, "Offset from the last message to retry from.")
|
||||
|
||||
applyPromptFlags(ctx, cmd)
|
||||
applyGenerationFlags(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user