Compare commits

...

2 Commits

Author SHA1 Message Date
1e8ff60c54 Add lmcli rename to rename conversations 2023-11-29 15:33:25 +00:00
af2fccd4ee Fix README errors 2023-11-29 15:33:25 +00:00
3 changed files with 65 additions and 14 deletions

View File

@ -29,17 +29,17 @@ the model could at any time decide to use one of these tools to discover and
read potentially sensitive information from your filesystem.** read potentially sensitive information from your filesystem.**
It's best to only have these tools enabled in `config.yaml` when you intend to It's best to only have these tools enabled in `config.yaml` when you intend to
be using them, because their descriptions (see `pkg/cmd/functions.go`) count be using them, because their descriptions (see `pkg/cli/functions.go`) count
towards context usage. towards context usage.
Available tools: Available tools:
- `read_dir` - Read the contents of a directory - `read_dir` - Read the contents of a directory.
- `read_file` - Read the contents of a file - `read_file` - Read the contents of a file.
- `write_file` - Write contents to a file - `write_file` - Write contents to a file.
- `insert_file_lines` - Insert lines at a position within a file. Tricky for - `file_insert_lines` - Insert lines at a position within a file. Tricky for
the model to use, but can potentially save tokens. the model to use, but can potentially save tokens.
- `replace_file_lines` - Remove or replace a range of lines within a file. Even - `file_replace_lines` - Remove or replace a range of lines within a file. Even
trickier for the model to use. trickier for the model to use.
## Install ## Install

View File

@ -26,11 +26,14 @@ func init() {
cmd.MarkFlagsMutuallyExclusive("system-prompt", "system-prompt-file") cmd.MarkFlagsMutuallyExclusive("system-prompt", "system-prompt-file")
} }
renameCmd.Flags().Bool("generate", false, "Use the LLM to generate the conversation title.")
rootCmd.AddCommand( rootCmd.AddCommand(
continueCmd, continueCmd,
lsCmd, lsCmd,
newCmd, newCmd,
promptCmd, promptCmd,
renameCmd,
replyCmd, replyCmd,
retryCmd, retryCmd,
rmCmd, rmCmd,
@ -357,8 +360,8 @@ var newCmd = &cobra.Command{
Fatal("No message was provided.\n") Fatal("No message was provided.\n")
} }
conversation := Conversation{} conversation := &Conversation{}
err := store.SaveConversation(&conversation) err := store.SaveConversation(conversation)
if err != nil { if err != nil {
Fatal("Could not save new conversation: %v\n", err) Fatal("Could not save new conversation: %v\n", err)
} }
@ -387,18 +390,67 @@ var newCmd = &cobra.Command{
conversation.GenerateAndSaveReplies(messages) conversation.GenerateAndSaveReplies(messages)
err = conversation.GenerateTitle() title, err := conversation.GenerateTitle()
if err != nil { if err != nil {
Warn("Could not generate title for conversation: %v\n", err) Warn("Could not generate title for conversation: %v\n", err)
} }
err = store.SaveConversation(&conversation) conversation.Title = title
err = store.SaveConversation(conversation)
if err != nil { if err != nil {
Warn("Could not save conversation after generating title: %v\n", err) Warn("Could not save conversation after generating title: %v\n", err)
} }
}, },
} }
var renameCmd = &cobra.Command{
Use: "rename <conversation> [title]",
Short: "Rename a conversation",
Long: `Renames a conversation, either with the provided title or by generating a new name.`,
Args: func(cmd *cobra.Command, args []string) error {
argCount := 1
if err := cobra.MinimumNArgs(argCount)(cmd, args); err != nil {
return err
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
shortName := args[0]
conversation, err := store.ConversationByShortName(shortName)
if conversation.ID == 0 {
Fatal("Conversation not found with short name: %s\n", shortName)
}
generate, _ := cmd.Flags().GetBool("generate")
var title string
if generate {
title, err = conversation.GenerateTitle()
if err != nil {
Fatal("Could not generate title for conversation: %v\n", err)
}
} else {
if len(args) < 2 {
Fatal("Conversation title not provided.")
}
title = strings.Join(args[1:], " ")
}
conversation.Title = title
err = store.SaveConversation(conversation)
if err != nil {
Warn("Could not save conversation with new title: %v\n", err)
}
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
compMode := cobra.ShellCompDirectiveNoFileComp
if len(args) != 0 {
return nil, compMode
}
return store.ConversationShortNameCompletions(toComplete), compMode
},
}
var promptCmd = &cobra.Command{ var promptCmd = &cobra.Command{
Use: "prompt [message]", Use: "prompt [message]",
Short: "Do a one-shot prompt", Short: "Do a one-shot prompt",

View File

@ -29,7 +29,7 @@ func (m *Message) FriendlyRole() string {
return friendlyRole return friendlyRole
} }
func (c *Conversation) GenerateTitle() error { func (c *Conversation) GenerateTitle() (string, error) {
const header = "Generate a consise 4-5 word title for the conversation below." const header = "Generate a consise 4-5 word title for the conversation below."
prompt := fmt.Sprintf("%s\n\n---\n\n%s", header, c.FormatForExternalPrompting(false)) prompt := fmt.Sprintf("%s\n\n---\n\n%s", header, c.FormatForExternalPrompting(false))
@ -43,11 +43,10 @@ func (c *Conversation) GenerateTitle() error {
model := "gpt-3.5-turbo" // use cheap model to generate title model := "gpt-3.5-turbo" // use cheap model to generate title
response, err := CreateChatCompletion(model, messages, 25, nil) response, err := CreateChatCompletion(model, messages, 25, nil)
if err != nil { if err != nil {
return err return "", err
} }
c.Title = response return response, nil
return nil
} }
func (c *Conversation) FormatForExternalPrompting(system bool) string { func (c *Conversation) FormatForExternalPrompting(system bool) string {