llama-cpp-python-djs-bot/llamabot.js
Raven Scott c14635769d feat: Add error handling for empty response in chatbot conversation
This commit adds a new block of code to handle cases where the chatbot generates an empty response, which was previously causing a delay of one message in the conversation. The new code selects a random message from a predefined list of human-like responses to notify the user that an error has occurred, then resets the conversation history and deletes the memory map for that user. This ensures that subsequent messages from the same user will not be delayed due to the empty response.
2023-04-10 02:53:37 +02:00

175 lines
6.1 KiB
JavaScript

const Discord = require('discord.js');
const fetch = require('node-fetch');
const emptyResponses = require('./assets/emptyMessages.js');
const {resetResponses, userResetMessages} = require('./assets/resetMessages.js');
const {errorMessages, busyResponses} = require('./assets/errorMessages.js');
require('dotenv').config()
// hi
const {
Client,
GatewayIntentBits,
ActivityType,
Partials
} = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.DirectMessages,
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildBans,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
partials: [Partials.Channel],
});
const channelID = '1094494101631680653'; // Replace with your channel ID
const channelID2 = '1094628334727614605'; // Replace with your channel ID
const conversations = new Map();
client.once('ready', () => {
console.log('Bot is ready.');
client.user.setPresence({
activities: [{
name: `AI`,
type: ActivityType.Playing
}],
status: 'dnd',
});
});
client.on('messageCreate', async (message) => {
// Only respond in the specified channels
if (message.channel.id !== channelID && message.channel.id !== channelID2) {
return;
}
if (message.author.bot) return; // Ignore messages from bots
if (conversations.get(message.author.id)?.busy) {
message.delete()
const busyResponse = busyResponses[Math.floor(Math.random() * busyResponses.length)];
await message.author.send(busyResponse); // give a notification of reset using a human like response.
return;
}
const userID = message.author.id;
let conversation = conversations.get(userID) || {
messages: [],
busy: false
};
if (conversation.messages.length === 0) {
conversation.messages.push({
role: 'user',
content: `Welcome to our conversation your name is "llama".`
});
conversation.messages.push({
role: 'user',
content: `My name is ${message.author.username}.`
});
conversation.messages.push({
role: 'assistant',
content: `Hello, ${message.author.username}, I am here to answer any question you have, how may I help you?`
});
conversation.messages.push({
role: 'user',
content: message.cleanContent
});
} else {
// Append user message to conversation history
conversation.messages.push({
role: 'user',
content: message.cleanContent
});
}
if (message.content === '!reset' || message.content === '!r') {
conversations.delete(userID); // Delete user's conversation map if they request reset
const userResetMessage = userResetMessages[Math.floor(Math.random() * userResetMessages.length)];
await message.channel.send(userResetMessage); // give a notification of reset using a human like response.
return;
}
// Append user message to conversation history
conversation.messages.push({
role: 'user',
content: message.cleanContent
});
try {
conversation.busy = true;
const response = await generateResponse(conversation);
// Append bot message to conversation history
conversation.messages.push({
role: 'assistant',
content: response
});
if (response && response.trim()) {
// Send response to user if it's not empty
await message.channel.send(response);
conversation.busy = false;
} else {
// Handle empty response here
const randomResponse = emptyResponses[Math.floor(Math.random() * emptyResponses.length)];
// We had an empty response, create a new memory map for sanity.
await message.channel.send(randomResponse); // give the user a human like reponse about the error
conversations.delete(userID); // Delete user's conversation map if they request reset
const resetMessage = resetResponses[Math.floor(Math.random() * resetResponses.length)];
await message.channel.send(resetMessage); // give a notification of reset using a human like response.
conversation.busy = false;
}
conversations.set(userID, conversation); // Update user's conversation map in memory
} catch (err) {
console.error(err);
const errorMessage = errorMessages[Math.floor(Math.random() * errorMessages.length)];
await message.channel.send(errorMessage); // give a notification of reset using a human like response. } finally {
conversation.busy = false;
}
});
async function generateResponse(conversation) {
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
}, 900000);
const messagesCopy = [...conversation.messages]; // create a copy of the messages array
try {
const response = await fetch(`http://${process.env.ROOT_IP}:${process.env.ROOT_PORT}/v1/chat/completions`, {
method: 'POST',
headers: {
'accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: messagesCopy // use the copy of the messages array
}),
signal: controller.signal
});
const responseData = await response.json();
console.log(JSON.stringify(responseData))
const choice = responseData.choices[0];
// Remove "user None:" and any text after it from the response
const responseText = choice.message.content.trim();
const startIndex = responseText.indexOf('user None:');
const sanitizedResponse = startIndex === -1 ? responseText : responseText.substring(0, startIndex);
return sanitizedResponse;
} catch (err) {
throw err;
} finally {
clearTimeout(timeout);
}
}
client.login(process.env.THE_TOKEN); // Replace with your bot token