'use strict' /* Pakete die wir brauchen */ const querystring = require('querystring'); const fetch = require('node-fetch'); var WebSocketClient = require('websocket').client; /** Wissensbasis importieren und als Dictionary abspeichern */ var wissensbasis = require('./wissensbasis.json'); var answerDict = {}; wissensbasis.intents.forEach(e => { answerDict[e.intent] = e.answers; }); var repeat1Dict = {}; wissensbasis.intents.forEach(e => { repeat1Dict[e.intent] = e.repeat1; }); var repeat2Dict = {}; wissensbasis.intents.forEach(e => { repeat2Dict[e.intent] = e.repeat2; }); var fallbacks = []; wissensbasis.fallbacks.forEach(e => { fallbacks.push(e); }); /* Die Intents der letzten 2 Anfragen werden hier gespeichert */ var savedIntents = {}; /** bot ist ein einfacher Websocket Chat Client */ class bot { /** * Konstruktor baut den client auf. Er erstellt einen Websocket und verbindet sich zum Server * Bitte beachten Sie, dass die Server IP hardcodiert ist. Sie müssen sie umsetzten */ constructor () { /** Die Websocketverbindung */ this.client = new WebSocketClient() /** Der Name des Bots */ this.botname = "Raspi-Bot" /** Wenn der Websocket verbunden ist, dann setzten wir ihn auf true */ this.connected = false /** LUIS Endpoint-Parameter */ this.endpointKey = "9c4cdfefdcde4156a0735c0d2100ef3e"; this.endpoint = "raspberry-pi-4-chatbot.cognitiveservices.azure.com/"; this.appId = "87bb26ac-91ee-4006-a144-6cc7db61b0fb"; /** Wenn die Verbindung nicht zustande kommt, dann läuft der Aufruf hier hinein */ this.client.on('connectFailed', function (error) { console.log('[BOT] Connect Error: ' + error.toString()) }) /** Wenn der Client sich mit dem Server verbindet sind wir hier */ this.client.on('connect', function (connection) { this.con = connection console.log('[BOT] WebSocket Client Connected') connection.on('error', function (error) { console.log('[BOT] Connection Error: ' + error.toString()) }) /** * Es kann immer sein, dass sich der Client disconnected * (typischer Weise, wenn der Server nicht mehr da ist) */ connection.on('close', function () { console.log('[BOT] echo-protocol Connection Closed') }) /** * Hier ist der Kern, wenn immmer eine Nachricht empfangen wird, kommt hier die * Nachricht an. */ connection.on('message', function (message) { if (message.type === 'utf8') { var data = JSON.parse(message.utf8Data) console.log('[BOT] Received: ' + data.msg + ' ' + data.name) } }) /** * Hier senden wir unsere Kennung damit der Server uns erkennt. * Wir formatieren die Kennung als JSON */ function joinGesp () { if (connection.connected) { connection.sendUTF('{"type": "join", "name":"Raspi-Bot"}') } } joinGesp() }) } /** * Methode um sich mit dem Server zu verbinden. */ connect () { this.client.connect('ws://localhost:8181/', 'chat') this.connected = true } /** * Hier muss ihre Verarbeitungslogik integriert werden. * Diese Funktion wird automatisch im Server aufgerufen, wenn etwas ankommt, das wir * nicht geschrieben haben * @param nachricht auf die der bot reagieren soll * @param nachricht name des Absenders */ async post (nachricht, uname) { // Initialisiert den Intent-Speicher falls dies noch nicht geschehen ist if(savedIntents[uname] == undefined){ savedIntents[uname] = []; } // Sendet die Nachricht an LUIS und erhält extrahiert den Top-Intent und dessen Score aus der Antwort var luisResponse = await this.sendLUISrequest(nachricht); var intent = luisResponse.prediction.topIntent; var intentScore = luisResponse.prediction.intents[intent].score; // Antwort anhand des erhaltenen Intents und den vorherigen Intents ermitteln var answer; if(intentScore > 0.5){ if(intent != savedIntents[uname][0]){ var answerArray = answerDict[intent] answer = answerArray[Math.floor(Math.random() * answerArray.length)]; }else{ if(intent == savedIntents[uname][1]){ var repeat2Array = repeat2Dict[intent] answer = repeat2Array[Math.floor(Math.random() * repeat2Array.length)]; }else{ var repeat1Array = repeat1Dict[intent] answer = repeat1Array[Math.floor(Math.random() * repeat1Array.length)]; } } // Speichert den neuen Intent ab savedIntents[uname][1] = savedIntents[uname][0]; savedIntents[uname][0] = intent; }else{ answer = fallbacks[Math.floor(Math.random() * fallbacks.length)]; } // Antwort zusammensetzen und absenden var msg = '{"type": "msg", "name": "Raspi-Bot", "msg":"' + answer + '"}' this.client.con.sendUTF(msg) } /** * Sendet die Nachricht zum LUIS Endpoint * * @param message die Nachricht * @returns die Antwort */ async sendLUISrequest(message){ var queryParams = { "show-all-intents": true, "verbose": true, "query": message, "subscription-key": this.endpointKey } var URI =`https://${this.endpoint}/luis/prediction/v3.0/apps/${this.appId}/slots/production/predict?${querystring.stringify(queryParams)}`; var result await fetch(URI).then(d=>d.json()).then(e=>{ result = e }); return result; } } module.exports = bot