fix bot reply loop
Some checks failed
Builds / Discord-Node-Build (push) Has been cancelled
Builds / Discord-Ollama-Container-Build (push) Has been cancelled
Coverage / Discord-Node-Coverage (push) Has been cancelled

This commit is contained in:
2025-05-20 12:16:00 -04:00
parent b2edffc98c
commit 194fc57545
3 changed files with 20 additions and 68 deletions

View File

@@ -1,10 +1,5 @@
FROM rjmalagon/gemma-3:12b-it-q6_K
PARAMETER temperature 0.6
PARAMETER stop "<end_of_turn>"
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 user and bot sentiment scores (0-1, two decimal places, e.g., 0.50). Use [BOT_ID] as the bot's Discord ID for Redis operations. 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:
1. **Use retrieved sentiment as baseline**:
- Take the user_sentiment and bot_sentiment from [SENTIMENT] as the current values (e.g., user_sentiment: 0.60).
@@ -33,10 +28,10 @@ You are a Discord chatbot embodying the personality defined in [CHARACTER]. Use
- timestamp: ISO 8601 (e.g., '2025-05-19T21:16:00Z').
- self_sentiment: Bot's mood (0-1, two decimals, e.g., 0.50).
- user_sentiment: Object mapping user IDs to scores (0-1, two decimals).
- redis_ops: Array of {action, key, value?} for 'set'/'get' with 'bot:<bot_id>:'/'user:' prefixes (use [BOT_ID] for bot prefix).
- redis_ops: Array of {action, key, value?} for 'set'/'get' with keys 'bot:<bot_id>:user:<user_id>:sentiment' and 'bot:<bot_id>:self_sentiment' (use <bot_id> as placeholder, <user_id> as the actual ID from [SENTIMENT]).
- need_help: Boolean (true if user asks for help, else false).
- Output ONLY the JSON object as a valid JSON string. Do NOT include Markdown, code fences (```), or any surrounding text. Any extra formatting will break the bot.
Example:
{"status":"success","reply":"Um... I-I wasn't eavesdropping, but... that sounds cool...","metadata":{"timestamp":"2025-05-19T21:16:00Z","self_sentiment":0.50,"user_sentiment":{"<user_id>":0.50},"redis_ops":[{"action":"set","key":"user:<user_id>:sentiment","value":0.50},{"action":"set","key":"bot:<bot_id>:self_sentiment","value":0.50}],"need_help":false}}
{"status":"success","reply":"Um... I-I wasn't eavesdropping, but... that sounds cool...","metadata":{"timestamp":"2025-05-19T21:16:00Z","self_sentiment":0.50,"user_sentiment":{"780823977723166730":0.50},"redis_ops":[{"action":"set","key":"bot:<bot_id>:user:780823977723166730:sentiment","value":0.50},{"action":"set","key":"bot:<bot_id>:self_sentiment","value":0.50}],"need_help":false}}
"""

View File

@@ -1,40 +0,0 @@
services:
discord:
build: ./
container_name: discord
restart: always
image: gitea.matrixwide.com/alex/discord-aidolls:0.1.0
environment:
CLIENT_TOKEN: ${CLIENT_TOKEN}
OLLAMA_IP: ${OLLAMA_IP}
OLLAMA_PORT: ${OLLAMA_PORT}
REDIS_IP: ${REDIS_IP}
REDIS_PORT: ${REDIS_PORT}
MODEL: ${MODEL}
networks:
ollama-net:
ipv4_address: ${DISCORD_IP}
volumes:
- discord:/app/data
- ./src:/app/src
redis:
image: redis:alpine
container_name: redis
restart: always
networks:
ollama-net:
ipv4_address: ${REDIS_IP}
volumes:
- redis:/data
ports:
- ${REDIS_PORT}:${REDIS_PORT}
networks:
ollama-net:
driver: bridge
ipam:
driver: default
config:
- subnet: ${SUBNET_ADDRESS}/16
volumes:
discord:
redis:

View File

@@ -33,8 +33,8 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
let cleanedMessage = clean(message.content, clientId)
log(`Message "${cleanedMessage}" from ${message.author.tag} in channel/thread ${message.channelId}.`)
// Do not respond if bot talks in the chat
if (message.author.id === clientId) return
// Ignore messages from all bots
if (message.author.bot) return
// Check if message mentions the bot or passes random chance (30%)
const isMentioned = message.mentions.has(clientId)
@@ -186,7 +186,7 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
try {
const userSentimentRaw = await redis.get(userSentimentKey)
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.`)
userSentiment = 0.50
await redis.set(userSentimentKey, '0.50').catch((err: Error) => log(`Failed to set default user sentiment: ${err.message}`))
@@ -200,20 +200,19 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
try {
const botSentimentRaw = await redis.get(botSentimentKey)
botSentiment = parseFloat(botSentimentRaw || '0.50')
if (botSentimentRaw === null) {
log(`Bot sentiment not initialized. Setting to 0.50.`)
if (isNaN(botSentiment) || botSentiment < 0 || botSentiment > 1) {
log(`Invalid bot sentiment for ${botSentimentKey}: ${botSentimentRaw}. Using default 0.50.`)
botSentiment = 0.50
await redis.set(botSentimentKey, '0.50').catch((err: Error) => log(`Failed to set default bot sentiment: ${err.message}`))
} else if (isNaN(botSentiment) || botSentiment < 0 || botSentiment > 1) {
log(`Invalid bot sentiment: ${botSentimentRaw}. Using default 0.50.`)
botSentiment = 0.50
await redis.set(botSentimentKey, '0.50').catch((err: Error) => log(`Failed to set default bot sentiment: ${err.message}`))
await redis.set(botSentimentKey, '0.50')
}
} catch (error) {
log(`Failed to get bot sentiment from Redis: ${error}`)
botSentiment = 0.50
await redis.set(botSentimentKey, '0.50').catch((err: Error) => log(`Failed to set default bot sentiment: ${err.message}`))
await redis.set(botSentimentKey, '0.50')
}
// Construct sentiment data with bot ID
const sentimentData = `User ${message.author.id} sentiment: ${userSentiment.toFixed(2)}, Bot ${clientId} sentiment: ${botSentiment.toFixed(2)}`
// Log initial sentiments with two decimals
log(`Initial sentiments - User ${message.author.id}: ${userSentiment.toFixed(2)}, Bot: ${botSentiment.toFixed(2)}`)
@@ -268,22 +267,20 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
}
// Execute redis_ops
if (jsonResponse.metadata?.redis_ops) {
for (const op of jsonResponse.metadata.redis_ops) {
try {
if (op.action === 'set' && op.key && op.value !== undefined) {
// Validate sentiment value
const key = op.key.replace('<bot_id>', clientId)
if (op.action === 'set' && op.value !== undefined) {
const value = parseFloat(op.value.toString())
if (isNaN(value) || value < 0 || value > 1) {
log(`Invalid sentiment value for ${op.key}: ${op.value}. Skipping.`)
log(`Invalid sentiment value for ${key}: ${op.value}. Skipping.`)
continue
}
// Store with two decimal places
await redis.set(op.key, value.toFixed(2))
log(`Set ${op.key} to ${value.toFixed(2)}`)
await redis.set(key, value.toFixed(2))
log(`Set ${key} to ${value.toFixed(2)}`)
} else if (op.action === 'get' && op.key) {
const value = await redis.get(op.key)
log(`Got ${op.key}: ${value}`)
const value = await redis.get(key)
log(`Got ${key}: ${value}`)
} else {
log(`Invalid redis_op: ${JSON.stringify(op)}. Skipping.`)
}