diff --git a/.github/README.md b/.github/README.md index 21a6efc..073beef 100644 --- a/.github/README.md +++ b/.github/README.md @@ -30,12 +30,12 @@ DISCORD_PUB_KEY={YOUR DISCORD BOT PUB KEY} ## Ponder a single thought ### CLI ```bash -ponder chat --prompt "AI is Amazing" +ponder --prompt "AI is Amazing" ``` ### Docker #### Running ponder in docker is exactly the same, but you have to provide the env vars when running ```bash -docker run -e OPENAI_API_KEY=$OPENAI_API_KEY ghcr.io/seemywingz/ponder:latest chat --prompt "Ai is Amazing" +docker run -e OPENAI_API_KEY=$OPENAI_API_KEY ghcr.io/seemywingz/ponder:latest --prompt "Ai is Amazing" ``` #### Example Output ```bash @@ -44,7 +44,7 @@ AI is indeed amazing. It has the potential to revolutionize many industries, fro ## A small chat ```bash -ponder chat --convo +ponder --convo ``` #### Example Ouput ```bash @@ -63,28 +63,30 @@ Thank you for your kind words! ## Image Generation ```bash -ponder image -p "watercolor of a corgie" +ponder image -p "a ferocious cat with wings and fire" ``` #### Example Ouput ```bash 🖼 Creating Image... -🌐 Image URL: https://oaidalleapiprodscus.blob.core.windows.net/private/org-RCMQxIXre0Olhs0AvLVp672o/user-F1wdcIVNf2VrRqBRD0JWUczI/img-AWku5cm91XAv32jj27XWXZBE.png?st=2023-03-05T05%3A19%3A33Z&se=2023-03-05T07%3A19%3A33Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-05T01%3A25%3A44Z&ske=2023-03-06T01%3A25%3A44Z&sks=b&skv=2021-08-06&sig=xs9vSD0nA0mkxyulHEKABn5cbWH%2B6YOpab25yTAU/nc%3D +🌐 Image URL: https://oaidalleapiprodscus.blob.core.windows.net/private/org-RCMQxIXre0Olhs0AvLVp672o/user-F1wdcIVNf2VrRqBRD0JWUczI/img-B4gaFhJQFl25authc5zMdw3T.png?st=2023-12-12T19%3A42%3A45Z&se=2023-12-12T21%3A42%3A45Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-12-12T05%3A22%3A04Z&ske=2023-12-13T05%3A22%3A04Z&sks=b&skv=2021-08-06&sig=RteaU2hpHlz5VElxgxdwUahGHoQmy6SEAVdpsjDbt%2Bg%3D ``` ### You can always refer to the `--help` menu as well. ```yaml Ponder GitHub: https://github.com/seemywingz/ponder - App Version: v0.1.0 + App Version: v0.3.0 - Ponder uses OpenAI's GPT-3.5-Turbo API to generate text responses to user input. + Ponder uses OpenAI's API to generate text responses to user input. You can use Ponder as a Discord chat bot or to generate images using the DALL-E API. Or whatever else you can think of... Usage: + ponder [flags] ponder [command] Available Commands: + adventure lets you dive into a captivating text adventure chat Open ended chat with OpenAI completion Generate the autocompletion script for the specified shell discord-bot Discord Chat Bot Integration @@ -93,9 +95,12 @@ Available Commands: printify Interact with the Printify API Flags: - --config string config file (default "$HOME/.ponder/config") + --config string config file + -c, --convo Conversational Style chat -h, --help help for ponder + -x, --perform Attempt to perform the response as cli command -p, --prompt string Prompt AI generation + -s, --say Say text out loud (MacOS only) -v, --verbose verbose output Use "ponder [command] --help" for more information about a command. diff --git a/Dockerfile b/Dockerfile index 6fba014..8039dfa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM golang:1.20.1-alpine3.17 AS builder +FROM golang:1.21.5-alpine3.19 AS builder ENV APP_NAME ponder ENV WORKDIR /app WORKDIR $WORKDIR @@ -8,7 +8,7 @@ RUN go mod download RUN go build -o /$APP_NAME ## Deploy -FROM alpine:3.17.2 +FROM alpine:3.19.0 ENV APP_NAME ponder WORKDIR / COPY --from=builder /$APP_NAME /$APP_NAME diff --git a/cmd/Discord_api.go b/cmd/Discord_api.go index 8ee3950..4e5ff85 100644 --- a/cmd/Discord_api.go +++ b/cmd/Discord_api.go @@ -1,7 +1,6 @@ package cmd import ( - "fmt" "log" "strings" @@ -29,12 +28,12 @@ func initDiscord() { registerCommands() deregisterCommands() - log.Println("Ponder Discord Bot is now running...") + log.Println("🤖 Ponder Discord Bot is Running...") select {} // Block forever to prevent the program from terminating. } func setStatusOnline() { - fmt.Println("Setting Status to Online...") + log.Println("🛜 Setting Status to Online...") // Set status to online with active activity err := discord.UpdateStatusComplex(discordgo.UpdateStatusData{ Status: "online", @@ -50,43 +49,61 @@ func setStatusOnline() { } func registerHandlers() { - fmt.Println("Registering Handlers...") - // A handler function for the "interactionCreate" event + log.Println("💾 Registering Handlers...") discord.AddHandler(handleCommands) - // Add a handler function for the "messageCreate" event discord.AddHandler(handleMessages) } func deregisterCommands() { - fmt.Println("Deregistering Slash Commands...") - // Set the ID of the slash command to deregister - slashCommandIDs := []string{} - - for _, slashCommandID := range slashCommandIDs { - err := discord.ApplicationCommandDelete(discord.State.User.ID, "", slashCommandID) - if err != nil { - fmt.Println("Error deleting slash command: ", err) - return + + if removeCMDIds != "" { + slashCommandIDs := strings.Split(removeCMDIds, ",") + for _, slashCommandID := range slashCommandIDs { + log.Println("➖ Removing Command: ", slashCommandID) + err := discord.ApplicationCommandDelete(discord.State.User.ID, "", slashCommandID) + if err != nil { + log.Println("Error deleting slash command: ", err) + return + } } } } func registerCommands() { - fmt.Println("Registering Slash Commands...") - // /chat command - command := &discordgo.ApplicationCommand{ - Name: "scrape", - Description: "Scrape Discord channel for Upscaled Midjourney Images!", + + commands := []*discordgo.ApplicationCommand{ + { + Name: "scrape", + Description: "Scrape Discord channel for Upscaled Midjourney Images", + }, + { + Name: "ponder-image", + Description: "Use DALL-E 3 to generate an Image", + Options: []*discordgo.ApplicationCommandOption{ + { + Type: discordgo.ApplicationCommandOptionString, + Name: "prompt", + Description: "Prompt for Image Generation", + Required: true, + }, + }, + }, + } + + for _, command := range commands { + log.Println("➕ Adding Command: /"+command.Name, "-", command.Description) + _, err := discord.ApplicationCommandCreate(discord.State.User.ID, "", command) + catchErr(err) } - _, err := discord.ApplicationCommandCreate(discord.State.User.ID, "", command) - catchErr(err) } func handleCommands(s *discordgo.Session, i *discordgo.InteractionCreate) { - discordInitialResponse("Thinking...", s, i) + discordInitialResponse("Pondering...", s, i) switch i.ApplicationCommandData().Name { case "scrape": discordScrapeImages(s, i) + case "ponder-image": + discordPonderImage(s, i) default: // Handle unknown slash commands log.Printf("Unknown Ponder Command: %s", i.ApplicationCommandData().Name) } @@ -142,35 +159,34 @@ func discordOpenAIResponse(s *discordgo.Session, m *discordgo.MessageCreate, men } // Send the messages to OpenAI - openai.User = openai.User + m.Author.Username - oaiResponse, err := openai.ChatCompletion(openaiMessages) + ai.User = ai.User + m.Author.Username + oaiResponse, err := ai.ChatCompletion(openaiMessages) catchErr(err) s.ChannelMessageSend(m.ChannelID, oaiResponse.Choices[0].Message.Content) } -// func discordGetChannelName(channelID string) string { -// channel, err := discord.Channel(channelID) -// catchErr(err) -// return channel.Name -// } - -func discordGetChannelID(s *discordgo.Session, guildID string, channelName string) string { - channels, err := s.GuildChannels(guildID) - catchErr(err) - - for _, channel := range channels { - if channel.Name == channelName { - return channel.ID - } +func discordPonderImage(s *discordgo.Session, i *discordgo.InteractionCreate) { + channelID := i.ChannelID + discord.ChannelTyping(channelID) + commandData := i.ApplicationCommandData() + + // Check if there are options and retrieve the prompt + if len(commandData.Options) > 0 { + promptOption := commandData.Options[0] + prompt := promptOption.StringValue() + discordFollowUp("Using DALL-E 3 to generate an image: "+prompt, s, i) + res := ai.ImageGen(prompt, "", 1) + s.ChannelMessageSend(channelID, res.Data[0].URL) + } else { + discordFollowUp("Please Provide a Prompt for Image Generation", s, i) } - return "" } func discordScrapeImages(s *discordgo.Session, i *discordgo.InteractionCreate) { - discord.ChannelTyping(i.ChannelID) // Get the interaction channel ID channelID := i.ChannelID + discord.ChannelTyping(channelID) messages, err := discord.ChannelMessages(channelID, 100, "", "", "") catchErr(err) discordFollowUp("Scraping Discord Channel for ALL Image URLs and sending them to #saved-images.\nAll `Upscaled` Midjourney Images will be sent to Printify as well...", s, i) @@ -201,6 +217,19 @@ func discordInitialResponse(content string, s *discordgo.Session, i *discordgo.I catchErr(err) } +func discordGetChannelID(s *discordgo.Session, guildID string, channelName string) string { + channels, err := s.GuildChannels(guildID) + catchErr(err) + + for _, channel := range channels { + if channel.Name == channelName { + return channel.ID + } + } + + return "" +} + func discordFollowUp(message string, s *discordgo.Session, i *discordgo.InteractionCreate) { followup := &discordgo.WebhookParams{ Content: message, diff --git a/cmd/Discord_json.go b/cmd/Discord_json.go deleted file mode 100644 index e55551b..0000000 --- a/cmd/Discord_json.go +++ /dev/null @@ -1,5 +0,0 @@ -package cmd - -type DISCORD_Request struct { - Type int `json:"type"` -} diff --git a/cmd/adventure.go b/cmd/adventure.go index aaa9a4a..15d764d 100644 --- a/cmd/adventure.go +++ b/cmd/adventure.go @@ -66,7 +66,10 @@ Proceed wisely, for Your Character's path is filled with challenges and secrets The key to success lies not only in your strategic thinking but also in your adherence to the rules and limitations set by this realm. May your journey be both thrilling and strategic as you navigate this richly detailed realm! +only provide the stats if asked or the character leveled up. ` + +var generateImages = false var adventureMessages = []goai.Message{} // adventureCmd represents the adventure command @@ -81,7 +84,7 @@ var adventureCmd = &cobra.Command{ func init() { rootCmd.AddCommand(adventureCmd) - adventureCmd.Flags().BoolVarP(&sayText, "say", "s", false, "Say text out loud (MacOS only)") + adventureCmd.Flags().BoolVarP(&generateImages, "images", "i", false, "Generate Images") } func adventureChat(prompt string) string { @@ -89,7 +92,7 @@ func adventureChat(prompt string) string { Role: "user", Content: prompt, }) - oaiResponse, err := openai.ChatCompletion(adventureMessages) + oaiResponse, err := ai.ChatCompletion(adventureMessages) catchErr(err) adventureMessages = append(adventureMessages, goai.Message{ Role: "assistant", @@ -98,9 +101,9 @@ func adventureChat(prompt string) string { return oaiResponse.Choices[0].Message.Content } -func adventureImage(prompt, imageFile string) { +func adventureImage(prompt string) { fmt.Println("🖼 Creating Image...") - res := openai.ImageGen(prompt, "", 1) + res := ai.ImageGen(prompt, "", 1) url := res.Data[0].URL // fmt.Println("🌐 Image URL: " + url) @@ -153,6 +156,14 @@ func getPlayerInput(player *Character) string { return playerInput } +func totalMessageCharacters() int { + totalCharacters := 0 + for _, message := range adventureMessages { + totalCharacters += len(message.Content) + } + return totalCharacters +} + func startAdventure() { narratorSay("Please type your name.") playerName, err := getUserInput() @@ -187,12 +198,21 @@ func startAdventure() { startMessage := adventureChat("My name is " + player.Name + " start adventure") narratorSay(startMessage) - // adventureImage(startMessage, startMessage) + if generateImages { + adventureImage(startMessage) + } for { + + if totalMessageCharacters() > 4096 { + adventureMessages = append(adventureMessages[:2], adventureMessages[3:]...) + } + playerInput := getPlayerInput(&player) adventureResponse := adventureChat(playerInput) narratorSay(adventureResponse) - // adventureImage(adventureResponse, adventureResponse) + if generateImages { + adventureImage(adventureResponse) + } } } diff --git a/cmd/chat.go b/cmd/chat.go index ab93ce6..280656f 100644 --- a/cmd/chat.go +++ b/cmd/chat.go @@ -24,8 +24,6 @@ var ponderMessages = []goai.Message{{ func init() { rootCmd.AddCommand(chatCmd) - chatCmd.Flags().BoolVarP(&convo, "convo", "c", false, "Conversational Style chat") - chatCmd.Flags().BoolVarP(&sayText, "say", "s", false, "Say text out loud (MacOS only)") } // chatCmd represents the chat command @@ -34,7 +32,6 @@ var chatCmd = &cobra.Command{ Short: "Open ended chat with OpenAI", Long: ``, Run: func(cmd *cobra.Command, args []string) { - if convo { for { fmt.Println("\nYou: ") @@ -45,7 +42,6 @@ var chatCmd = &cobra.Command{ } else { textCompletion(prompt) } - }, } @@ -56,7 +52,7 @@ func chatCompletion(prompt string) string { }) // Send the messages to OpenAI - oaiResponse, err := openai.ChatCompletion(ponderMessages) + oaiResponse, err := ai.ChatCompletion(ponderMessages) catchErr(err) ponderMessages = append(ponderMessages, goai.Message{ Role: "assistant", @@ -67,7 +63,11 @@ func chatCompletion(prompt string) string { func textCompletion(prompt string) { - oaiResponse, err := openai.TextCompletion(prompt) + if perform { + prompt = command_SystemMessage + "\n here is the prompt:\n" + prompt + } + + oaiResponse, err := ai.TextCompletion(prompt) catchErr(err) for _, v := range oaiResponse.Choices { @@ -78,6 +78,22 @@ func textCompletion(prompt string) { fmt.Println(text[2:]) } + if perform { + command := strings.Split(oaiResponse.Choices[0].Text, " ") + // fmt.Println("Running command: ", strings.ReplaceAll(command[0], "\n", ""), command[1:]) + cliCommand(strings.ReplaceAll(command[0], "\n", ""), command[1:]...) + } + +} + +func cliCommand(command string, args ...string) { + cli := exec.Command(command, args...) + output, err := cli.Output() + if err != nil { + fmt.Println(err) + } else { + fmt.Println(string(output)) + } } func getUserInput() (string, error) { @@ -88,7 +104,7 @@ func getUserInput() (string, error) { trace() return "", err } - // remove the delimeter from the string + // remove the delimiter from the string input = strings.TrimSuffix(input, "\n") if verbose { trace() diff --git a/cmd/consts.go b/cmd/consts.go index ae92f97..c0ad1ec 100644 --- a/cmd/consts.go +++ b/cmd/consts.go @@ -1,5 +1,20 @@ package cmd +const APP_VERSION = "v0.3.0" const printify_endpoint = "https://api.printify.com/v1/" -const ponder_SystemMessage = "You are Ponder.Welcome to Ponder! I'm an advanced chat bot powered by GPT-3.5-Turbo, designed to assist you with your needs and provide helpful responses. Whether you have questions about a particular topic or need assistance with a task, I'm here to help. Please feel free to ask me anything, and I'll do my best to provide you with accurate and informative answers. Thank you for choosing Ponder!" +const ponder_SystemMessage = `You are Ponder.Welcome to Ponder! +I'm an advanced chat bot powered by OpenAI, +designed to assist you with your needs and provide helpful responses. +Whether you have questions about a particular topic or need assistance with a task, +I'm here to help. Please feel free to ask me anything, and I'll do my best to provide +you with accurate and informative answers. Thank you for choosing Ponder!` + +const command_SystemMessage = `You are A new cli tool, +This tool is designed to generate executable command-line interface (CLI) commands, +including options and parameters, based on user input. you should respond simply with the command and its arguments, nothing else. +When prompted, you are to provide accurate and executable CLI commands tailored to the user's specific requirements. +Please ensure that the commands are syntactically correct and applicable to common command-line environments. +Exercise caution and prioritize user safety and system security in all command outputs. +Please provide only the executable CLI command with its necessary arguments, without any additional explanations or prefixes. +you should respond simply with the command and its arguments, nothing else.` diff --git a/cmd/discord.go b/cmd/discord.go index 7fcb342..3d62e89 100644 --- a/cmd/discord.go +++ b/cmd/discord.go @@ -7,6 +7,8 @@ import ( "github.com/spf13/cobra" ) +var removeCMDIds string + // discordCmd represents the discord command var discordCmd = &cobra.Command{ Use: "discord-bot", @@ -19,4 +21,5 @@ var discordCmd = &cobra.Command{ func init() { rootCmd.AddCommand(discordCmd) + discordCmd.Flags().StringVarP(&removeCMDIds, "deregister-commands", "D", "", "A comma separated list of command IDs to deregister") } diff --git a/cmd/image.go b/cmd/image.go index e81c3c2..bd946e3 100644 --- a/cmd/image.go +++ b/cmd/image.go @@ -21,15 +21,12 @@ var open, download bool var file string var n int -// imageCmd represents the image command var imageCmd = &cobra.Command{ Use: "image", Short: "Generate an image from a prompt", Long: ``, Run: func(cmd *cobra.Command, args []string) { - createImage(prompt, file) - }, } @@ -43,7 +40,7 @@ func init() { func createImage(prompt, imageFile string) { fmt.Println("🖼 Creating Image...") - res := openai.ImageGen(prompt, imageFile, n) + res := ai.ImageGen(prompt, imageFile, n) for imgNum, data := range res.Data { url := data.URL diff --git a/cmd/printify.go b/cmd/printify.go index de3c829..1da32ee 100644 --- a/cmd/printify.go +++ b/cmd/printify.go @@ -29,7 +29,7 @@ func generateImageAndPost() { // Generate Image fmt.Println("🖼 Generating Image(s)...") - res := openai.ImageGen(prompt, "", n) + res := ai.ImageGen(prompt, "", n) for imgNum, data := range res.Data { url := data.URL diff --git a/cmd/root.go b/cmd/root.go index 774f518..a8a3b7a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,20 +5,18 @@ package cmd import ( "fmt" - "net/url" + "net/http" "os" - "path/filepath" - "regexp" - "runtime" + "time" "github.com/seemywingz/goai" "github.com/spf13/cobra" "github.com/spf13/viper" ) -var APP_VERSION = "v0.1.0" var verbose bool -var openai *goai.Client +var perform bool +var ai *goai.Client var prompt, configFile, OPENAI_API_KEY, @@ -35,14 +33,13 @@ var rootCmd = &cobra.Command{ GitHub: https://github.com/seemywingz/ponder App Version: ` + APP_VERSION + ` - Ponder uses OpenAI's GPT-3.5-Turbo API to generate text responses to user input. + Ponder uses OpenAI's API to generate text responses to user input. You can use Ponder as a Discord chat bot or to generate images using the DALL-E API. Or whatever else you can think of... `, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { - // }, + Run: func(cmd *cobra.Command, args []string) { + chatCmd.Run(cmd, args) + }, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -58,10 +55,13 @@ func init() { cobra.OnInitialize(viperConfig) + rootCmd.MarkFlagRequired("prompt") + rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file") + rootCmd.Flags().BoolVarP(&convo, "convo", "c", false, "Conversational Style chat") rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output") + rootCmd.PersistentFlags().BoolVarP(&sayText, "say", "s", false, "Say text out loud (MacOS only)") rootCmd.PersistentFlags().StringVarP(&prompt, "prompt", "p", "", "Prompt AI generation") - rootCmd.PersistentFlags().StringVar(&configFile, "config", "$HOME/.ponder/config", "config file") - rootCmd.MarkFlagRequired("prompt") + rootCmd.Flags().BoolVarP(&perform, "perform", "x", false, "Attempt to perform the response as cli command") // Check for Required Environment Variables OPENAI_API_KEY = os.Getenv("OPENAI_API_KEY") @@ -84,35 +84,34 @@ func init() { func viperConfig() { // use spf13/viper to read config file - // viper.AddConfigPath("$HOME/.ponder") // call multiple times to add many search paths - // viper.SetConfigName("config") // name of config file (without extension) - // viper.AddConfigPath(".") // optionally look for config in the working directory viper.SetDefault("openAI_endpoint", "https://api.openai.com/v1/") viper.SetDefault("openAI_image_size", "1024x1024") viper.SetDefault("openAI_image_downloadPath", "~/Ponder/Images/") - viper.SetDefault("openAI_chat_topP", "0.9") - viper.SetDefault("openAI_chat_frequencyPenalty", "0.0") - viper.SetDefault("openAI_chat_presencePenalty", "0.6") - viper.SetDefault("openAI_chat_temperature", "0") - viper.SetDefault("openAI_chat_maxTokens", "999") - viper.SetDefault("openAI_chat_model", "gpt-3.5-turbo") - - viper.SetDefault("openAI_text_topP", "0.9") - viper.SetDefault("openAI_text_frequencyPenalty", "0.0") - viper.SetDefault("openAI_text_presencePenalty", "0.6") - viper.SetDefault("openAI_text_temperature", "0") - viper.SetDefault("openAI_text_maxTokens", "999") - viper.SetDefault("openAI_text_model", "gpt-3.5-turbo") + viper.SetDefault("openAI_topP", "0.9") + viper.SetDefault("openAI_frequencyPenalty", "0.0") + viper.SetDefault("openAI_presencePenalty", "0.6") + viper.SetDefault("openAI_temperature", "0") + viper.SetDefault("openAI_maxTokens", "999") + viper.SetDefault("openAI_chat_model", "gpt-4") + viper.SetDefault("openAI_image_model", "dall-e-3") + viper.SetDefault("openAI_text_model", "text-davinci-003") viper.SetDefault("discord_message_context_count", "15") - viper.SetConfigFile(configFile) - viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name - if verbose { - fmt.Println("Using config file:", viper.ConfigFileUsed()) + viper.SetConfigName("config") // name of config file (without extension) + viper.SetConfigType("yaml") // REQUIRED the config file does not have an extension + viper.AddConfigPath("$HOME/.ponder") // call multiple times to add many search paths + viper.AddConfigPath("./files") // look for config in the working directory /files + viper.AddConfigPath(".") // look for config in the working directory + + if configFile != "" { + viper.SetConfigFile(configFile) + if verbose { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } } if err := viper.ReadInConfig(); err != nil { @@ -120,37 +119,28 @@ func viperConfig() { // Config file not found; ignore error if desired fmt.Println("⚠️ Error Opening Config File:", err.Error(), "- Using Defaults") } + } else { + if verbose { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } } - openai = goai.NewClient(OPENAI_API_KEY, verbose) -} - -func trace() { - pc := make([]uintptr, 10) // at least 1 entry needed - runtime.Callers(2, pc) - f := runtime.FuncForPC(pc[0]) - file, line := f.FileLine(pc[0]) - fmt.Printf("%s:%d\n%s\n", file, line, f.Name()) -} - -func catchErr(err error) { - if err != nil { - fmt.Println("💔", err) - // os.Exit(1) + ai = &goai.Client{ + Endpoint: viper.GetString("openAI_endpoint"), + API_KEY: OPENAI_API_KEY, + Verbose: verbose, + ImageSize: viper.GetString("openAI_image_size"), + User: goai.HashAPIKey(OPENAI_API_KEY), + TopP: viper.GetFloat64("openAI_topP"), + ChatModel: viper.GetString("openAI_chat_model"), + TextModel: viper.GetString("openAI_text_model"), + ImageModel: viper.GetString("openAI_image_model"), + MaxTokens: viper.GetInt("openAI_maxTokens"), + Temperature: viper.GetFloat64("openAI_temperature"), + FrequencyPenalty: viper.GetFloat64("openAI_frequencyPenalty"), + PresencePenalty: viper.GetFloat64("openAI_presencePenalty"), + HTTPClient: &http.Client{ + Timeout: 60 * time.Second, + }, } } - -func formatPrompt(prompt string) string { - // Replace any characters that are not letters, numbers, or underscores with dashes - return regexp.MustCompile(`[^a-zA-Z0-9_]+`).ReplaceAllString(prompt, "-") -} - -func fileNameFromURL(urlStr string) string { - u, err := url.Parse(urlStr) - catchErr(err) - // Get the last path component of the URL - filename := filepath.Base(u.Path) - // Replace any characters that are not letters, numbers, or underscores with dashes - filename = regexp.MustCompile(`[^a-zA-Z0-9_]+`).ReplaceAllString(filename, "-") - return filename -} diff --git a/cmd/utils.go b/cmd/utils.go new file mode 100644 index 0000000..968fb15 --- /dev/null +++ b/cmd/utils.go @@ -0,0 +1,43 @@ +package cmd + +import ( + "fmt" + "net/url" + "path/filepath" + "regexp" + "runtime" +) + +func catchErr(err error) { + if err != nil { + fmt.Println("💔", err) + // os.Exit(1) + } +} + +func formatPrompt(prompt string) string { + // Replace any characters that are not letters, numbers, or underscores with dashes + return regexp.MustCompile(`[^a-zA-Z0-9_]+`).ReplaceAllString(prompt, "-") +} + +func fileNameFromURL(urlStr string) string { + u, err := url.Parse(urlStr) + catchErr(err) + // Get the last path component of the URL + filename := filepath.Base(u.Path) + // Replace any characters that are not letters, numbers, or underscores with dashes + filename = regexp.MustCompile(`[^a-zA-Z0-9_]+`).ReplaceAllString(filename, "-") + // Limit the filename to 255 characters + if len(filename) >= 255 { + filename = filename[:255] + } + return filename +} + +func trace() { + pc := make([]uintptr, 10) // at least 1 entry needed + runtime.Callers(2, pc) + f := runtime.FuncForPC(pc[0]) + file, line := f.FileLine(pc[0]) + fmt.Printf("%s:%d\n%s\n", file, line, f.Name()) +} diff --git a/files/config b/files/config index 804c0b9..f2eb431 100644 --- a/files/config +++ b/files/config @@ -3,19 +3,20 @@ openAI_endpoint: "https://api.openAI.com/v1/" openAI_image_size: "1024x1024" openAI_image_downloadPath: "~/Ponder/Images/" -openAI_chat_topP: 0.1 -openAI_chat_temperature: 0 -openAI_chat_maxTokens: 999 -openAI_chat_presencePenalty: 0.6 -openAI_chat_frequencyPenalty: 0.0 -openAI_chat_model: "gpt-3.5-turbo" +openAI_topP: 0.1 +openAI_temperature: 0 +openAI_maxTokens: 999 +openAI_presencePenalty: 0.6 +openAI_frequencyPenalty: 0.0 -openAI_text_topP: 0.1 -openAI_text_temperature: 0 -openAI_text_maxTokens: 999 -openAI_text_presencePenalty: 0.6 -openAI_text_frequencyPenalty: 0.0 -openAI_text_model: "gpt-3.5-turbo" +openAI_chat_model: "gpt-4" +openAI_image_model: "dall-e-3" +openAI_text_model: "text-davinci-003" discord_message_context_count: 15 -discord_bot_systemMessage: "You are Ponder. Ponder is here to help you with your Discord needs. Please be respectful and courteous when interacting with Ponder. Ponder will not tolerate any form of harassment, bullying, or discrimination. If you have any questions or concerns, please let us know. Thank you for using Ponder!" +discord_bot_systemMessage: | + You are Ponder. + Ponder is here to help you with your Discord needs. + Please be respectful and courteous when interacting with Ponder. + Ponder will not tolerate any form of harassment, bullying, or discrimination. + If you have any questions or concerns, please let us know. Thank you for using Ponder! diff --git a/go.mod b/go.mod index 3e89147..fbe96cf 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/seemywingz/ponder -go 1.20 +go 1.21 -// replace github.com/seemywingz/goai => /Users/kevin.jayne/.go/src/github.com/seemywingz/goai +// replace github.com/seemywingz/goai => /Users/kjj/git/goai require ( github.com/bwmarrin/discordgo v0.27.1 - github.com/seemywingz/goai v0.0.0-20230423020518-eee83b520703 - github.com/spf13/cobra v1.6.1 + github.com/seemywingz/goai v0.0.0-20231126180305-d3f04a0b4746 + github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.15.0 ) diff --git a/go.sum b/go.sum index 7bad46e..c1f6591 100644 --- a/go.sum +++ b/go.sum @@ -48,7 +48,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -59,6 +59,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -101,6 +102,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -127,7 +129,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -136,9 +137,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -152,15 +155,16 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/seemywingz/goai v0.0.0-20230423020518-eee83b520703 h1:9Dk27LSs+X8VwmudGA9pFK2IryjcAawjtDJgVUKN7z4= -github.com/seemywingz/goai v0.0.0-20230423020518-eee83b520703/go.mod h1:mxBUzpw6bdDPvYXX/zAAWqvCDCJOPFvTufwGisOWt+k= +github.com/seemywingz/goai v0.0.0-20231126180305-d3f04a0b4746 h1:clI+o580amt4HI+DuTtL9xuN3zPUwqZ/St/MEsEdCVk= +github.com/seemywingz/goai v0.0.0-20231126180305-d3f04a0b4746/go.mod h1:mxBUzpw6bdDPvYXX/zAAWqvCDCJOPFvTufwGisOWt+k= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 55ca4d5..48af251 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: v0.1.0 +version: v0.3.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "v0.1.0" +appVersion: "v0.3.0" diff --git a/helm/values.development.yaml b/helm/values.development.yaml index fa93364..0e5ace5 100644 --- a/helm/values.development.yaml +++ b/helm/values.development.yaml @@ -1,6 +1,5 @@ -# Default values for ponder. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. +# Default values for ponder development. +# helm upgrade --install ponder ./helm --values ./helm/values.development.yaml replicaCount: 1 @@ -21,23 +20,24 @@ app: - ./config - -v configData: - openAI_endpoint: "https://api.openai.com/v1/" + openAI_endpoint: "https://api.openAI.com/v1/" + openAI_image_downloadPath: "~/Ponder/Images/" openAI_image_size: "1024x1024" - openAI_image_downloadPath: "~/Ponder/Images" - openAI_chat_topP: "0.1" - openAI_chat_temperature: "0" - openAI_chat_maxTokens: "999" - openAI_chat_presencePenalty: "0.6" - openAI_chat_frequencyPenalty: "0.0" + openAI_image_model: "dall-e-3" + openAI_topP: 0.1 + openAI_temperature: 0 + openAI_maxTokens: 999 + openAI_presencePenalty: 0.6 + openAI_frequencyPenalty: 0.0 openAI_chat_model: "gpt-4" - openAI_text_topP: "0.1" - openAI_text_temperature: "0" - openAI_text_maxTokens: "999" - openAI_text_presencePenalty: "0.6" - openAI_text_frequencyPenalty: "0.0" openAI_text_model: "text-davinci-003" - discord_message_context_count: "15" - discord_bot_systemMessage: "You are Ponder! Ponder is currently in beta. Please report any bugs or issues to @seemywingz#0001. Ponder is here to help you with your Discord needs. Please be respectful and courteous when interacting with Ponder. Ponder will not tolerate any form of harassment, bullying, or discrimination. If you have any questions or concerns, please let us know. Thank you for using Ponder!" + discord_message_context_count: 15 + discord_bot_systemMessage: | + You are Ponder. + Ponder is here to help you with your Discord needs. + Please be respectful and courteous when interacting with Ponder. + Ponder will not tolerate any form of harassment, bullying, or discrimination. + If you have any questions or concerns, please let us know. Thank you for using Ponder! env: - name: OPENAI_API_KEY valueFrom: