├── .gitignore ├── .eslintrc.js ├── deploymentScripts └── msbotClone │ └── bot.recipe ├── qna-bot-v-4.bot ├── PREREQUISITES.md ├── package.json ├── bot.js ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | .env 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "space-before-function-paren": [2, { 8 | "named": "never", 9 | "anonymous": "never", 10 | "asyncArrow": "always" 11 | }], 12 | "template-curly-spacing": [2, "always"] 13 | } 14 | }; -------------------------------------------------------------------------------- /deploymentScripts/msbotClone/bot.recipe: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "resources": [ 4 | { 5 | "type": "endpoint", 6 | "id": "90", 7 | "name": "development", 8 | "url": "http://localhost:3978/api/messages" 9 | }, 10 | { 11 | "type": "endpoint", 12 | "id": "2", 13 | "name": "production", 14 | "url": "https://your-bot-url.azurewebsites.net/api/messages" 15 | }, 16 | { 17 | "type": "abs", 18 | "id": "3", 19 | "name": "qna-bot-v-4-abs" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /qna-bot-v-4.bot: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qna-bot-v-4", 3 | "services": [ 4 | { 5 | "type": "endpoint", 6 | "name": "development", 7 | "endpoint": "http://localhost:3978/api/messages", 8 | "appId": "", 9 | "appPassword": "", 10 | "id": "1" 11 | }, 12 | { 13 | "type": "qna", 14 | "name": "my-test-kb", 15 | "kbId": "", 16 | "hostname": "", 17 | "endpointKey": "", 18 | "subscriptionKey": "", 19 | "id": "123" 20 | } 21 | ], 22 | "padlock": "", 23 | "version": "2.0" 24 | } 25 | -------------------------------------------------------------------------------- /PREREQUISITES.md: -------------------------------------------------------------------------------- 1 | # Azure Deployment Prerequisites 2 | This bot has prerequisite requirements in order to deploy the bot to Azure. 3 | 4 | This document will enumerate the required prerequisites and show how to install them. 5 | 6 | ## Overview 7 | There are a small set of CLI tools that will automate the process of deploying this bot to Azure. These CLI tools are only require for deployment. If you only plan to run the bot locally, these prerequisites are not required. 8 | 9 | ## Prerequisites 10 | - If you don't have an Azure subscription, create a [free account][5]. 11 | - Install the latest version of the [Azure CLI][6] tool. Version 2.0.54 or higher. 12 | - Install latest version of the `MSBot` CLI tool. Version 4.3.2 or higher. 13 | ```bash 14 | # install msbot CLI tool 15 | npm install -g msbot 16 | ``` 17 | 18 | [Return to README.md][3] 19 | 20 | 21 | [3]: ./README.md 22 | [4]: https://nodejs.org 23 | [5]: https://azure.microsoft.com/free/ 24 | [6]: https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qna-bot-v-4", 3 | "version": "1.0.0", 4 | "description": "Demonstrate the core capabilities of the Microsoft Bot Framework", 5 | "author": "Generated using Microsoft Bot Builder Yeoman generator v4.2.6", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "scripts": { 9 | "lint": "./node_modules/.bin/eslint .", 10 | "start": "node ./index.js", 11 | "test": "echo \"Error: no test specified\" && exit 1", 12 | "watch": "nodemon ./index.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com" 17 | }, 18 | "dependencies": { 19 | "botbuilder": "^4.2.0", 20 | "botbuilder-ai": "^4.3.4", 21 | "botframework-config": "^4.2.0", 22 | "dotenv": "^6.1.0", 23 | "restify": "^7.2.3" 24 | }, 25 | "devDependencies": { 26 | "eslint": "^5.8.0", 27 | "eslint-config-standard": "^12.0.0", 28 | "eslint-plugin-import": "^2.14.0", 29 | "eslint-plugin-node": "^8.0.0", 30 | "eslint-plugin-promise": "^4.0.1", 31 | "eslint-plugin-standard": "^4.0.0", 32 | "nodemon": "^1.18.7" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /bot.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | const { ActivityTypes } = require('botbuilder'); 5 | 6 | class MyBot { 7 | /** 8 | * 9 | * @param {TurnContext} on turn context object. 10 | */ 11 | 12 | constructor(qnaServices) { 13 | this.qnaServices = qnaServices; 14 | } 15 | 16 | async onTurn(turnContext) { 17 | // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types. 18 | if (turnContext.activity.type === ActivityTypes.Message) { 19 | for (let i = 0; i < this.qnaServices.length; i++) { 20 | const qnaResults = await this.qnaServices[i].getAnswers(turnContext); 21 | if(qnaResults[0]) { 22 | await turnContext.sendActivity(qnaResults[0].answer); 23 | return; 24 | } 25 | } 26 | await turnContext('No QnA Maker answers were found. ' 27 | + 'This example uses a QnA Maker Knowledge Base that focuses on smart light bulbs. ' 28 | + `Ask the bot questions like "Why won't it turn on?" or "I need help."`); 29 | } else { 30 | await turnContext.sendActivity(`[${ turnContext.activity.type } event detected]`); 31 | } 32 | } 33 | } 34 | 35 | module.exports.MyBot = MyBot; 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qna-bot-v-4 2 | Demonstrate the core capabilities of the Microsoft Bot Framework 3 | 4 | This bot has been created using [Bot Framework][1], it shows how to create a simple bot that accepts input from the user and echoes it back. 5 | 6 | ## Prerequisites 7 | - [Node.js][4] version 8.5 or higher 8 | ```bash 9 | # determine node version 10 | node --version 11 | ``` 12 | # To run the bot 13 | - Install modules 14 | ```bash 15 | npm install 16 | ``` 17 | - Start the bot 18 | ```bash 19 | npm start 20 | ``` 21 | 22 | # Testing the bot using Bot Framework Emulator **v4** 23 | [Bot Framework Emulator][5] is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. 24 | 25 | - Install the Bot Framework Emulator version 4.2.0 or greater from [here][6] 26 | 27 | ## Connect to the bot using Bot Framework Emulator **v4** 28 | - Launch Bot Framework Emulator 29 | - File -> Open Bot Configuration 30 | - Navigate to `qna-bot-v-4` folder 31 | - Select `qna-bot-v-4.bot` file 32 | 33 | # Deploy the bot to Azure 34 | 35 | ## Prerequisites 36 | - [Azure Deployment Prerequisites][41] 37 | 38 | ## Provision a Bot with Azure Bot Service 39 | After creating the bot and testing it locally, you can deploy it to Azure to make it accessible from anywhere. To deploy your bot to Azure: 40 | 41 | ```bash 42 | # login to Azure 43 | az login 44 | ``` 45 | 46 | ```bash 47 | # provision Azure Bot Services resources to host your bot 48 | msbot clone services --name "qna-bot-v-4" --code-dir "." --location --sdkLanguage "Node" --folder deploymentScripts/msbotClone --verbose 49 | ``` 50 | 51 | ## Publishing Changes to Azure Bot Service 52 | As you make changes to your bot running locally, and want to deploy those change to Azure Bot Service, you can _publish_ those change using either `publish.cmd` if you are on Windows or `./publish` if you are on a non-Windows platform. The following is an example of publishing 53 | 54 | ```bash 55 | # run the publish helper (non-Windows) to update Azure Bot Service. Use publish.cmd if running on Windows 56 | ./publish 57 | ``` 58 | 59 | ## Getting Additional Help with Deploying to Azure 60 | To learn more about deploying a bot to Azure, see [Deploy your bot to Azure][40] for a complete list of deployment instructions. 61 | 62 | # Further reading 63 | - [Bot Framework Documentation][20] 64 | - [Bot Basics][32] 65 | - [Azure Bot Service Introduction][21] 66 | - [Azure Bot Service Documentation][22] 67 | - [Deploy Your Bot to Azure][40] 68 | - [Azure CLI][7] 69 | - [msbot CLI][9] 70 | - [Azure Portal][10] 71 | - [Language Understanding using LUIS][11] 72 | - [Restify][30] 73 | - [dotenv][31] 74 | 75 | [1]: https://dev.botframework.com 76 | [2]: https://www.typescriptlang.org 77 | [3]: https://www.typescriptlang.org/#download-links 78 | [4]: https://nodejs.org 79 | [5]: https://github.com/microsoft/botframework-emulator 80 | [6]: https://github.com/Microsoft/BotFramework-Emulator/releases 81 | [7]: https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest 82 | [8]: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest 83 | [9]: https://github.com/Microsoft/botbuilder-tools/tree/master/packages/MSBot 84 | [10]: https://portal.azure.com 85 | [11]: https://www.luis.ai 86 | [20]: https://docs.botframework.com 87 | [21]: https://docs.microsoft.com/en-us/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0 88 | [22]: https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0 89 | [30]: https://www.npmjs.com/package/restify 90 | [31]: https://www.npmjs.com/package/dotenv 91 | [32]: https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0 92 | [40]: https://aka.ms/azuredeployment 93 | [41]: ./PREREQUISITES.md 94 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | const dotenv = require('dotenv'); 5 | const path = require('path'); 6 | const restify = require('restify'); 7 | const { QnAMaker } = require('botbuilder-ai'); 8 | 9 | // Import required bot services. 10 | // See https://aka.ms/bot-services to learn more about the different parts of a bot. 11 | const { BotFrameworkAdapter } = require('botbuilder'); 12 | 13 | // Import required bot configuration. 14 | const { BotConfiguration } = require('botframework-config'); 15 | 16 | // This bot's main dialog. 17 | const { MyBot } = require('./bot'); 18 | 19 | // Read botFilePath and botFileSecret from .env file 20 | // Note: Ensure you have a .env file and include botFilePath and botFileSecret. 21 | const ENV_FILE = path.join(__dirname, '.env'); 22 | dotenv.config({ path: ENV_FILE }); 23 | 24 | // bot endpoint name as defined in .bot file 25 | // See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. 26 | const DEV_ENVIRONMENT = 'development'; 27 | 28 | // bot name as defined in .bot file 29 | // See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. 30 | const BOT_CONFIGURATION = (process.env.NODE_ENV || DEV_ENVIRONMENT); 31 | 32 | // Create HTTP server 33 | const server = restify.createServer(); 34 | server.listen(process.env.port || process.env.PORT || 3978, () => { 35 | console.log(`\n${ server.name } listening to ${ server.url }`); 36 | console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`); 37 | console.log(`\nTo talk to your bot, open qna-bot-v-4.bot file in the Emulator`); 38 | }); 39 | 40 | // .bot file path 41 | const BOT_FILE = path.join(__dirname, (process.env.botFilePath || '')); 42 | 43 | // Read bot configuration from .bot file. 44 | let botConfig; 45 | try { 46 | botConfig = BotConfiguration.loadSync(BOT_FILE, process.env.botFileSecret); 47 | } catch (err) { 48 | console.error(`\nError reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.`); 49 | console.error(`\n - The botFileSecret is available under appsettings for your Azure Bot Service bot.`); 50 | console.error(`\n - If you are running this bot locally, consider adding a .env file with botFilePath and botFileSecret.`); 51 | console.error(`\n - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.\n\n`); 52 | process.exit(); 53 | } 54 | 55 | // Get bot endpoint configuration by service name 56 | const endpointConfig = botConfig.findServiceByNameOrId(BOT_CONFIGURATION); 57 | 58 | const qnaServices = []; 59 | botConfig.services.map(service => { 60 | if(service.type == "qna") { 61 | const endpoint = { 62 | knowledgeBaseId: service.kbId, 63 | endpointKey: service.endpointKey, 64 | host: service.hostname 65 | } 66 | const options = {}; 67 | qnaServices.push(new QnAMaker(endpoint, options)); 68 | } 69 | }); 70 | 71 | // Create adapter. 72 | // See https://aka.ms/about-bot-adapter to learn more about .bot file its use and bot configuration. 73 | const adapter = new BotFrameworkAdapter({ 74 | appId: endpointConfig.appId || process.env.microsoftAppID, 75 | appPassword: endpointConfig.appPassword || process.env.microsoftAppPassword 76 | }); 77 | 78 | // Catch-all for errors. 79 | adapter.onTurnError = async (context, error) => { 80 | // This check writes out errors to console log .vs. app insights. 81 | console.error(`\n [onTurnError]: ${ error }`); 82 | // Send a message to the user 83 | await context.sendActivity(`Oops. Something went wrong!`); 84 | }; 85 | 86 | // Create the main dialog. 87 | const myBot = new MyBot(qnaServices); 88 | 89 | // Listen for incoming requests. 90 | server.post('/api/messages', (req, res) => { 91 | adapter.processActivity(req, res, async (context) => { 92 | // Route to main dialog. 93 | await myBot.onTurn(context); 94 | }); 95 | }); 96 | --------------------------------------------------------------------------------