Hello! Let me begin by saying that I’m a complete noob when it comes to coding, however thanks to the wonders of AI copilots avaliable in VSC I managed to construct such monstrocity <I spent last couple hours trying to figure it out so here’s the updated code>:
const { NlpManager } = require('node-nlp');
const fs = require('fs');
const path = require('path');
const tf = require('@tensorflow/tfjs-node');
// Register the CPU backend with TensorFlow
tf.setBackend('cpu');
const modelPath = path.join(__dirname, 'qna-model.json');
// Check if the saved model file exists, and load it if it does
let manager;
if (fs.existsSync(modelPath)) {
const modelJson = fs.readFileSync(modelPath, 'utf-8');
manager = new NlpManager({ languages: ['en'] });
manager.import(modelJson);
} else {
manager = new NlpManager({ languages: ['en'] });
// Train the QnA with sample data
manager.addDocument('en', 'Hello', 'greetings.hello');
manager.addDocument('en', 'Hi', 'greetings.hello');
manager.addDocument('en', 'How are you?', 'greetings.howareyou');
manager.addDocument('en', 'What is your name?', 'bot.name');
manager.train();
// Retrieve the last 1000 messages from the database
const numMessages = 1000;
db.all(`SELECT message FROM messages ORDER BY timestamp DESC LIMIT ${numMessages}`, [], (err, rows) => {
if (err) {
console.error(err);
} else {
// Train the QnA with the retrieved messages
rows.forEach((row) => {
const message = row.message;
if (typeof message === 'string' && message.length > 0) {
manager.addDocument('en', message, 'user.message');
}
});
// Save the updated model to a JSON file
const modelJson = manager.export();
fs.writeFileSync(modelPath, modelJson, 'utf-8');
manager.train();
}
});
}
const qna = require('@tensorflow-models/qna');
function sendErrorMessage(ws, errorMessage) {
const errorResponse = { error: errorMessage };
ws.send(JSON.stringify(errorResponse));
}
// Define an async function that loads the QnA model and generates a response
async function generateResponse(message) {
const question = message.question;
const passage = message.passage;
const model = await qna.load();
const answers = await model.findAnswers(question, passage);
// Return the top answer found by the model, or an error message if no answers were found
if (answers.length > 0) {
return answers[0].text;
} else {
return 'Sorry, I could not find an answer to your question.';
}
}
// Define an async function that handles incoming messages
async function handleMessage(message, ws) {
const response = { message: message.message };
try {
const result = await manager.process('en', message.message);
console.log(result);
if (result.intent) {
response.intent = result.intent;
}
if (result.entities) {
response.entities = result.entities;
}
if (result.answer) {
response.answer = result.answer;
} else if (message.question && message.passage) {
// If NLP wasn't able to provide an answer, generate one using QnA
response.answer = await generateResponse(message);
} else {
response.answer = 'Sorry, I could not understand your request.';
}
} catch (error) {
console.error(error);
sendErrorMessage(ws, 'An error occurred while processing the message.');
}
return response;
}
// Use the handleMessage function as a callback for incoming messages
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 5000 });
wss.on('connection', (ws) => {
console.log('New connection');
// Send a welcome message to the client
ws.send('Welcome to the chat-hub server!');
// Handle incoming messages from the client
ws.on('message', async (message) => {
console.log(`Received message: ${message}`);
// Parse the message as a JSON object
const parsedMessage = JSON.parse(message);
// Extract the message text from the "text" property, or use an empty string if the property is missing
const messageText = parsedMessage.text || '';
// Store the message in the database
const timestamp = new Date().toISOString();
const sender = 'client';
db.run(`INSERT INTO messages (sender, message, timestamp) VALUES (?, ?, ?)`, [sender, messageText, timestamp], (err) => {
if (err) {
console.error(err);
}
});
try {
// Use the handleMessage function to generate a response from the input message
if (parsedMessage.question && parsedMessage.passage) {
const answer = await generateResponse(parsedMessage);
const response = { answer };
// Send the response back to the client that sent the message
ws.send(JSON.stringify(response));
}
} catch (error) {
console.error(error);
sendErrorMessage(ws, 'An error occurred while processing the message.');
}
});
});
// Add code to connect to local database and file system
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('chat-hub.db');
db.run(`CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sender TEXT,
message TEXT,
timestamp TEXT
)`);
The general idea is to get a model that works as a websocket server and make it respond coherently to client’s messages (questions). There is also a module that creates a sql database to store all the messages which then are supposed to be used to re-train the model - although I’m not sure if it works as supposed to as the saved json file has a constant size of 8KB. At the current stage websocket server is working as supposed to and is receiving messages from clients but I didn’t manage to get any response from it. Here’s what I get when I run the code:
New connection
Received message: {“text”:“”,“question”:“What is the meaning of life?”,“passage”:“The meaning of life is a philosophical question…”}
============================
Hi, looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, visit GitHub - tensorflow/tfjs-node: TensorFlow powered JavaScript library for training and deploying ML models on Node.js. for more details.
…
Can you help?