add slash command example, better message trimming

This commit is contained in:
Kristian 2024-11-07 19:26:51 +01:00
parent d3f6deb6df
commit 2e100387da
4 changed files with 92 additions and 52 deletions

View File

@ -2,3 +2,4 @@ export BOT_TOKEN=
export CRYPTO_TOKEN= export CRYPTO_TOKEN=
export OPENAI_TOKEN= export OPENAI_TOKEN=
export ADMIN_DISCORD_ID= export ADMIN_DISCORD_ID=
export APP_ID=

View File

@ -18,6 +18,7 @@ var (
OpenAIToken string OpenAIToken string
CryptoToken string CryptoToken string
AllowedUserID string AllowedUserID string
AppId string
) )
func Run() { func Run() {
@ -27,10 +28,15 @@ func Run() {
} }
discord.AddHandler(newMessage) discord.AddHandler(newMessage)
discord.AddHandler(commandHandler)
log.Info("Opening Discord connection...") log.Info("Opening Discord connection...")
discord.Open() err = discord.Open()
if err != nil {
log.Fatal(err)
}
defer discord.Close() defer discord.Close()
registerCommands(discord, AppId)
log.Info("BitBot is running...") log.Info("BitBot is running...")
// Try initializing PocketBase after Discord is connected // Try initializing PocketBase after Discord is connected
@ -258,3 +264,33 @@ func handleRollCommand(session *discordgo.Session, message *discordgo.MessageCre
} }
} }
} }
func registerCommands(discord *discordgo.Session, appID string) {
cmd := &discordgo.ApplicationCommand{
Name: "ping",
Description: "Check the bot's ping.",
}
_, err := discord.ApplicationCommandCreate(appID, "", cmd)
if err != nil {
log.Fatalf("Cannot create slash command: %v", err)
}
}
func commandHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
if i.Type == discordgo.InteractionApplicationCommand {
data := i.ApplicationCommandData()
if data.Name == "ping" {
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: "Pong!",
},
})
if err != nil {
log.Printf("Error responding to interaction: %v", err)
}
}
}
}

View File

@ -12,7 +12,7 @@ import (
) )
const ( const (
maxTokens = 2000 maxTokens = 1500
maxContextTokens = 2000 maxContextTokens = 2000
maxMessageTokens = 2000 maxMessageTokens = 2000
systemMessageText = "your name is !bit you are a discord bot, you use brief answers untill asked to elaborate or explain" systemMessageText = "your name is !bit you are a discord bot, you use brief answers untill asked to elaborate or explain"
@ -26,75 +26,73 @@ func populateConversationHistory(session *discordgo.Session, channelID string, c
return conversationHistory return conversationHistory
} }
// Define max tokens for the conversation history // Set max tokens and initialize counters
maxTokens := 2000 maxTokens := 1500
totalTokens := 0 totalTokens := 0
// Calculate current token count in conversation history // Calculate the token count for existing messages in history
for _, msg := range conversationHistory { for _, msg := range conversationHistory {
content, okContent := msg["Content"].(string) content, okContent := msg["content"].(string)
role, okRole := msg["Role"].(string) if okContent {
if okContent && okRole { tokens := len(content) + 2 // Account for message tokens
tokens := len(content) + len(role) + 2 // Account for tokens in content and role
totalTokens += tokens totalTokens += tokens
log.Infof("Existing message tokens: %d", tokens)
} }
} }
// Process messages in reverse order (newest to oldest) // Add the latest message first
for i := len(messages) - 1; i >= 0; i-- { if len(messages) > 0 {
message := messages[i] latestMessage := messages[0]
latestTokens := len(latestMessage.Content) + 2
// Check if the message is older than 30 minutes
if time.Since(message.Timestamp) < 30*time.Minute {
tokens := len(message.Content) + 2
if totalTokens+tokens <= maxTokens {
// Append as map[string]interface{} instead of map[string]string
conversationHistory = append(conversationHistory, map[string]interface{}{
"role": "user",
"content": message.Content,
})
totalTokens += tokens
log.Infof("Adding message with tokens: %d", tokens)
} else {
log.Warnf("Skipping message with tokens: %d", tokens)
}
} else {
log.Infof("Skipping message, older than 30 minutes: %s", message.Content)
}
// Ensure the current message is included (regardless of token limit)
conversationHistory = append(conversationHistory, map[string]interface{}{ conversationHistory = append(conversationHistory, map[string]interface{}{
"role": "user", "role": "user",
"content": message.Content, "content": latestMessage.Content,
}) })
totalTokens += len(message.Content) + 2 totalTokens += latestTokens
log.Infof("Adding message with tokens: %d", totalTokens) log.Infof("Added latest message with tokens: %d", latestTokens)
}
// Now check if the token limit is exceeded and trim older messages // Process the remaining messages in reverse (newest to oldest) and add if under limit
if totalTokens > maxTokens && len(conversationHistory) > 1 { for i := 1; i < len(messages); i++ {
// Remove the oldest message from the history message := messages[i]
conversationHistory = conversationHistory[1:] if time.Since(message.Timestamp) > 30*time.Minute {
content, okContent := conversationHistory[0]["Content"].(string) continue // Skip messages older than 30 minutes
role, okRole := conversationHistory[0]["Role"].(string) }
if okContent && okRole {
tokens := len(content) + len(role) + 2 tokens := len(message.Content) + 2
totalTokens -= tokens if totalTokens+tokens <= maxTokens {
log.Infof("Trimming message with tokens: %d", tokens) conversationHistory = append([]map[string]interface{}{{
} "role": "user",
log.Info("Trimming oldest message to maintain token limit") "content": message.Content,
}}, conversationHistory...)
totalTokens += tokens
log.Infof("Adding message with tokens: %d", tokens)
} else {
break // Stop if adding the next message would exceed the max token limit
} }
} }
log.Info("Final Conversation History Order: %s", conversationHistory) // Trim older messages if needed
for totalTokens > maxTokens && len(conversationHistory) > 1 {
firstMessage := conversationHistory[0]
content, ok := firstMessage["content"].(string)
if ok {
totalTokens -= len(content) + 2
}
conversationHistory = conversationHistory[1:]
log.Infof("Trimming oldest message to maintain token limit, remaining tokens: %d", totalTokens)
}
log.Infof("Final Conversation History Order (Total Tokens: %d): %v", totalTokens, conversationHistory)
return conversationHistory return conversationHistory
} }
// Function to handle Groq API requests and pagination // Function to handle Groq API requests and pagination
func chatGPT(session *discordgo.Session, channelID string, conversationHistory []map[string]interface{}) { func chatGPT(session *discordgo.Session, channelID string, conversationHistory []map[string]interface{}) {
OpenAIToken := OpenAIToken OpenAIToken := OpenAIToken
GroqBaseURL := "https://api.groq.com/openai/v1" GroqBaseURL := "https://api.groq.com/openai/v1"
GroqModel := "llama-3.1-70b-versatile" GroqModel := "llama-3.2-90b-text-preview"
// Add system message at the start of conversation history // Add system message at the start of conversation history
conversationHistory = append([]map[string]interface{}{ conversationHistory = append([]map[string]interface{}{

View File

@ -24,6 +24,10 @@ func main() {
if !ok { if !ok {
log.Fatal("Must set crypto token as env variable: CRYPTO_TOKEN") log.Fatal("Must set crypto token as env variable: CRYPTO_TOKEN")
} }
appId, ok := os.LookupEnv("APP_ID")
if !ok {
log.Fatal("Must set appId as env variable: APP_ID")
}
openAIToken, ok := os.LookupEnv("OPENAI_TOKEN") openAIToken, ok := os.LookupEnv("OPENAI_TOKEN")
if !ok { if !ok {
log.Fatal("Must set OpenAI token as env variable: OPENAI_TOKEN") log.Fatal("Must set OpenAI token as env variable: OPENAI_TOKEN")
@ -35,6 +39,7 @@ func main() {
bot.BotToken = botToken bot.BotToken = botToken
bot.CryptoToken = cryptoToken bot.CryptoToken = cryptoToken
bot.AppId = appId
bot.OpenAIToken = openAIToken bot.OpenAIToken = openAIToken
bot.AllowedUserID = AllowedUserID bot.AllowedUserID = AllowedUserID