-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathMicrosoft Bot Framework HOL.html
1093 lines (992 loc) · 65.9 KB
/
Microsoft Bot Framework HOL.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<title>Microsoft Bot Framework HOL</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* GitHub stylesheet for MarkdownPad (http://markdownpad.com) */
/* Author: Nicolas Hery - http://nicolashery.com */
/* Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff */
/* Source: https://github.com/nicolahery/markdownpad-github */
/* RESET
=============================================================================*/
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
}
/* BODY
=============================================================================*/
body {
font-family: Helvetica, arial, freesans, clean, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #333;
background-color: #fff;
padding: 20px;
max-width: 960px;
margin: 0 auto;
}
body>*:first-child {
margin-top: 0 !important;
}
body>*:last-child {
margin-bottom: 0 !important;
}
/* BLOCKS
=============================================================================*/
p, blockquote, ul, ol, dl, table, pre {
margin: 15px 0;
}
/* HEADERS
=============================================================================*/
h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
}
h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
font-size: inherit;
}
h1 {
font-size: 28px;
color: #000;
}
h2 {
font-size: 24px;
border-bottom: 1px solid #ccc;
color: #000;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 16px;
}
h5 {
font-size: 14px;
}
h6 {
color: #777;
font-size: 14px;
}
body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}
h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}
/* LINKS
=============================================================================*/
a {
color: #4183C4;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* LISTS
=============================================================================*/
ul, ol {
padding-left: 30px;
}
ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}
ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}
dl {
padding: 0;
}
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
dl dt:first-child {
padding: 0;
}
dl dt>:first-child {
margin-top: 0px;
}
dl dt>:last-child {
margin-bottom: 0px;
}
dl dd {
margin: 0 0 15px;
padding: 0 15px;
}
dl dd>:first-child {
margin-top: 0px;
}
dl dd>:last-child {
margin-bottom: 0px;
}
/* CODE
=============================================================================*/
pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}
pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}
pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}
pre code, pre tt {
background-color: transparent;
border: none;
}
kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}
/* QUOTES
=============================================================================*/
blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}
blockquote>:first-child {
margin-top: 0px;
}
blockquote>:last-child {
margin-bottom: 0px;
}
/* HORIZONTAL RULES
=============================================================================*/
hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}
/* TABLES
=============================================================================*/
table th {
font-weight: bold;
}
table th, table td {
border: 1px solid #ccc;
padding: 6px 13px;
}
table tr {
border-top: 1px solid #ccc;
background-color: #fff;
}
table tr:nth-child(2n) {
background-color: #f8f8f8;
}
/* IMAGES
=============================================================================*/
img {
max-width: 100%
}
</style>
<style type="text/css">
.highlight { background: #ffffff; }
.highlight .c { color: #999988; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { font-weight: bold } /* Keyword */
.highlight .o { font-weight: bold } /* Operator */
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { font-weight: bold } /* Keyword.Constant */
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #d14 } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #0086B3 } /* Name.Builtin */
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
.highlight .no { color: #008080 } /* Name.Constant */
.highlight .ni { color: #800080 } /* Name.Entity */
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
.highlight .nn { color: #555555 } /* Name.Namespace */
.highlight .nt { color: #000080 } /* Name.Tag */
.highlight .nv { color: #008080 } /* Name.Variable */
.highlight .ow { font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
.highlight .sc { color: #d14 } /* Literal.String.Char */
.highlight .sd { color: #d14 } /* Literal.String.Doc */
.highlight .s2 { color: #d14 } /* Literal.String.Double */
.highlight .se { color: #d14 } /* Literal.String.Escape */
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
.highlight .si { color: #d14 } /* Literal.String.Interpol */
.highlight .sx { color: #d14 } /* Literal.String.Other */
.highlight .sr { color: #009926 } /* Literal.String.Regex */
.highlight .s1 { color: #d14 } /* Literal.String.Single */
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #008080 } /* Name.Variable.Class */
.highlight .vg { color: #008080 } /* Name.Variable.Global */
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
.pl-c {
color: #969896;
}
.pl-c1,.pl-mdh,.pl-mm,.pl-mp,.pl-mr,.pl-s1 .pl-v,.pl-s3,.pl-sc,.pl-sv {
color: #0086b3;
}
.pl-e,.pl-en {
color: #795da3;
}
.pl-s1 .pl-s2,.pl-smi,.pl-smp,.pl-stj,.pl-vo,.pl-vpf {
color: #333;
}
.pl-ent {
color: #63a35c;
}
.pl-k,.pl-s,.pl-st {
color: #a71d5d;
}
.pl-pds,.pl-s1,.pl-s1 .pl-pse .pl-s2,.pl-sr,.pl-sr .pl-cce,.pl-sr .pl-sra,.pl-sr .pl-sre,.pl-src,.pl-v {
color: #df5000;
}
.pl-id {
color: #b52a1d;
}
.pl-ii {
background-color: #b52a1d;
color: #f8f8f8;
}
.pl-sr .pl-cce {
color: #63a35c;
font-weight: bold;
}
.pl-ml {
color: #693a17;
}
.pl-mh,.pl-mh .pl-en,.pl-ms {
color: #1d3e81;
font-weight: bold;
}
.pl-mq {
color: #008080;
}
.pl-mi {
color: #333;
font-style: italic;
}
.pl-mb {
color: #333;
font-weight: bold;
}
.pl-md,.pl-mdhf {
background-color: #ffecec;
color: #bd2c00;
}
.pl-mdht,.pl-mi1 {
background-color: #eaffea;
color: #55a532;
}
.pl-mdr {
color: #795da3;
font-weight: bold;
}
.pl-mo {
color: #1d3e81;
}
.task-list {
padding-left:10px;
margin-bottom:0;
}
.task-list li {
margin-left: 20px;
}
.task-list-item {
list-style-type:none;
padding-left:10px;
}
.task-list-item label {
font-weight:400;
}
.task-list-item.enabled label {
cursor:pointer;
}
.task-list-item+.task-list-item {
margin-top:3px;
}
.task-list-item-checkbox {
display:inline-block;
margin-left:-20px;
margin-right:3px;
vertical-align:1px;
}
</style>
</head>
<body>
<p><a name="HOLTitle"></a></p>
<h1>Building Intelligent Bots with the Microsoft Bot Framework</h1>
<hr>
<p><a name="Overview"></a></p>
<h2>Overview</h2>
<p>Software bots are everywhere. You probably interact with them every day without realizing it. Bots, especially chat and messenger bots, are changing the way we interact with businesses, communities, and even each other. Thanks to light-speed advances in artificial intelligence (AI) and the ready availability of AI services, bots are not only becoming more advanced and personalized, but also more accessible to developers.</p>
<p>Regardless of the target language or platform, developers building bots face the same challenges. Bots must be able process input and output intelligently. Bots need to be responsive, scalable, and extensible. They need to work cross-platform, and they need to interact with users in a conversational manner and in the language the user chooses.</p>
<p>The <a href="https://dev.botframework.com/">Microsoft Bot Framework</a>, combined with <a href="https://qnamaker.ai/">Microsoft QnA Maker</a>, provides the tools developers need to build and publish intelligent bots that interact naturally with users using a range of services. In this lab, you will create a bot using Visual Studio Code and the Microsoft Bot Framework, and connect it to a knowledge base built with QnA Maker. Then you will interact with the bot using Skype — one of many popular services with which bots built with the Microsoft Bot Framework can integrate.</p>
<p><a name="Objectives"></a></p>
<h3>Objectives</h3>
<p>In this hands-on lab, you will learn how to:</p>
<ul>
<li>Create an Azure Bot Service to host a bot</li>
<li>Create a Microsoft QnA knowledge base, populate it with data, and connect it to a bot</li>
<li>Implement bots in code and debug the bots that you build</li>
<li>Publish bots and use continuous integration to keep them up to date</li>
<li>Plug a bot into Skype and interact with it there</li>
</ul>
<p><a name="Prerequisites"></a></p>
<h3>Prerequisites</h3>
<p>The following are required to complete this hands-on lab:</p>
<ul>
<li>An active Microsoft Azure subscription. If you don't have one, <a href="http://aka.ms/WATK-FreeTrial">sign up for a free trial</a>.</li>
<li><a href="http://code.visualstudio.com">Visual Studio Code</a></li>
<li><a href="https://git-scm.com/downloads">Git Client</a></li>
<li><a href="https://nodejs.org">Node.js</a></li>
<li><a href="https://emulator.botframework.com/">Microsoft Bot Framework Emulator</a></li>
<li><a href="https://www.skype.com/en/download-skype/skype-for-computer/">Skype</a></li>
</ul>
<hr>
<p><a name="Exercises"></a></p>
<h2>Exercises</h2>
<p>This hands-on lab includes the following exercises:</p>
<ul>
<li><a href="#Exercise1">Exercise 1: Create an Azure Bot Service</a></li>
<li><a href="#Exercise2">Exercise 2: Get started with Microsoft QnA Maker</a></li>
<li><a href="#Exercise3">Exercise 3: Expand the QnA Maker knowledge base</a></li>
<li><a href="#Exercise4">Exercise 4: Deploy the bot and set up continuous integration</a></li>
<li><a href="#Exercise5">Exercise 5: Debug the bot locally</a></li>
<li><a href="#Exercise6">Exercise 6: Connect the bot to the knowledge base</a></li>
<li><a href="#Exercise7">Exercise 7: Test the bot with Skype</a></li>
</ul>
<p>Estimated time to complete this lab: <strong>60</strong> minutes.</p>
<p><a name="Exercise1"></a></p>
<h2>Exercise 1: Create an Azure Bot Service</h2>
<p>The first step in creating a bot is to provide a location for the bot to be hosted, as well as configuring the services that the bot will use. <a href="https://azure.microsoft.com/services/app-service/web/">Azure Web Apps</a> are perfect for hosting bot applications, and the Azure Bot Service is designed to provision and connect these services for you. In this exercise, you will create and configure an Azure Bot Service.</p>
<ol>
<li>
<p>Open the <a href="https://portal.azure.com">Azure Portal</a> in your browser. If you are asked to sign in, do so using your Microsoft account.</p>
</li>
<li>
<p>Click <strong>+ New</strong>, followed by <strong>Intelligence + analytics</strong> and then <strong>Bot Service (preview)</strong>.</p>
<p><a href="Images/portal-new-bot-service.png" target="_blank"><img src="Images/portal-new-bot-service.png" alt="Creating a new Azure Bot Service" style="max-width:100%;"></a></p>
<p><em>Creating a new Azure Bot Service</em></p>
</li>
<li>
<p>Enter a name such as "qnafactbot" (without quotation marks) into the <strong>App name</strong> box. <em>This name must be unique within Azure, so make sure a green check mark appears next to it.</em> Make sure <strong>Create new</strong> is selected under <strong>Resource Group</strong> and enter the resource-group name "BotsResourceGroup" (again, without quotation marks). Then select the location nearest you and click <strong>Create</strong>.</p>
<p><a href="Images/portal-create-new-bot-service.png" target="_blank"><img src="Images/portal-create-new-bot-service.png" alt="Configuring a new Azure Bot Service" style="max-width:100%;"></a></p>
<p><em>Configuring a new Azure Bot Service</em></p>
</li>
<li>
<p>Click <strong>Resource Groups</strong> in the</p>
</li>
<li>
<p>on the left, followed by <strong>BotsResourceGroup</strong> to open the resource group created for the Bot Service.</p>
<p><a href="Images/portal-open-resource-group.png" target="_blank"><img src="Images/portal-open-resource-group.png" alt="Opening the resource group" style="max-width:100%;"></a></p>
<p><em>Opening the resource group</em></p>
</li>
<li>
<p>Wait until "Deploying" changes to "Succeeded" indicating that the Bot Service was successfully deployed. You can click the <strong>Refresh</strong> button at the top of the blade to refresh the deployment status.</p>
<p><a href="Images/portal-app-deployment-status.png" target="_blank"><img src="Images/portal-app-deployment-status.png" alt="Successful deployment" style="max-width:100%;"></a></p>
<p><em>Successful deployment</em></p>
</li>
<li>
<p>Click <strong>qnafactbot</strong> (or the name you entered in Step 3) to open the App Service created for your bot.</p>
<p><a href="Images/portal-click-bot-service.png" target="_blank"><img src="Images/portal-click-bot-service.png" alt="Opening the Bot Service" style="max-width:100%;"></a></p>
<p><em>Opening the Bot Service</em></p>
</li>
<li>
<p>Click <strong>Create Microsoft App ID and password</strong>. If you are asked to sign in again, do so using your Microsoft account.</p>
<p><a href="Images/portal-click-create-msft-app.png" target="_blank"><img src="Images/portal-click-create-msft-app.png" alt="Creating an app ID and password" style="max-width:100%;"></a></p>
<p><em>Creating an app ID and password</em></p>
</li>
<li>
<p>Click <strong>Generate an app password to continue</strong>.</p>
<p><a href="Images/portal-generate-password.png" target="_blank"><img src="Images/portal-generate-password.png" alt="Generating an app password" style="max-width:100%;"></a></p>
<p><em>Generating an app password</em></p>
</li>
<li>
<p>Copy the password to the clipboard. <strong>You will not be able to retrieve this password after this step</strong>, but will be required to use it in a later exercise. Once the password is saved, click <strong>Ok</strong> to dismiss the dialog.</p>
<p><a href="Images/portal-new-password-generated.png" target="_blank"><img src="Images/portal-new-password-generated.png" alt="Copying the app password" style="max-width:100%;"></a></p>
<p><em>Copying the app password</em></p>
</li>
<li>
<p>Review the application registration information, and then click <strong>Finish and go back to Bot Framework</strong>.</p>
<p><a href="Images/portal-click-finish.png" target="_blank"><img src="Images/portal-click-finish.png" alt="Finalizing the app registration" style="max-width:100%;"></a></p>
<p><em>Finalizing the app registration</em></p>
</li>
<li>
<p>Paste the password copied to the clipboard in Step 9 into the password box.</p>
<p><a href="Images/portal-paste-app-password.png" target="_blank"><img src="Images/portal-paste-app-password.png" alt="Pasting the app password" style="max-width:100%;"></a></p>
<p><em>Pasting the app password</em></p>
</li>
<li>
<p>Click <strong>NodeJS</strong>. Then click <strong>Question and Answer</strong> and click <strong>Create bot</strong>. If you are asked to sign in again, do so using your Microsoft account. Also, if you are asked for permission for QnA Maker to access your info, click <strong>Yes</strong>.</p>
<p><a href="Images/portal-select-template.png" target="_blank"><img src="Images/portal-select-template.png" alt="Selecting a language and template" style="max-width:100%;"></a></p>
<p><em>Selecting a language and template</em></p>
</li>
<li>
<p>Check the <strong>I agree</strong> box, and then click <strong>OK</strong>. (If you are presented with the option of connecting to an existing knowledge base or creating a new one, choose the latter.)</p>
<p><a href="Images/connect-bot-to-qnamaker.png" target="_blank"><img src="Images/connect-bot-to-qnamaker.png" alt="Connecting to QnA Maker" style="max-width:100%;"></a></p>
<p><em>Connecting to QnA Maker</em></p>
</li>
<li>
<p>After a brief pause, the Bot Service will open in the portal and display the Bot Service editor, as pictured below. Behind the scenes, the bot has been registered, an Azure Web App has been created to host it, and the bot has been connected to Microsoft QnA Maker.</p>
<p><a href="Images/portal-editor-new.png" target="_blank"><img src="Images/portal-editor-new.png" alt="The Bot Service editor" style="max-width:100%;"></a></p>
<p><em>The Bot Service editor</em></p>
</li>
<li>
<p>To make sure these services can communicate with each other, you can test bot communication in the Azure Bot Service editor. To test, type the word "hi" (without quotation marks) into the chat window on the right side of the page. Then press <strong>Enter</strong> or click the paper-airplane icon.</p>
<p><a href="Images/portal-send-chat-test.png" target="_blank"><img src="Images/portal-send-chat-test.png" alt="Testing bot communication" style="max-width:100%;"></a></p>
<p><em>Testing bot communication</em></p>
</li>
<li>
<p>Wait for the bot to respond with the word "hello," indicating your bot is configured and ready to go.</p>
<p><a href="Images/portal-test-chat.png" target="_blank"><img src="Images/portal-test-chat.png" alt="Chatting with your bot" style="max-width:100%;"></a></p>
<p><em>Chatting with your bot</em></p>
</li>
</ol>
<p>With the Bot Service deployed and configured, the next step is to update the Microsoft QnA Maker service that the bot is connected to.</p>
<p><a name="Exercise2"></a></p>
<h2>Exercise 2: Get started with Microsoft QnA Maker</h2>
<p><a href="https://qnamaker.ai/">Microsoft QnA Maker</a> is part of <a href="https://www.microsoft.com/cognitive-services/">Microsoft Cognitive Services</a>, which is a suite of APIs for building intelligent apps. Rather than infuse a bot with intelligence by writing code that tries to anticipate every question a user might ask and provide a response, you can connect it to a knowledge base of questions and answers created with QnA Maker. A common usage scenario is to create a knowledge base from a FAQ so the bot can answer domain-specific questions such as "How do I find my Windows product key" or "Where can I download Visual Studio Code?"</p>
<p>In this exercise, you will use the QnA Maker portal to edit the knowledge base that was created when you connected the bot to QnA Maker. That knowledge base currently contains a single question and answer: "hi" and "hello." You will edit the response and then, in <a href="#Exercise3">Exercise 3</a>, populate the knowledge base with additional questions and answers.</p>
<ol>
<li>
<p>Open the <a href="https://qnamaker.ai/">Microsoft QnA Maker portal</a> in your browser. If you are not signed in, click <strong>Sign in</strong> in the upper-right corner and sign in with your Microsoft account. If you are presented with a terms agreement, check the <strong>I agree</strong> box and continue.</p>
<p><a href="Images/qna-click-signin.png" target="_blank"><img src="Images/qna-click-signin.png" alt="Signing in to QnA Maker" style="max-width:100%;"></a></p>
<p><em>Signing in to QnA Maker</em></p>
</li>
<li>
<p>Ensure that <strong>My services</strong> is selected at the top. Then click the pencil icon.</p>
<p><a href="Images/qna-click-edit-icon.png" target="_blank"><img src="Images/qna-click-edit-icon.png" alt="Editing a QnA service" style="max-width:100%;"></a></p>
<p><em>Editing a QnA service</em></p>
</li>
<li>
<p>Click <strong>Settings</strong>. Replace the value in the <strong>Service name</strong> box with "QnA Factbot" (without quotation marks). Then click <strong>Save and retrain</strong> to save the change.</p>
<p><a href="Images/qna-save-service-name.png" target="_blank"><img src="Images/qna-save-service-name.png" alt="Updating the service name" style="max-width:100%;"></a></p>
<p><em>Updating the service name</em></p>
</li>
<li>
<p>Click <strong>Knowledge Base</strong>.</p>
<p><a href="Images/qna-select-kb-tab.png" target="_blank"><img src="Images/qna-select-kb-tab.png" alt="Opening the Knowledge Base page" style="max-width:100%;"></a></p>
<p><em>Opening the Knowledge Base page</em></p>
</li>
<li>
<p>Replace "hello" in the Answer column with "Welcome to the QnA Factbot!" Then click <strong>Save and retrain</strong> to save the change.</p>
<p><a href="Images/qna-update-default-answer.png" target="_blank"><img src="Images/qna-update-default-answer.png" alt="Updating a response" style="max-width:100%;"></a></p>
<p><em>Updating a response</em></p>
</li>
<li>
<p>Click <strong>Test</strong>.</p>
<p><a href="Images/qna-select-test-tab.png" target="_blank"><img src="Images/qna-select-test-tab.png" alt="Opening the Test page" style="max-width:100%;"></a></p>
<p><em>Opening the Test page</em></p>
</li>
<li>
<p>Type "hi" into the box at the bottom of the chat window and press <strong>Enter</strong>. Confirm that the bot responds with "Welcome to the QnA Factbot!"</p>
<p><a href="Images/qna-updated-chat-response.png" target="_blank"><img src="Images/qna-updated-chat-response.png" alt="Chatting with the bot" style="max-width:100%;"></a></p>
<p><em>Chatting with the bot</em></p>
</li>
</ol>
<p>This is a great start, but a simple reply to the greeting "hi" doesn't demonstrate a lot of value. To give your bot some meaningful content to work with, the next step is to populate the knowledge base with additional questions and answers.</p>
<p><a name="Exercise3"></a></p>
<h2>Exercise 3: Expand the QnA Maker knowledge base</h2>
<p>You can enter questions and answers into a QnA Maker knowledge base manually, or you can import them from a variety of sources, including Web sites and local text files. In this exercise, you will use both of these techniques to populate the knowledge base with questions and answers and then publish the updated knowledge base for your bot to use.</p>
<ol>
<li>
<p>Click <strong>Settings</strong> to the return to the Settings page in the <a href="https://qnamaker.ai/">Microsoft QnA Maker portal</a>.</p>
<p><a href="Images/qna-select-settings-tab.png" target="_blank"><img src="Images/qna-select-settings-tab.png" alt="Opening the Settings page" style="max-width:100%;"></a></p>
<p><em>Opening the Settings page</em></p>
</li>
<li>
<p>Paste the following URL into the <strong>URLs</strong> box:</p>
<pre><code>https://traininglabservices.azurewebsites.net/help/faqs.html
</code></pre>
</li>
<li>
<p>Click <strong>Save and retrain</strong> to populate the knowledge base with questions and answers from the Web site whose URL you provided.</p>
<p><a href="Images/qna-add-faq-url.png" target="_blank"><img src="Images/qna-add-faq-url.png" alt="Importing questions and answers from a URL" style="max-width:100%;"></a></p>
<p><em>Importing questions and answers from a URL</em></p>
</li>
<li>
<p>Click <strong>Knowledge Base</strong> and confirm that six new questions and answers were added. Then click <strong>Save and retrain</strong> to save the changes.</p>
<p><a href="Images/qna-updated-kb-01.png" target="_blank"><img src="Images/qna-updated-kb-01.png" alt="The updated knowledge base" style="max-width:100%;"></a></p>
<p><em>The updated knowledge base</em></p>
</li>
<li>
<p>Click <strong>Test</strong> to return to the Test page. Type "What's the largest city in the world?" into the box at the bottom of the chat window and press <strong>Enter</strong>. Confirm that the bot responds as shown below.</p>
<p><a href="Images/qna-test-largest-city.png" target="_blank"><img src="Images/qna-test-largest-city.png" alt="Testing the updated knowledge base" style="max-width:100%;"></a></p>
<p><em>Testing the updated knowledge base</em></p>
</li>
<li>
<p>The knowledge base only contains a few questions and answers, but can easily be updated to include more. You can even import questions and answers stored in text files on your computer. To demonstrate, click <strong>Replace Knowledge Base</strong> in the upper-left corner of the portal.</p>
<p><a href="Images/qna-click-replace-kb.png" target="_blank"><img src="Images/qna-click-replace-kb.png" alt="Replacing the knowledge base" style="max-width:100%;"></a></p>
<p><em>Replacing the knowledge base</em></p>
</li>
<li>
<p>Browse to the "Resources" folder included with this lab and select the text file named <strong>Final QnA.txt</strong>. Click <strong>OK</strong> when prompted to confirm that importing this file will overwrite existing questions and answers.</p>
</li>
<li>
<p>Click <strong>Knowledge Base</strong> and confirm that 14 new questions and answers appear in the knowledge base. (The six you imported from the URL are still there, despite the fact that you were warned that they would be overwritten.) Then click <strong>Save and retrain</strong> to save the changes.</p>
<p><a href="Images/qna-updated-kb-02.png" target="_blank"><img src="Images/qna-updated-kb-02.png" alt="The updated knowledge base" style="max-width:100%;"></a></p>
<p><em>The updated knowledge base</em></p>
</li>
<li>
<p>Click <strong>Test</strong> to return to the Test page. Type "What book has sold the most copies?" into the box at the bottom of the chat window and press <strong>Enter</strong>. Confirm that the bot responds as shown below.</p>
<p><a href="Images/qna-test-book.png" target="_blank"><img src="Images/qna-test-book.png" alt="Chatting with the bot" style="max-width:100%;"></a></p>
<p><em>Chatting with the bot</em></p>
</li>
<li>
<p>The knowledge base now contains 20 questions and answers, but an invalid character is present in the answer in row 7. To remove the character, click <strong>Knowledge Base</strong> to return to the Knowledge Base page. Locate the invalid character in row 7 between the words "most" and "Emmys," and replace it with a space character. Then click <strong>Save and retrain</strong>.</p>
<p><a href="Images/qna-invalid-char.png" target="_blank"><img src="Images/qna-invalid-char.png" alt="Editing answer #7" style="max-width:100%;"></a></p>
<p><em>Editing answer #7</em></p>
</li>
<li>
<p>Click <strong>Publish</strong> to publish the changes to the knowledge base.</p>
<p><a href="Images/qna-click-publish.png" target="_blank"><img src="Images/qna-click-publish.png" alt="Publishing the knowledge base" style="max-width:100%;"></a></p>
<p><em>Publishing the knowledge base</em></p>
</li>
<li>
<p>Review the changes and click <strong>Publish</strong>. After a brief pause, you should be notified that the service has been deployed.</p>
<p><a href="Images/qna-review-publishing-changes.png" target="_blank"><img src="Images/qna-review-publishing-changes.png" alt="Reviewing changes" style="max-width:100%;"></a></p>
<p><em>Reviewing changes</em></p>
</li>
</ol>
<p>With a sample knowledge base deployed, it is now time to lend attention to the bot itself.</p>
<p><a name="Exercise4"></a></p>
<h2>Exercise 4: Deploy the bot and set up continuous integration</h2>
<p>When you deployed a Bot Service in <a href="#Exercise1">Exercise 1</a>, an Azure Web App was created to host the bot. But the bot still needs to be written and deployed to the Azure Web app. In this exercise, you will code the bot using source code generated for you by QnA Maker. Then you will create a local Git repository for the code, connect it to the Azure Web App, and publish the bot to Azure, all using Visual Studio Code.</p>
<ol>
<li>
<p>If you haven't installed Visual Studio Code, take a moment to do so now. You can download Visual Studio Code from <a href="http://code.visualstudio.com">http://code.visualstudio.com</a>. You should also install <a href="https://nodejs.org">Node.js</a> and <a href="https://git-scm.com/downloads">Git Client</a> if they aren't already installed. All of these products work cross-platform and can be installed on Windows, macOS, or Linux.</p>
<blockquote>
<p>An easy way to determine whether Node.js is installed is to open a terminal window or Command Prompt window and execute a <strong>node -v</strong> command. If the Node.js version number is displayed, then Node.js is installed.</p>
</blockquote>
</li>
<li>
<p>Return to the Azure Portal and open the Bot Service you created in <a href="#Exercise1">Exercise 1</a> if it isn't already open.</p>
<p><a href="Images/portal-click-bot-service.png" target="_blank"><img src="Images/portal-click-bot-service.png" alt="Opening the Bot Service" style="max-width:100%;"></a></p>
<p><em>Opening the Bot Service</em></p>
</li>
<li>
<p>Click <strong>Settings</strong>, and then click <strong>Configure</strong>.</p>
<p><a href="Images/portal-expand-configure.png" target="_blank"><img src="Images/portal-expand-configure.png" alt="Configuring continuous integration" style="max-width:100%;"></a></p>
<p><em>Configuring continuous integration</em></p>
</li>
<li>
<p>Click the link to the zip file containing source code. Once the download is complete, unzip the zip file and copy its contents to the local folder of your choice.</p>
<p><a href="Images/portal-click-download-source.png" target="_blank"><img src="Images/portal-click-download-source.png" alt="Downloading the source code" style="max-width:100%;"></a></p>
<p><em>Downloading the source code</em></p>
</li>
<li>
<p>Scroll down the page and click the <strong>Open</strong> button to the right of "Advanced Settings."</p>
<p><a href="Images/portal-open-advanced-settings.png" target="_blank"><img src="Images/portal-open-advanced-settings.png" alt="Opening advanced settings" style="max-width:100%;"></a></p>
<p><em>Opening advanced settings</em></p>
</li>
<li>
<p>Click <strong>Deployment credentials</strong>.</p>
<p><a href="Images/portal-select-deployment-credentials.png" target="_blank"><img src="Images/portal-select-deployment-credentials.png" alt="Viewing deployment credentials" style="max-width:100%;"></a></p>
<p><em>Viewing deployment credentials</em></p>
</li>
<li>
<p>Enter a user name such as "BotAdministrator" (you will probably have to enter a different user name since these must be unique within Azure) and enter "Password_1" as the password. Click <strong>Save</strong> to save your changes. Then close the blade by clicking the <strong>x</strong> in the upper-right corner.</p>
<p><a href="Images/portal-enter-ci-creds.png" target="_blank"><img src="Images/portal-enter-ci-creds.png" alt="Entering deployment credentials" style="max-width:100%;"></a></p>
<p><em>Entering deployment credentials</em></p>
</li>
<li>
<p>Click <strong>Set up integration source</strong>.</p>
<p><a href="Images/portal-click-set-source.png" target="_blank"><img src="Images/portal-click-set-source.png" alt="Setting up an integration source" style="max-width:100%;"></a></p>
<p><em>Setting up an integration source</em></p>
</li>
<li>
<p>Click <strong>Setup</strong>, followed by <strong>Choose Source</strong>.</p>
<p><a href="Images/portal-select-source.png" target="_blank"><img src="Images/portal-select-source.png" alt="Choosing a deployment source" style="max-width:100%;"></a></p>
<p><em>Choosing a deployment source</em></p>
</li>
<li>
<p>Select <strong>Local Git Repository</strong> as the deployment source, and then click <strong>OK</strong>.</p>
<p><a href="Images/portal-set-local-git.png" target="_blank"><img src="Images/portal-set-local-git.png" alt="Specifying a local Git repository as the deployment source" style="max-width:100%;"></a></p>
<p><em>Specifying a local Git repository as the deployment source</em></p>
</li>
<li>
<p>Start Visual Studio Code. Select <strong>Open Folder</strong> from the <strong>File</strong> menu and browse to the folder to which you copied the contents of the zip file downloaded in Step 4. Then select the "messages" folder and click <strong>Select Folder</strong>.</p>
<p><a href="Images/fe-select-messages-folder.png" target="_blank"><img src="Images/fe-select-messages-folder.png" alt="Selecting the "messages" folder" style="max-width:100%;"></a></p>
<p><em>Selecting the "messages" folder</em></p>
</li>
<li>
<p>Click the <strong>Git</strong> button in the View Bar on the left side of Visual Studio Code, and then click <strong>Initialize Git Repository</strong>. This will initialize a local Git repository for the project.</p>
<p><a href="Images/vs-init-git-repo.png" target="_blank"><img src="Images/vs-init-git-repo.png" alt="Initializing a local Git repository" style="max-width:100%;"></a></p>
<p><em>Initializing a local Git repository</em></p>
</li>
<li>
<p>Type "First commit" into the message box, and then click the check mark to commit your changes.</p>
<p><a href="Images/vs-first-git-commit.png" target="_blank"><img src="Images/vs-first-git-commit.png" alt="Committing changes to the local Git repository" style="max-width:100%;"></a></p>
<p><em>Committing changes to the local Git repository</em></p>
</li>
<li>
<p>Use Visual Studio Code's <strong>View -> Integrated Terminal</strong> command to open an integrated terminal window. Execute the following command in the integrated terminal, replacing "BOT_APP_NAME" in two places with the name of the Bot Service you entered in <a href="#Exercise1">Exercise 1</a>, Step 3.</p>
<pre><code>git remote add qnafactbot https://BOT_APP_NAME.scm.azurewebsites.net:443/BOT_APP_NAME.git
</code></pre>
</li>
<li>
<p>Select <strong>Command Palette</strong> from the <strong>View</strong> menu to open Visual Studio Code's command palette. Then type "git pub" into the command palette and select <strong>Git: Publish</strong> to publish the bot code to Azure.</p>
<p><a href="Images/vs-select-git-publish.png" target="_blank"><img src="Images/vs-select-git-publish.png" alt="Publishing the bot" style="max-width:100%;"></a></p>
<p><em>Publishing the bot</em></p>
</li>
<li>
<p>If prompted to confirm that you want to publish, click <strong>Publish</strong>.</p>
<p><a href="Images/vs-confirm-publish.png" target="_blank"><img src="Images/vs-confirm-publish.png" alt="Confirming Git publishing" style="max-width:100%;"></a></p>
<p><em>Confirming Git publishing</em></p>
</li>
<li>
<p>If prompted for credentials, enter the user name and password ("Password_1") you specified in Step 7 of this exercise.</p>
<p><a href="Images/vs-enter-git-creds.png" target="_blank"><img src="Images/vs-enter-git-creds.png" alt="Entering deployment credentials" style="max-width:100%;"></a></p>
<p><em>Entering deployment credentials</em></p>
</li>
<li>
<p>Wait until your bot code has been published. A clock will appear over the Git button in the View Bar while publishing is in progress, and disappear when publishing is complete.</p>
<p><a href="Images/vs-git-delay-icon.png" target="_blank"><img src="Images/vs-git-delay-icon.png" alt="The Git publishing indicator" style="max-width:100%;"></a></p>
<p><em>The Git publishing indicator</em></p>
</li>
</ol>
<p>In this exercise, you created a project for your bot in Visual Studio Code and set up continuous integration using Git to simplify publishing code changes. Your bot has been published to Azure and it's time to see it in action and learn how to debug it in Visual Studio Code.</p>
<p><a name="Exercise5"></a></p>
<h2>Exercise 5: Debug the bot locally</h2>
<p>As with any application code that you write, changes to bot code need to be tested and debugged locally before being deployed to production. To help debug bots, Microsoft offers the <a href="https://emulator.botframework.com/">Bot Framework Emulator</a>. In this exercise, you will learn how to use Visual Studio Code and the Bot Framework Emulator to debug your bots.</p>
<ol>
<li>
<p>If you haven't installed the Microsoft Bot Framework Emulator, take a moment to do so now. You can download it from <a href="https://emulator.botframework.com/">https://emulator.botframework.com/</a>.</p>
</li>
<li>
<p>Click the <strong>Explorer</strong> button in Visual Studio Code's View Bar. Then select <strong>index.js</strong> to open it in the code editor. This file contains the code that drives the bot — code that was generated by QnA Maker and downloaded from the QnA Maker portal.</p>
<p><a href="Images/vs-select-index-js.png" target="_blank"><img src="Images/vs-select-index-js.png" alt="Opening index.js" style="max-width:100%;"></a></p>
<p><em>Opening index.js</em></p>
</li>
<li>
<p>Replace the contents of <strong>index.js</strong> with the following code:</p>
<div class="highlight highlight-source-js"><pre><span class="pl-s"><span class="pl-pds">"</span>use strict<span class="pl-pds">"</span></span>;
<span class="pl-k">var</span> builder <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>botbuilder<span class="pl-pds">"</span></span>);
<span class="pl-k">var</span> botbuilder_azure <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>botbuilder-azure<span class="pl-pds">"</span></span>);
<span class="pl-k">var</span> useEmulator <span class="pl-k">=</span> (<span class="pl-c1">process</span>.<span class="pl-smi">env</span>.<span class="pl-c1">NODE_ENV</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>development<span class="pl-pds">'</span></span>);
<span class="pl-k">var</span> connector <span class="pl-k">=</span> useEmulator <span class="pl-k">?</span> <span class="pl-k">new</span> <span class="pl-en">builder.ChatConnector</span>() <span class="pl-k">:</span> <span class="pl-k">new</span> <span class="pl-en">botbuilder_azure.BotServiceConnector</span>({
appId<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>MicrosoftAppId<span class="pl-pds">'</span></span>],
appPassword<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>MicrosoftAppPassword<span class="pl-pds">'</span></span>],
stateEndpoint<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>BotStateEndpoint<span class="pl-pds">'</span></span>],
openIdMetadata<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>BotOpenIdMetadata<span class="pl-pds">'</span></span>]
});
<span class="pl-k">var</span> bot <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">builder.UniversalBot</span>(connector);
<span class="pl-smi">bot</span>.<span class="pl-en">dialog</span>(<span class="pl-s"><span class="pl-pds">'</span>/<span class="pl-pds">'</span></span>, [
<span class="pl-k">function</span> (<span class="pl-smi">session</span>) {
<span class="pl-smi">builder</span>.<span class="pl-smi">Prompts</span>.<span class="pl-c1">text</span>(session, <span class="pl-s"><span class="pl-pds">"</span>Hello, and welcome to QnA Factbot! What's your name?<span class="pl-pds">"</span></span>);
},
<span class="pl-k">function</span> (<span class="pl-smi">session</span>, <span class="pl-smi">results</span>) {
<span class="pl-smi">session</span>.<span class="pl-smi">userData</span>.<span class="pl-c1">name</span> <span class="pl-k">=</span> <span class="pl-smi">results</span>.<span class="pl-smi">response</span>;
<span class="pl-smi">builder</span>.<span class="pl-smi">Prompts</span>.<span class="pl-en">number</span>(session, <span class="pl-s"><span class="pl-pds">"</span>Hi <span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-smi">results</span>.<span class="pl-smi">response</span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">"</span>, how many years have you been writing code?<span class="pl-pds">"</span></span>);
},
<span class="pl-k">function</span> (<span class="pl-smi">session</span>, <span class="pl-smi">results</span>) {
<span class="pl-smi">session</span>.<span class="pl-smi">userData</span>.<span class="pl-smi">yearsCoding</span> <span class="pl-k">=</span> <span class="pl-smi">results</span>.<span class="pl-smi">response</span>;
<span class="pl-smi">builder</span>.<span class="pl-smi">Prompts</span>.<span class="pl-en">choice</span>(session, <span class="pl-s"><span class="pl-pds">"</span>What language do you love the most?<span class="pl-pds">"</span></span>, [<span class="pl-s"><span class="pl-pds">"</span>C#<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>JavaScript<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>TypeScript<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>Visual FoxPro<span class="pl-pds">"</span></span>]);
},
<span class="pl-k">function</span> (<span class="pl-smi">session</span>, <span class="pl-smi">results</span>) {
<span class="pl-smi">session</span>.<span class="pl-smi">userData</span>.<span class="pl-c1">language</span> <span class="pl-k">=</span> <span class="pl-smi">results</span>.<span class="pl-smi">response</span>.<span class="pl-smi">entity</span>;
<span class="pl-smi">session</span>.<span class="pl-c1">send</span>(<span class="pl-s"><span class="pl-pds">"</span>Okay, <span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-smi">session</span>.<span class="pl-smi">userData</span>.<span class="pl-c1">name</span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">"</span>, I think I've got it:<span class="pl-pds">"</span></span> <span class="pl-k">+</span>
<span class="pl-s"><span class="pl-pds">"</span> You've been writing code for <span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-smi">session</span>.<span class="pl-smi">userData</span>.<span class="pl-smi">yearsCoding</span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">"</span> years,<span class="pl-pds">"</span></span> <span class="pl-k">+</span>
<span class="pl-s"><span class="pl-pds">"</span> and prefer to use <span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-smi">session</span>.<span class="pl-smi">userData</span>.<span class="pl-c1">language</span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">"</span>.<span class="pl-pds">"</span></span>);
}]);
<span class="pl-k">if</span> (useEmulator) {
<span class="pl-k">var</span> restify <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">'</span>restify<span class="pl-pds">'</span></span>);
<span class="pl-k">var</span> server <span class="pl-k">=</span> <span class="pl-smi">restify</span>.<span class="pl-en">createServer</span>();
<span class="pl-smi">server</span>.<span class="pl-en">listen</span>(<span class="pl-c1">3978</span>, <span class="pl-k">function</span>() {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">'</span>test bot endpoint at http://localhost:3978/api/messages<span class="pl-pds">'</span></span>);
});
<span class="pl-smi">server</span>.<span class="pl-en">post</span>(<span class="pl-s"><span class="pl-pds">'</span>/api/messages<span class="pl-pds">'</span></span>, <span class="pl-smi">connector</span>.<span class="pl-en">listen</span>());
} <span class="pl-k">else</span> {
<span class="pl-c1">module</span>.<span class="pl-smi">exports</span> <span class="pl-k">=</span> { default<span class="pl-k">:</span> <span class="pl-smi">connector</span>.<span class="pl-en">listen</span>() }
}
</pre></div>
</li>
<li>
<p>Note the Bot Builder prompts on lines 19, 25, and 31. Set a breakpoint on each of these lines by clicking in the margin on the left.</p>
<p><a href="Images/vs-add-breakpoints.png" target="_blank"><img src="Images/vs-add-breakpoints.png" alt="Adding breakpoints to index.js" style="max-width:100%;"></a></p>
<p><em>Adding breakpoints to index.js</em></p>
</li>
<li>
<p>Click the <strong>Debug</strong> button in the View Bar, and then click the green arrow to start a debugging session. Observe that "test bot endpoint at <a href="http://localhost:3978/api/messages">http://localhost:3978/api/messages</a>" appears in the debug console.</p>
<p><a href="Images/vs-launch-debugger.png" target="_blank"><img src="Images/vs-launch-debugger.png" alt="Launching the debugger" style="max-width:100%;"></a></p>
<p><em>Launching the debugger</em></p>
</li>
<li>
<p>Your bot code is now running locally. Launch the Bot Framework Emulator and type the following URL into the box at the top of the window:</p>
<pre><code>http://localhost:3978/api/messages
</code></pre>
</li>
<li>
<p>Leave <strong>Microsoft App ID</strong> and <strong>Microsoft App Password</strong> blank for now, and click <strong>CONNECT</strong> to connect the emulator to the debugging session.</p>
<p><a href="Images/emulator-connect.png" target="_blank"><img src="Images/emulator-connect.png" alt="Connecting the emulator to the debugging session" style="max-width:100%;"></a></p>
<p><em>Connecting the emulator to the debugging session</em></p>
</li>
<li>
<p>Type "Hi" (without quotation marks) into the box at the bottom of the emulator and press <strong>Enter</strong>. Visual Studio Code will break on line 19 of <strong>index.js</strong>.</p>
<p><a href="Images/emulator-step-01.png" target="_blank"><img src="Images/emulator-step-01.png" alt="Chatting with the bot" style="max-width:100%;"></a></p>
<p><em>Chatting with the bot</em></p>
</li>
<li>
<p>Click the <strong>Continue</strong> button in Visual Studio Code's debugging toolbar and return to the emulator to see the bot's response.</p>
<p><a href="Images/vs-click-continue.png" target="_blank"><img src="Images/vs-click-continue.png" alt="Continuing in the debugger" style="max-width:100%;"></a></p>
<p><em>Continuing in the debugger</em></p>
</li>
<li>
<p>Continue through the guided bot conversation, answering each question and clicking <strong>Continue</strong> in Visual Studio Code each time a breakpoint is hit.</p>
<p><a href="Images/emulator-complete-convo.png" target="_blank"><img src="Images/emulator-complete-convo.png" alt="A guided bot conversation" style="max-width:100%;"></a></p>
<p><em>A guided bot conversation</em></p>
</li>
<li>
<p>Click the <strong>Stop</strong> button in Visual Studio Code's debugging toolbar to end the debugging session.</p>
</li>
</ol>
<p>At this point, you have a fully functioning bot and know how to debug it by launching it in the debugger in Visual Studio Code and connecting to the debugging session from the Microsoft Bot Emulator. The next step is to make the bot more intelligent by connecting it to the knowledge base you deployed in <a href="#Exercise3">Exercise 3</a>.</p>
<p><a name="Exercise6"></a></p>
<h2>Exercise 6: Connect the bot to the knowledge base</h2>
<p>In this exercise, you will connect your bot to the QnA Maker knowledge base you built earlier so the bot can converse more intelligently. This involves retrieving a couple of keys from the Azure Portal, copying them into a configuration file in the bot project, and redeploying the bot to Azure.</p>
<ol>
<li>
<p>In Visual Studio Code, click the <strong>Explorer</strong> button and select <strong>index.js</strong> if it isn't already selected.</p>
<p><a href="Images/vs-reopen-index-js.png" target="_blank"><img src="Images/vs-reopen-index-js.png" alt="Opening index.js" style="max-width:100%;"></a></p>
<p><em>Opening index.js</em></p>
</li>
<li>
<p>Click the <strong>Debug</strong> button in the View Bar. Then click the <strong>Remove All Breakpoints</strong> icon to clear the breakpoints you added earlier.</p>
<p><a href="Images/vs-remove-breakpoint.png" target="_blank"><img src="Images/vs-remove-breakpoint.png" alt="Removing all breakpoints" style="max-width:100%;"></a></p>
<p><em>Removing all breakpoints</em></p>
</li>
<li>
<p>Replace the contents of <strong>index.js</strong> with the following code:</p>
<div class="highlight highlight-source-js"><pre><span class="pl-c"><span class="pl-c">//</span> For more information about this template visit http://aka.ms/azurebots-node-qnamaker</span>
<span class="pl-s"><span class="pl-pds">"</span>use strict<span class="pl-pds">"</span></span>;
<span class="pl-k">var</span> builder <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>botbuilder<span class="pl-pds">"</span></span>);
<span class="pl-k">var</span> botbuilder_azure <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>botbuilder-azure<span class="pl-pds">"</span></span>);
<span class="pl-k">var</span> builder_cognitiveservices <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>botbuilder-cognitiveservices<span class="pl-pds">"</span></span>);
<span class="pl-k">var</span> useEmulator <span class="pl-k">=</span> (<span class="pl-c1">process</span>.<span class="pl-smi">env</span>.<span class="pl-c1">NODE_ENV</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>development<span class="pl-pds">'</span></span>);
<span class="pl-k">var</span> connector <span class="pl-k">=</span> useEmulator <span class="pl-k">?</span> <span class="pl-k">new</span> <span class="pl-en">builder.ChatConnector</span>() <span class="pl-k">:</span> <span class="pl-k">new</span> <span class="pl-en">botbuilder_azure.BotServiceConnector</span>({
appId<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>MicrosoftAppId<span class="pl-pds">'</span></span>],
appPassword<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>MicrosoftAppPassword<span class="pl-pds">'</span></span>],
stateEndpoint<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>BotStateEndpoint<span class="pl-pds">'</span></span>],
openIdMetadata<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>[<span class="pl-s"><span class="pl-pds">'</span>BotOpenIdMetadata<span class="pl-pds">'</span></span>]
});
<span class="pl-k">var</span> bot <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">builder.UniversalBot</span>(connector);
<span class="pl-k">var</span> recognizer <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">builder_cognitiveservices.QnAMakerRecognizer</span>({
knowledgeBaseId<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>.<span class="pl-smi">QnAKnowledgebaseId</span>,
subscriptionKey<span class="pl-k">:</span> <span class="pl-c1">process</span>.<span class="pl-smi">env</span>.<span class="pl-smi">QnASubscriptionKey</span>});
<span class="pl-k">var</span> basicQnAMakerDialog <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">builder_cognitiveservices.QnAMakerDialog</span>({
recognizers<span class="pl-k">:</span> [recognizer],
defaultMessage<span class="pl-k">:</span> <span class="pl-s"><span class="pl-pds">'</span>No match! Try changing the query terms!<span class="pl-pds">'</span></span>,
qnaThreshold<span class="pl-k">:</span> <span class="pl-c1">0.3</span>}
);
<span class="pl-smi">bot</span>.<span class="pl-en">dialog</span>(<span class="pl-s"><span class="pl-pds">'</span>/<span class="pl-pds">'</span></span>, basicQnAMakerDialog);
<span class="pl-k">if</span> (useEmulator) {
<span class="pl-k">var</span> restify <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">'</span>restify<span class="pl-pds">'</span></span>);
<span class="pl-k">var</span> server <span class="pl-k">=</span> <span class="pl-smi">restify</span>.<span class="pl-en">createServer</span>();
<span class="pl-smi">server</span>.<span class="pl-en">listen</span>(<span class="pl-c1">3978</span>, <span class="pl-k">function</span>() {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">'</span>test bot endpoint at http://localhost:3978/api/messages<span class="pl-pds">'</span></span>);
});
<span class="pl-smi">server</span>.<span class="pl-en">post</span>(<span class="pl-s"><span class="pl-pds">'</span>/api/messages<span class="pl-pds">'</span></span>, <span class="pl-smi">connector</span>.<span class="pl-en">listen</span>());
} <span class="pl-k">else</span> {
<span class="pl-c1">module</span>.<span class="pl-smi">exports</span> <span class="pl-k">=</span> { default<span class="pl-k">:</span> <span class="pl-smi">connector</span>.<span class="pl-en">listen</span>() }
}</pre></div>
</li>
<li>
<p>Observe the call to <em>QnAMakerDialog</em> on line 23. This creates a dialog that integrates a bot built with the Microsoft Bot Framework with a knowledge base built Microsoft QnA Maker.</p>
<p><a href="Images/vs-using-qnamaker.png" target="_blank"><img src="Images/vs-using-qnamaker.png" alt="Creating a QnAMakerDialog" style="max-width:100%;"></a></p>
<p><em>Creating a QnAMakerDialog</em></p>
</li>
<li>
<p>Expand the <strong>.vscode</strong> folder in Explorer and select <strong>launch.json</strong> to open it for editing. Note the empty-string values for "QnAKnowledgebaseId" and "QnASubscriptionKey." To connect the bot to the knowledge base, you must replace the empty strings with a pair of keys generated by the Bot Service.</p>
<p><a href="Images/vs-launch-file.png" target="_blank"><img src="Images/vs-launch-file.png" alt="Opening launch.json" style="max-width:100%;"></a></p>
<p><em>Opening launch.json</em></p>
</li>
<li>
<p>Return to the Azure Portal and open your Bot Service if it isn't already open. Then click the <strong>Settings</strong> tab.</p>
<p><a href="Images/portal-select-settings.png" target="_blank"><img src="Images/portal-select-settings.png" alt="Opening the Settings page" style="max-width:100%;"></a></p>
<p><em>Opening the Settings page</em></p>
</li>
<li>
<p>Click <strong>Open</strong> to the right of "Application settings."</p>
<p><a href="Images/portal-open-app-settings.png" target="_blank"><img src="Images/portal-open-app-settings.png" alt="Viewing application settings" style="max-width:100%;"></a></p>
<p><em>Viewing application settings</em></p>
</li>
<li>
<p>Scroll down until you find the application setting named "QnAKnowledgebaseId" and copy its value to the clipboard.</p>
<p><a href="Images/portal-app-setting-01.png" target="_blank"><img src="Images/portal-app-setting-01.png" alt="Copying the knowledge-base ID" style="max-width:100%;"></a></p>
<p><em>Copying the knowledge-base ID</em></p>
</li>
<li>
<p>Return to Visual Studio Code and paste the value on the clipboard into the value for "QnAKnowledgebaseId."</p>
<p><a href="Images/vs-updated-key-01.png" target="_blank"><img src="Images/vs-updated-key-01.png" alt="Updating "QnAKnowledgebaseId" in launch.json" style="max-width:100%;"></a></p>
<p><em>Updating "QnAKnowledgebaseId" in launch.json</em></p>
</li>
<li>