npm init
npm install dotenv npm install restify npm install botbuilder npm install watson-developer-cloud npm install request-promise
app.js
file and copy the following code:
var restify = require('restify'); var builder = require('botbuilder'); var Conversation = require('watson-developer-cloud/conversation/v1'); // watson sdk require('dotenv').config({ silent: true }); var contexts; var workspace = process.env.WORKSPACE_ID; // Setup Restify Server var server = restify.createServer(); server.listen(process.env.port || process.env.PORT || 3978, function() { console.log('%s listening to %s', server.name, server.url); }); // Create the service wrapper var conversation = new Conversation({ username: process.env.WATSON_USERNAME, password: process.env.WATSON_PASSWORD, url: process.env.WATSON_URL + process.env.WORKSPACE_ID + '/message?version=2017-05-26', version_date: Conversation.VERSION_DATE_2017_05_26 }); // Create chat connector for communicating with the Bot Framework Service var connector = new builder.ChatConnector({ appId: process.env.MICROSOFT_APP_ID, appPassword: process.env.MICROSOFT_APP_PASSWORD }); // Listen for messages from users server.post('/api/messages', connector.listen()); // Create your bot with a function to receive messages from the user var bot = new builder.UniversalBot(connector, function(session) { let payload = { workspace_id: workspace, context: [], input: { text: session.message.text } }; let conversationContext = { workspaceId: workspace, watsonContext: {} }; if (!conversationContext) { conversationContext = {}; } payload.context = conversationContext.watsonContext; conversation.message(payload, function(err, response) { if (err) { console.log(err); session.send(err); } else { console.log(JSON.stringify(response, null, 2)); session.send(response.output.text); conversationContext.watsonContext = response.context; } }); });
.env
file:
# Bot Framework Credentials MICROSOFT_APP_ID=... MICROSOFT_APP_PASSWORD=... #Watson Url WATSON_URL=https://gateway.watsonplatform.net/conversation/api/v1/workspaces/ WATSON_USERNAME=... WATSON_PASSWORD=... WORKSPACE_ID=<UUID>
// This loads the environment variables from the .env file require('dotenv-extended').load(); var Conversation = require('watson-developer-cloud/conversation/v1'); // watson sdk var conversation = new Conversation({ username: process.env.WATSON_USERNAME, password: process.env.WATSON_PASSWORD, version_date: Conversation.VERSION_DATE_2017_05_26 }); conversation.listWorkspaces(function(err, response) { if (err) { console.error(err); } else { console.log(JSON.stringify(response, null, 2)); } });
node workspaces.js
var request = require("request-promise"); module.exports.Detect = async function LanguageDetect(text) { let options = { baseUrl: "https://watson-api-explorer.mybluemix.net", uri: "/language-translator/api/v2/identify", method: "GET", qs: { // Query string like ?text=some text text: text }, json: true }; try { let result = await request(options); return result.languages[0].language; } catch (err) { console.error(err); } };
var language = require('./language');
session.preferredLocale()
method to save or retrieve this property for each user:
// Detect language en/ar first and set correspondent locale let locale = await language.Detect(session.message.text); session.preferredLocale(locale);
// Get Watson service wrapper for English var conversation_en = new Conversation({ username: process.env.WATSON_USERNAME, password: process.env.WATSON_PASSWORD, url: process.env.WATSON_URL + process.env.WORKSPACE_ID_EN + '/message?version=2017-05-26', version_date: Conversation.VERSION_DATE_2017_05_26 }); // Get Watson service wrapper for Arabic var conversation_ar = new Conversation({ username: process.env.WATSON_USERNAME, password: process.env.WATSON_PASSWORD, url: process.env.WATSON_URL + process.env.WORKSPACE_ID_AR + '/message?version=2017-05-26', version_date: Conversation.VERSION_DATE_2017_05_26 });
Note. Note: now in the.env
file we have 2 variablesWORKSPACE_ID_EN
andWORKSPACE_ID_AR
, instead of oneWORKSPACE_ID
.
// Detect language en/ar first and set correspondent locale let locale = await language.Detect(session.message.text); session.preferredLocale(locale); let workspace = (locale == "ar") ? process.env.WORKSPACE_ID_AR : process.env.WORKSPACE_ID_EN; // Get Watson service wrapper according to the locale let conversation = (locale == "ar") ? conversation_ar : conversation_en; // Prepare Watson request let payload = { workspace_id: workspace, context: [], input: { text: session.message.text } }; let conversationContext = { workspaceId: workspace, watsonContext: {} }; ...
builder.Prompts.choice()
or session.send()
searches for the bot's messages in the ./locale/<>/index.json
file, where the IETF language tag represents the selected locale for which search posts. The following screenshot shows the resulting structure of the project directories for the English and Arabic languages:
session.send()
method instead of the previously localized text string:
session.send("greeting_message");
session.localizer.gettext()
method. For ease of use, I wrote an extension of the Session class and wrote a wrapper like the tr()
function from Qt (all the same, JavaScript is sometimes a very handy thing!). Here you can also implement the substitution of tokens of the type {name}, {id}, {phone}, etc .:
const { Session } = require('botbuilder'); // Object extension function for strings localization (translation) Session.prototype.tr = function (text) { return this.localizer.gettext(this.preferredLocale(), text) .replace("{name}", this.userName()); }; // Object extension function to get user id Session.prototype.userId = function () { return this.message.address.user.id; }; // Object extension function to get user name Session.prototype.userName = function () { return this.message.address.user.name; };
var responses = { // Responses object "greeting": { "no_entities": async function (session) { session.send("greeting_message"); }, }, "purchase": { "sale-stop": async function (session) { session.send("3_sales_end_dates"); }, "product-sale": async function (session) { session.send("4_sale_still_running"); }, /** @param {Session} session */ "price-product": async function (session) { session.send(session.tr("6_product_prices")); }, "price": async function (session) { session.send(session.tr("6_product_prices")); }, }, "inquiry": { "job": async function (session) { session.send("5_job_opportunity"); }, ... }, ... }
// Send request to Watson conversation.message(payload, async function (err, response) { if (err) { console.log(err); session.send(err); } else { // Generate response to user according to Watson intent-entity pairs let processed = false; // Get intent let intent = (response.intents[0]) ? response.intents[0].intent : undefined; for(i = 0; i < response.entities.length; i++) { // Process single entity in response let entity = (response.entities[i]) ? response.entities[i].entity : undefined; // Process single entity in response if (responses[intent] && responses[intent][entity]) { await responses[intent][entity](session, intent, [response.entities[i]]); processed = true; break; } } // Message was not recognized if(!processed) { session.send(session.tr("get_started")); } conversationContext.watsonContext = response.context; } });
Source: https://habr.com/ru/post/340092/