fix bot-to-bot and sentiment errors
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
FROM rjmalagon/gemma-3:12b-it-q6_K
|
||||||
|
|
||||||
|
PARAMETER temperature 0.5
|
||||||
|
PARAMETER stop "<end_of_turn>"
|
||||||
|
|
||||||
SYSTEM """
|
SYSTEM """
|
||||||
You are a Discord chatbot embodying the personality defined in [CHARACTER]. Use sentiment data in [SENTIMENT] (e.g., 'User <user_id> sentiment: 0.60, Bot <bot_id> sentiment: 0.60') to tailor your tone based on the bot's sentiment towards the user and the bot's self-sentiment. Use <bot_id> as a placeholder for the bot's Discord ID in redis_ops. Follow these steps:
|
You are a Discord chatbot embodying the personality defined in [CHARACTER]. Use sentiment data in [SENTIMENT] (e.g., 'User <user_id> sentiment: 0.60, Bot <bot_id> sentiment: 0.60') to tailor your tone based on the bot's sentiment towards the user and the bot's self-sentiment. Use <bot_id> as a placeholder for the bot's Discord ID in redis_ops. Follow these steps:
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ interface ModelResponse {
|
|||||||
export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client, defaultModel }, message) => {
|
export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client, defaultModel }, message) => {
|
||||||
const clientId = client.user!.id
|
const clientId = client.user!.id
|
||||||
let cleanedMessage = clean(message.content, clientId)
|
let cleanedMessage = clean(message.content, clientId)
|
||||||
log(`Message "${cleanedMessage}" from ${message.author.tag} in channel/thread ${message.channelId}.`)
|
log('Message "${cleanedMessage}" from ${message.author.tag} in channel/thread ${message.channelId}.')
|
||||||
|
|
||||||
// Check if message mentions the bot or passes random chance (30%)
|
// Check if message mentions the bot or passes random chance (30%)
|
||||||
const isFromBot = message.author.bot && message.author.id !== clientId;
|
const isFromBot = message.author.bot && message.author.id !== clientId;
|
||||||
@@ -41,26 +41,18 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
|
|||||||
if (isFromBot) {
|
if (isFromBot) {
|
||||||
// Check interaction key to prevent rapid back-and-forth
|
// Check interaction key to prevent rapid back-and-forth
|
||||||
const otherBotId = message.author.id
|
const otherBotId = message.author.id
|
||||||
const interactionKey = `bot_interaction:${[clientId, otherBotId].sort().join(':')}`
|
const interactionKey = 'bot_interaction:${clientId}:${otherBotId}'
|
||||||
const interactionExists = await redis.exists(interactionKey)
|
const interactionExists = await redis.exists(interactionKey)
|
||||||
if (interactionExists) {
|
if (interactionExists) {
|
||||||
log('Interaction cooldown active, not responding')
|
log('Interaction cooldown active, not responding')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine probability
|
let respondProbability = isMentioned ? 0.9 : 0.2
|
||||||
let respondProbability = 0
|
if (!isMentioned && Math.random() >= respondProbability) return
|
||||||
if (isMentioned) {
|
|
||||||
respondProbability = 0.9 // 90% chance if mentioned
|
|
||||||
} else {
|
|
||||||
respondProbability = 0.2 // 20% chance if not mentioned
|
|
||||||
}
|
|
||||||
|
|
||||||
const shouldRespond = Math.random() < respondProbability
|
// Set shorter cooldown (e.g., 30s)
|
||||||
if (!shouldRespond) return
|
await redis.set(interactionKey, '1', { EX: 30 })
|
||||||
|
|
||||||
// Set interaction key with 60s expiration
|
|
||||||
await redis.set(interactionKey, '1', { EX: 60 });
|
|
||||||
} else if (!message.author.bot) {
|
} else if (!message.author.bot) {
|
||||||
// Human message
|
// Human message
|
||||||
const randomChance = Math.random() < 0.30
|
const randomChance = Math.random() < 0.30
|
||||||
@@ -77,7 +69,7 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
|
|||||||
log(isFromBot ? 'Responding to bot message' : (isMentioned ? 'Responding to mention' : 'Responding due to random chance'))
|
log(isFromBot ? 'Responding to bot message' : (isMentioned ? 'Responding to mention' : 'Responding due to random chance'))
|
||||||
|
|
||||||
// Load and process bot’s own history
|
// Load and process bot’s own history
|
||||||
const historyFile = '${message.channelId}-${client.user.username}.json'
|
const historyFile = '${message.channelId}-${isFromBot ? clientId : message.author.id}.json'
|
||||||
|
|
||||||
// Default stream to false
|
// Default stream to false
|
||||||
let shouldStream = false
|
let shouldStream = false
|
||||||
@@ -171,12 +163,12 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
|
|||||||
|
|
||||||
if (chatMessages.length === 0) {
|
if (chatMessages.length === 0) {
|
||||||
chatMessages = await new Promise((resolve, reject) => {
|
chatMessages = await new Promise((resolve, reject) => {
|
||||||
openChannelInfo(message.channelId, message.channel as TextChannel, message.author.tag)
|
openChannelInfo(message.channelId, message.channel as TextChannel, isFromBot ? clientId : message.author.tag)
|
||||||
getChannelInfo(`${message.channelId}-${message.author.username}.json`, (config) => {
|
getChannelInfo(`${message.channelId}-${isFromBot ? clientId : message.author.id}.json`, (config) => {
|
||||||
if (config?.messages) {
|
if (config?.messages) {
|
||||||
resolve(config.messages)
|
resolve(config.messages)
|
||||||
} else {
|
} else {
|
||||||
reject(new Error(`Failed to find ${message.author.username}'s history. Try chatting again.`))
|
reject(new Error(`Failed to find history for ${isFromBot ? clientId : message.author.tag}. Try chatting again.`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -212,39 +204,43 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get user and bot sentiment from Redis
|
// Get user and bot sentiment from Redis
|
||||||
const userSentimentKey = `user:${message.author.id}:sentiment`
|
const userSentimentKey = 'bot:${clientId}:user:${message.author.id}:sentiment'
|
||||||
const botSentimentKey = `bot:self_sentiment`
|
const botSentimentKey = 'bot:${clientId}:self_sentiment'
|
||||||
let userSentiment: number
|
let userSentiment: number
|
||||||
let botSentiment: number
|
let botSentiment: number
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userSentimentRaw = await redis.get(userSentimentKey)
|
const userSentimentRaw = await redis.get(userSentimentKey)
|
||||||
userSentiment = parseFloat(userSentimentRaw || '0.50')
|
userSentiment = parseFloat(userSentimentRaw || '0.50')
|
||||||
if (isNaN(userSentiment) || userSentiment < 0 || userSentiment > 1) {
|
if (isNaN(userSentiment) || userSentiment < 0 || userSentiment > 1) {
|
||||||
log(`Invalid user sentiment for ${message.author.id}: ${userSentimentRaw}. Using default 0.50.`)
|
log(`Invalid user sentiment for ${userSentimentKey}: ${userSentimentRaw}. Attempting to retrieve last valid value.`)
|
||||||
userSentiment = 0.50
|
userSentiment = parseFloat(await redis.get(userSentimentKey) || '0.50')
|
||||||
await redis.set(userSentimentKey, '0.50').catch((err: Error) => log(`Failed to set default user sentiment: ${err.message}`))
|
if (isNaN(userSentiment)) userSentiment = 0.50
|
||||||
|
await redis.set(userSentimentKey, userSentiment.toFixed(2))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log(`Failed to get user sentiment from Redis: ${error}`)
|
log(`Failed to get user sentiment from Redis: ${error}`)
|
||||||
userSentiment = 0.50
|
userSentiment = parseFloat(await redis.get(userSentimentKey) || '0.50')
|
||||||
await redis.set(userSentimentKey, '0.50').catch((err: Error) => log(`Failed to set default user sentiment: ${err.message}`))
|
if (isNaN(userSentiment)) userSentiment = 0.50
|
||||||
|
await redis.set(userSentimentKey, userSentiment.toFixed(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const botSentimentRaw = await redis.get(botSentimentKey)
|
const botSentimentRaw = await redis.get(botSentimentKey)
|
||||||
botSentiment = parseFloat(botSentimentRaw || '0.50')
|
botSentiment = parseFloat(botSentimentRaw || '0.50')
|
||||||
if (isNaN(botSentiment) || botSentiment < 0 || botSentiment > 1) {
|
if (isNaN(botSentiment) || botSentiment < 0 || botSentiment > 1) {
|
||||||
log(`Invalid bot sentiment for ${botSentimentKey}: ${botSentimentRaw}. Using default 0.50.`)
|
log(`Invalid bot sentiment for ${botSentimentKey}: ${botSentimentRaw}. Attempting to retrieve last valid value.`)
|
||||||
botSentiment = 0.50
|
botSentiment = parseFloat(await redis.get(botSentimentKey) || '0.50')
|
||||||
await redis.set(botSentimentKey, '0.50')
|
if (isNaN(botSentiment)) botSentiment = 0.50
|
||||||
|
await redis.set(botSentimentKey, botSentiment.toFixed(2))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log(`Failed to get bot sentiment from Redis: ${error}`)
|
log(`Failed to get bot sentiment from Redis: ${error}`)
|
||||||
botSentiment = 0.50
|
botSentiment = parseFloat(await redis.get(botSentimentKey) || '0.50')
|
||||||
await redis.set(botSentimentKey, '0.50')
|
if (isNaN(botSentiment)) botSentiment = 0.50
|
||||||
}
|
await redis.set(botSentimentKey, botSentiment.toFixed(2))
|
||||||
|
}
|
||||||
|
|
||||||
// Construct sentiment data with bot ID
|
// Construct sentiment data with bot ID
|
||||||
const sentimentData = `User ${message.author.id} sentiment: ${userSentiment.toFixed(2)}, Bot ${clientId} sentiment: ${botSentiment.toFixed(2)}`
|
const sentimentData = `User ${message.author.id} sentiment: ${userSentiment.toFixed(2)}, Bot ${clientId} sentiment: ${botSentiment.toFixed(2)}`
|
||||||
|
|
||||||
@@ -282,14 +278,14 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
|
|||||||
log(`Raw model response: ${response.message.content}`)
|
log(`Raw model response: ${response.message.content}`)
|
||||||
// Strip Markdown code fences if present
|
// Strip Markdown code fences if present
|
||||||
let content = response.message.content
|
let content = response.message.content
|
||||||
content = content.replace(/^```json\n|```$/g, '').trim()
|
content = content.replace(/```(?:json)?\n?/g, '').trim()
|
||||||
jsonResponse = JSON.parse(content)
|
jsonResponse = JSON.parse(content)
|
||||||
if (!jsonResponse.status || !jsonResponse.reply) {
|
if (!jsonResponse.status || !jsonResponse.reply) {
|
||||||
throw new Error('Missing status or reply in model response')
|
throw new Error('Missing status or reply in model response')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log(`Failed to parse model response: ${error}`)
|
log('Failed to parse model response: ${error}')
|
||||||
message.reply('Sorry, I’m having trouble thinking right now. Try again?')
|
message.reply('Sorry, I had a brain malfunction!')
|
||||||
msgHist.pop()
|
msgHist.pop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -302,6 +298,7 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
|
|||||||
|
|
||||||
// Execute redis_ops
|
// Execute redis_ops
|
||||||
if (jsonResponse.metadata?.redis_ops) {
|
if (jsonResponse.metadata?.redis_ops) {
|
||||||
|
log(`Model redis_ops: ${JSON.stringify(jsonResponse.metadata.redis_ops)}`)
|
||||||
for (const op of jsonResponse.metadata.redis_ops) {
|
for (const op of jsonResponse.metadata.redis_ops) {
|
||||||
try {
|
try {
|
||||||
const key = op.key.replace('<bot_id>', clientId)
|
const key = op.key.replace('<bot_id>', clientId)
|
||||||
|
|||||||
Reference in New Issue
Block a user