├── .gitattributes ├── .gitignore ├── AI-engine ├── config_mitie.json ├── config_spacy.json ├── data │ ├── demo-rasa.json │ └── sitebot-data.json └── rasa_nlu_log.json ├── bot-application ├── app.py ├── extract.py ├── getSchedule.py ├── local_settings.py ├── models.py ├── response.py ├── static │ ├── css │ │ ├── chat_interface.css │ │ ├── style.css │ │ ├── style.css~ │ │ └── temporary.css │ └── js │ │ ├── bind.js │ │ └── jquery.timeago.js └── templates │ ├── base.html │ └── home.html ├── readme.md └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | static/* linguist-vendored 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | AI-engine/logs/* 3 | AI-engine/model_* 4 | bot-application/migrations 5 | *.db 6 | *.dat 7 | venv 8 | .idea 9 | models 10 | -------------------------------------------------------------------------------- /AI-engine/config_mitie.json: -------------------------------------------------------------------------------- 1 | { 2 | "backend": "mitie", 3 | "mitie_file": "data/total_word_feature_extractor.dat", 4 | "path" : "./", 5 | "data" : "data/sitebot-data.json", 6 | "num_threads":100, 7 | "pipeline": "mitie" 8 | } 9 | -------------------------------------------------------------------------------- /AI-engine/config_spacy.json: -------------------------------------------------------------------------------- 1 | { 2 | "backend": "spacy_sklearn", 3 | "path" : "./", 4 | "data" : "data/sitebot-data.json", 5 | "num_threads":100, 6 | "pipeline":"spacy_sklearn" 7 | } 8 | -------------------------------------------------------------------------------- /AI-engine/data/demo-rasa.json: -------------------------------------------------------------------------------- 1 | { 2 | "rasa_nlu_data": { 3 | "entity_examples": [ 4 | { 5 | "text": "hey", 6 | "intent": "greet", 7 | "entities": [] 8 | }, 9 | { 10 | "text": "howdy", 11 | "intent": "greet", 12 | "entities": [] 13 | }, 14 | { 15 | "text": "hey there", 16 | "intent": "greet", 17 | "entities": [] 18 | }, 19 | { 20 | "text": "hello", 21 | "intent": "greet", 22 | "entities": [] 23 | }, 24 | { 25 | "text": "hi", 26 | "intent": "greet", 27 | "entities": [] 28 | }, 29 | { 30 | "text": "i'm looking for a place to eat", 31 | "intent": "restaurant_search", 32 | "entities": [] 33 | }, 34 | { 35 | "text": "i'm looking for a place in the north of town", 36 | "intent": "restaurant_search", 37 | "entities": [ 38 | { 39 | "start": 31, 40 | "end": 36, 41 | "value": "north", 42 | "entity": "location" 43 | } 44 | ] 45 | }, 46 | { 47 | "text": "show me chinese restaurants", 48 | "intent": "restaurant_search", 49 | "entities": [ 50 | { 51 | "start": 8, 52 | "end": 15, 53 | "value": "chinese", 54 | "entity": "cuisine" 55 | } 56 | ] 57 | }, 58 | { 59 | "text": "yes", 60 | "intent": "affirm", 61 | "entities": [] 62 | }, 63 | { 64 | "text": "yep", 65 | "intent": "affirm", 66 | "entities": [] 67 | }, 68 | { 69 | "text": "yeah", 70 | "intent": "affirm", 71 | "entities": [] 72 | }, 73 | { 74 | "text": "show me a mexican place in the centre", 75 | "intent": "restaurant_search", 76 | "entities": [ 77 | { 78 | "start": 31, 79 | "end": 37, 80 | "value": "centre", 81 | "entity": "location" 82 | }, 83 | { 84 | "start": 10, 85 | "end": 17, 86 | "value": "mexican", 87 | "entity": "cuisine" 88 | } 89 | ] 90 | }, 91 | { 92 | "text": "bye", 93 | "intent": "goodbye", 94 | "entities": [] 95 | }, 96 | { 97 | "text": "goodbye", 98 | "intent": "goodbye", 99 | "entities": [] 100 | }, 101 | { 102 | "text": "good bye", 103 | "intent": "goodbye", 104 | "entities": [] 105 | }, 106 | { 107 | "text": "stop", 108 | "intent": "goodbye", 109 | "entities": [] 110 | }, 111 | { 112 | "text": "end", 113 | "intent": "goodbye", 114 | "entities": [] 115 | }, 116 | { 117 | "text": "i am looking for an indian spot", 118 | "intent": "restaurant_search", 119 | "entities": [ 120 | { 121 | "start": 20, 122 | "end": 26, 123 | "value": "indian", 124 | "entity": "cuisine" 125 | } 126 | ] 127 | }, 128 | { 129 | "text": "search for restaurants", 130 | "intent": "restaurant_search", 131 | "entities": [] 132 | }, 133 | { 134 | "text": "anywhere in the west", 135 | "intent": "restaurant_search", 136 | "entities": [ 137 | { 138 | "start": 16, 139 | "end": 20, 140 | "value": "west", 141 | "entity": "location" 142 | } 143 | ] 144 | }, 145 | { 146 | "text": "central indian restaurant", 147 | "intent": "restaurant_search", 148 | "entities": [ 149 | { 150 | "start": 0, 151 | "end": 7, 152 | "value": "central", 153 | "entity": "location" 154 | }, 155 | { 156 | "start": 8, 157 | "end": 14, 158 | "value": "indian", 159 | "entity": "cuisine" 160 | } 161 | ] 162 | }, 163 | { 164 | "text": "indeed", 165 | "intent": "affirm", 166 | "entities": [] 167 | }, 168 | { 169 | "text": "that's right", 170 | "intent": "affirm", 171 | "entities": [] 172 | }, 173 | { 174 | "text": "ok", 175 | "intent": "affirm", 176 | "entities": [] 177 | }, 178 | { 179 | "text": "great", 180 | "intent": "affirm", 181 | "entities": [] 182 | } 183 | ], 184 | "intent_examples": [ 185 | { 186 | "text": "hey", 187 | "intent": "greet" 188 | }, 189 | { 190 | "text": "howdy", 191 | "intent": "greet" 192 | }, 193 | { 194 | "text": "hey there", 195 | "intent": "greet" 196 | }, 197 | { 198 | "text": "hello", 199 | "intent": "greet" 200 | }, 201 | { 202 | "text": "hi", 203 | "intent": "greet" 204 | }, 205 | { 206 | "text": "i'm looking for a place to eat", 207 | "intent": "restaurant_search" 208 | }, 209 | { 210 | "text": "i'm looking for a place in the north of town", 211 | "intent": "restaurant_search" 212 | }, 213 | { 214 | "text": "show me chinese restaurants", 215 | "intent": "restaurant_search" 216 | }, 217 | { 218 | "text": "yes", 219 | "intent": "affirm" 220 | }, 221 | { 222 | "text": "yep", 223 | "intent": "affirm" 224 | }, 225 | { 226 | "text": "yeah", 227 | "intent": "affirm" 228 | }, 229 | { 230 | "text": "show me a mexican place in the centre", 231 | "intent": "restaurant_search" 232 | }, 233 | { 234 | "text": "bye", 235 | "intent": "goodbye" 236 | }, 237 | { 238 | "text": "goodbye", 239 | "intent": "goodbye" 240 | }, 241 | { 242 | "text": "good bye", 243 | "intent": "goodbye" 244 | }, 245 | { 246 | "text": "stop", 247 | "intent": "goodbye" 248 | }, 249 | { 250 | "text": "end", 251 | "intent": "goodbye" 252 | }, 253 | { 254 | "text": "i am looking for an indian spot", 255 | "intent": "restaurant_search" 256 | }, 257 | { 258 | "text": "search for restaurants", 259 | "intent": "restaurant_search" 260 | }, 261 | { 262 | "text": "anywhere in the west", 263 | "intent": "restaurant_search" 264 | }, 265 | { 266 | "text": "central indian restaurant", 267 | "intent": "restaurant_search" 268 | }, 269 | { 270 | "text": "indeed", 271 | "intent": "affirm" 272 | }, 273 | { 274 | "text": "that's right", 275 | "intent": "affirm" 276 | }, 277 | { 278 | "text": "ok", 279 | "intent": "affirm" 280 | }, 281 | { 282 | "text": "great", 283 | "intent": "affirm" 284 | } 285 | ] 286 | } 287 | } -------------------------------------------------------------------------------- /AI-engine/data/sitebot-data.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "rasa_nlu_data": { 4 | "common_examples": [ 5 | { 6 | "text": "who are you?", 7 | "intent": "intro", 8 | "entities": [] 9 | }, 10 | { 11 | "text": "what do you do?", 12 | "intent": "intro", 13 | "entities": [] 14 | }, 15 | { 16 | "text": "what can you do for me?", 17 | "intent": "intro", 18 | "entities": [] 19 | }, 20 | { 21 | "text": "hey", 22 | "intent": "greet", 23 | "entities": [] 24 | }, 25 | { 26 | "text": "hey", 27 | "intent": "greet", 28 | "entities": [] 29 | }, 30 | { 31 | "text": "howdy", 32 | "intent": "greet", 33 | "entities": [] 34 | }, 35 | { 36 | "text": "hey there", 37 | "intent": "greet", 38 | "entities": [] 39 | }, 40 | { 41 | "text": "hello", 42 | "intent": "greet", 43 | "entities": [] 44 | }, 45 | { 46 | "text": "hi", 47 | "intent": "greet", 48 | "entities": [] 49 | }, 50 | { 51 | "text": "yes", 52 | "intent": "affirm", 53 | "entities": [] 54 | }, 55 | { 56 | "text": "yep", 57 | "intent": "affirm", 58 | "entities": [] 59 | }, 60 | { 61 | "text": "yeah", 62 | "intent": "affirm", 63 | "entities": [] 64 | }, 65 | { 66 | "text": "bye", 67 | "intent": "goodbye", 68 | "entities": [] 69 | }, 70 | { 71 | "text": "goodbye", 72 | "intent": "goodbye", 73 | "entities": [] 74 | }, 75 | { 76 | "text": "good bye", 77 | "intent": "goodbye", 78 | "entities": [] 79 | }, 80 | { 81 | "text": "stop", 82 | "intent": "goodbye", 83 | "entities": [] 84 | }, 85 | { 86 | "text": "end", 87 | "intent": "goodbye", 88 | "entities": [] 89 | }, 90 | { 91 | "text": "indeed", 92 | "intent": "affirm", 93 | "entities": [] 94 | }, 95 | { 96 | "text": "that's right", 97 | "intent": "affirm", 98 | "entities": [] 99 | }, 100 | { 101 | "text": "ok", 102 | "intent": "affirm", 103 | "entities": [] 104 | }, 105 | { 106 | "text": "great", 107 | "intent": "affirm", 108 | "entities": [] 109 | }, 110 | { 111 | "text": "What is the event happening now", 112 | "intent": "event-request", 113 | "entities": [ 114 | { 115 | "start": 28, 116 | "end": 31, 117 | "value": "now", 118 | "entity": "time" 119 | } 120 | ] 121 | }, 122 | { 123 | "text": "What event is happening at Lecture hall 10 AM today", 124 | "intent": "event-request", 125 | "entities": [ 126 | { 127 | "start": 40, 128 | "end": 45, 129 | "value": "10 AM", 130 | "entity": "time" 131 | }, 132 | { 133 | "start": 46, 134 | "end": 51, 135 | "value": "today", 136 | "entity": "day" 137 | }, 138 | { 139 | "start": 27, 140 | "end": 39, 141 | "value": "Lecture hall", 142 | "entity": "place" 143 | } 144 | ] 145 | }, 146 | { 147 | "text": "What is the event same time tomorrow", 148 | "intent": "event-request", 149 | "entities": [ 150 | { 151 | "start": 18, 152 | "end": 27, 153 | "value": "same time", 154 | "entity": "time" 155 | }, 156 | { 157 | "start": 28, 158 | "end": 36, 159 | "value": "tomorrow", 160 | "entity": "day" 161 | } 162 | ] 163 | }, 164 | { 165 | "text": "What event is happening at Lecture hall 2 tommorrow 10 PM", 166 | "intent": "event-request", 167 | "entities": [ 168 | { 169 | "start": 27, 170 | "end": 41, 171 | "value": "Lecture hall 2", 172 | "entity": "place" 173 | }, 174 | { 175 | "start": 52, 176 | "end": 57, 177 | "value": "10 PM", 178 | "entity": "time" 179 | }, 180 | { 181 | "start": 42, 182 | "end": 51, 183 | "value": "tomorrow", 184 | "entity": "day" 185 | } 186 | ] 187 | }, 188 | { 189 | "text": "What event is happening at Lecture hall 6 AM today", 190 | "intent": "event-request", 191 | "entities": [ 192 | { 193 | "start": 40, 194 | "end": 44, 195 | "value": "10 AM", 196 | "entity": "time" 197 | }, 198 | { 199 | "start": 45, 200 | "end": 52, 201 | "value": "today", 202 | "entity": "day" 203 | }, 204 | { 205 | "start": 27, 206 | "end": 39, 207 | "value": "Lecture hall", 208 | "entity": "place" 209 | } 210 | ] 211 | }, 212 | { 213 | "text": "What event is happening at Lecture hall 6:30 PM today", 214 | "intent": "event-request", 215 | "entities": [ 216 | { 217 | "start": 40, 218 | "end": 47, 219 | "value": "10 AM", 220 | "entity": "time" 221 | }, 222 | { 223 | "start": 48, 224 | "end": 55, 225 | "value": "today", 226 | "entity": "day" 227 | }, 228 | { 229 | "start": 27, 230 | "end": 39, 231 | "value": "Lecture hall", 232 | "entity": "place" 233 | } 234 | ] 235 | }, 236 | { 237 | "text": "What event is happening at Lecture hall 6 30 PM today", 238 | "intent": "event-request", 239 | "entities": [ 240 | { 241 | "start": 40, 242 | "end": 47, 243 | "value": "10 AM", 244 | "entity": "time" 245 | }, 246 | { 247 | "start": 48, 248 | "end": 55, 249 | "value": "today", 250 | "entity": "day" 251 | }, 252 | { 253 | "start": 27, 254 | "end": 39, 255 | "value": "Lecture hall", 256 | "entity": "place" 257 | } 258 | ] 259 | }, 260 | { 261 | "text": "What event is happening at 6 30 PM today", 262 | "intent": "event-request", 263 | "entities": [ 264 | { 265 | "start": 27, 266 | "end": 34, 267 | "value": "6 30 PM", 268 | "entity": "time" 269 | }, 270 | { 271 | "start": 35, 272 | "end": 40, 273 | "value": "today", 274 | "entity": "day" 275 | } 276 | ] 277 | }, 278 | { 279 | "text": "What event is happening at 6", 280 | "intent": "event-request", 281 | "entities": [ 282 | { 283 | "start": 27, 284 | "end": 28, 285 | "value": "6", 286 | "entity": "time" 287 | } 288 | ] 289 | }, 290 | { 291 | "text": "What event is at 12", 292 | "intent": "event-request", 293 | "entities": [ 294 | { 295 | "start": 17, 296 | "end": 19, 297 | "value": "12", 298 | "entity": "time" 299 | } 300 | ] 301 | }, 302 | { 303 | "text": "list events before 12", 304 | "intent": "event-request", 305 | "entities": [ 306 | { 307 | "start": 19, 308 | "end": 21, 309 | "value": "12", 310 | "entity": "time" 311 | }, 312 | { 313 | "start": 12, 314 | "end": 18, 315 | "value": "before", 316 | "entity": "relative-time" 317 | } 318 | ] 319 | }, 320 | { 321 | "text": "list events after 5", 322 | "intent": "event-request", 323 | "entities": [ 324 | { 325 | "start": 18, 326 | "end": 19, 327 | "value": "5", 328 | "entity": "time" 329 | }, 330 | { 331 | "start": 12, 332 | "end": 17, 333 | "value": "before", 334 | "entity": "relative-time" 335 | } 336 | ] 337 | }, 338 | { 339 | "text": "when is the chatbot event happening", 340 | "intent": "event-time", 341 | "entities": [ 342 | { 343 | "start": 12, 344 | "end": 19, 345 | "value": "chatbot", 346 | "entity": "event_name" 347 | } 348 | ] 349 | }, 350 | { 351 | "text": "when is python 101 event happening", 352 | "intent": "event-time", 353 | "entities": [ 354 | { 355 | "start": 8, 356 | "end": 18, 357 | "value": "python 101", 358 | "entity": "event_name" 359 | } 360 | ] 361 | }, 362 | { 363 | "text": "what event is happening 2 tomorrow", 364 | "intent": "event-request", 365 | "entities": [ 366 | { 367 | "start": 24, 368 | "end": 25, 369 | "value": "2", 370 | "entity": "time" 371 | }, 372 | { 373 | "start": 26, 374 | "end": 34, 375 | "value": "2", 376 | "entity": "time" 377 | } 378 | ] 379 | }, 380 | { 381 | "text": "What event is happening at Lecture hall 10 AM today", 382 | "intent": "event-request", 383 | "entities": [ 384 | { 385 | "start": 40, 386 | "end": 45, 387 | "value": "10 AM", 388 | "entity": "time" 389 | }, 390 | { 391 | "start": 46, 392 | "end": 51, 393 | "value": "today", 394 | "entity": "day" 395 | }, 396 | { 397 | "start": 27, 398 | "end": 39, 399 | "value": "Lecture hall", 400 | "entity": "place" 401 | } 402 | ] 403 | }, 404 | { 405 | "text": "What is the event same time tomorrow", 406 | "intent": "event-request", 407 | "entities": [ 408 | { 409 | "start": 18, 410 | "end": 27, 411 | "value": "same time", 412 | "entity": "time" 413 | }, 414 | { 415 | "start": 28, 416 | "end": 36, 417 | "value": "tomorrow", 418 | "entity": "day" 419 | } 420 | ] 421 | }, 422 | { 423 | "text": "What event is happening at Lecture hall 2 tommorrow 10 PM", 424 | "intent": "event-request", 425 | "entities": [ 426 | { 427 | "start": 27, 428 | "end": 41, 429 | "value": "Lecture hall 2", 430 | "entity": "place" 431 | }, 432 | { 433 | "start": 52, 434 | "end": 57, 435 | "value": "tomorrow 10 PM", 436 | "entity": "time" 437 | }, 438 | { 439 | "start": 42, 440 | "end": 51, 441 | "value": "tomorrow", 442 | "entity": "day" 443 | } 444 | ] 445 | }, 446 | { 447 | "text": "What event is happening at Lecture hall 6 AM today", 448 | "intent": "event-request", 449 | "entities": [ 450 | { 451 | "start": 40, 452 | "end": 44, 453 | "value": "6 AM", 454 | "entity": "time" 455 | }, 456 | { 457 | "start": 45, 458 | "end": 50, 459 | "value": "today", 460 | "entity": "day" 461 | }, 462 | { 463 | "start": 27, 464 | "end": 39, 465 | "value": "Lecture hall", 466 | "entity": "place" 467 | } 468 | ] 469 | }, 470 | { 471 | "text": "What event is happening at Lecture hall 6:30 PM today", 472 | "intent": "event-request", 473 | "entities": [ 474 | { 475 | "start": 40, 476 | "end": 47, 477 | "value": "6:30 PM", 478 | "entity": "time" 479 | }, 480 | { 481 | "start": 48, 482 | "end": 53, 483 | "value": "today", 484 | "entity": "day" 485 | }, 486 | { 487 | "start": 27, 488 | "end": 39, 489 | "value": "Lecture hall", 490 | "entity": "place" 491 | } 492 | ] 493 | }, 494 | { 495 | "text": "What event is happening at Lecture hall 6 30 PM today", 496 | "intent": "event-request", 497 | "entities": [ 498 | { 499 | "start": 40, 500 | "end": 47, 501 | "value": "10 AM", 502 | "entity": "time" 503 | }, 504 | { 505 | "start": 48, 506 | "end": 53, 507 | "value": "today", 508 | "entity": "day" 509 | }, 510 | { 511 | "start": 27, 512 | "end": 39, 513 | "value": "Lecture hall", 514 | "entity": "place" 515 | } 516 | ] 517 | }, 518 | { 519 | "text": "What event is happening at 6 30 PM today", 520 | "intent": "event-request", 521 | "entities": [ 522 | { 523 | "start": 27, 524 | "end": 34, 525 | "value": "6 30 PM", 526 | "entity": "time" 527 | }, 528 | { 529 | "start": 35, 530 | "end": 40, 531 | "value": "today", 532 | "entity": "day" 533 | } 534 | ] 535 | }, 536 | { 537 | "text": "What event is happening at 6 30 PM today", 538 | "intent": "event-request", 539 | "entities": [ 540 | { 541 | "start": 27, 542 | "end": 34, 543 | "value": "10 30 AM", 544 | "entity": "time" 545 | }, 546 | { 547 | "start": 35, 548 | "end": 40, 549 | "value": "today", 550 | "entity": "day" 551 | } 552 | ] 553 | }, 554 | { 555 | "text": "What event is happening at 6", 556 | "intent": "event-request", 557 | "entities": [ 558 | { 559 | "start": 27, 560 | "end": 28, 561 | "value": "6", 562 | "entity": "time" 563 | } 564 | ] 565 | }, 566 | { 567 | "text": "What event is at 12", 568 | "intent": "event-request", 569 | "entities": [ 570 | { 571 | "start": 17, 572 | "end": 19, 573 | "value": "12", 574 | "entity": "time" 575 | } 576 | ] 577 | }, 578 | { 579 | "text": "list events before 12", 580 | "intent": "event-request", 581 | "entities": [ 582 | { 583 | "start": 19, 584 | "end": 21, 585 | "value": "12", 586 | "entity": "time" 587 | }, 588 | { 589 | "start": 12, 590 | "end": 18, 591 | "value": "before", 592 | "entity": "relative-time" 593 | } 594 | ] 595 | }, 596 | { 597 | "text": "list events after 5", 598 | "intent": "event-request", 599 | "entities": [ 600 | { 601 | "start": 18, 602 | "end": 19, 603 | "value": "5", 604 | "entity": "time" 605 | }, 606 | { 607 | "start": 12, 608 | "end": 17, 609 | "value": "before", 610 | "entity": "relative-time" 611 | } 612 | ] 613 | }, 614 | { 615 | "text": "when is the chatbot event happening", 616 | "intent": "event-time", 617 | "entities": [ 618 | { 619 | "start": 12, 620 | "end": 19, 621 | "value": "chatbot", 622 | "entity": "event_name" 623 | } 624 | ] 625 | }, 626 | { 627 | "text": "when is python 101 event happening", 628 | "intent": "event-time", 629 | "entities": [ 630 | { 631 | "start": 8, 632 | "end": 18, 633 | "value": "python 101", 634 | "entity": "event_name" 635 | } 636 | ] 637 | }, 638 | { 639 | "text": "what event is happening 2 tomorrow", 640 | "intent": "event-request", 641 | "entities": [ 642 | { 643 | "start": 24, 644 | "end": 25, 645 | "value": "2", 646 | "entity": "time" 647 | }, 648 | { 649 | "start": 26, 650 | "end": 34, 651 | "value": "2", 652 | "entity": "time" 653 | } 654 | ] 655 | } 656 | ] 657 | } 658 | } -------------------------------------------------------------------------------- /AI-engine/rasa_nlu_log.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "entities": [], 4 | "confidence": 0.7503025949407385, 5 | "intent": "greet", 6 | "text": "hi" 7 | }, 8 | { 9 | "entities": [], 10 | "confidence": 0.3309503410702648, 11 | "intent": "greet", 12 | "text": "yo" 13 | }, 14 | { 15 | "entities": [ 16 | { 17 | "start": 0, 18 | "end": 9, 19 | "value": "first day", 20 | "entity": "time" 21 | } 22 | ], 23 | "confidence": 0.19041142788243318, 24 | "intent": "affirm", 25 | "text": "first day" 26 | }, 27 | { 28 | "entities": [], 29 | "confidence": 1.0887962093977857, 30 | "intent": "greet", 31 | "text": "hey" 32 | }, 33 | { 34 | "entities": [ 35 | { 36 | "start": 26, 37 | "end": 29, 38 | "value": "now", 39 | "entity": "time" 40 | } 41 | ], 42 | "confidence": 0.4448289239245017, 43 | "intent": "event-request", 44 | "text": "what events are happening now" 45 | }, 46 | { 47 | "entities": [ 48 | { 49 | "start": 0, 50 | "end": 5, 51 | "value": "heeey", 52 | "entity": "time" 53 | } 54 | ], 55 | "confidence": 0.21558314243108612, 56 | "intent": "greet", 57 | "text": "heeey" 58 | }, 59 | { 60 | "entities": [], 61 | "confidence": 0.09125234572941558, 62 | "intent": "affirm", 63 | "text": "whts up" 64 | }, 65 | { 66 | "entities": [], 67 | "confidence": 0.1148097920349114, 68 | "intent": "affirm", 69 | "text": "whats up" 70 | } 71 | ] -------------------------------------------------------------------------------- /bot-application/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask import render_template, jsonify, request 3 | import requests 4 | from models import * 5 | from response import * 6 | import random 7 | 8 | 9 | @app.route('/') 10 | def hello_world(): 11 | """ 12 | Sample hello world 13 | """ 14 | return render_template('home.html') 15 | 16 | 17 | def get_random_response(intent): 18 | print (response[intent]) 19 | return random.choice(response[intent]) 20 | 21 | 22 | def format_entities(entities): 23 | """ 24 | formats entities to key value pairs 25 | """ 26 | # Should be formatted to handle multiple entity values 27 | e = {"day": None, "time": None, "place": None} 28 | for entity in entities: 29 | e[entity["entity"]] = entity["value"] 30 | return e 31 | 32 | 33 | def get_event(day=None, time=None, place=None): 34 | """ 35 | gets event date and time from user utterance 36 | and finds event within next half an hour of that range 37 | """ 38 | if not day and not time: 39 | return get_random_response("events_link") 40 | date_time = get_date_time(day, time) 41 | print(date_time) 42 | events = Event.query.filter(Event.date_time >= date_time, 43 | Event.date_time <= date_time + datetime.timedelta(minutes=30)) 44 | events = events.all() 45 | if not events: 46 | return get_random_response("no_events") + "
" + get_random_response("events_link") 47 | event_description = "
".join(event.event_description + " at " + event.place for event in events) 48 | return event_description 49 | 50 | 51 | @app.route('/chat', methods=["POST"]) 52 | def chat(): 53 | """ 54 | chat end point that performs NLU using rasa.ai 55 | and constructs response from response.py 56 | """ 57 | # try: 58 | response = requests.get("http://localhost:5000/parse", params={"q": request.form["text"]}) 59 | response = response.json() 60 | print (response) 61 | intent = response.get("intent", {}).get("name", "default") 62 | entities = format_entities(response.get("entities", [])) 63 | if intent == "event-request": 64 | response_text = get_event(entities["day"], entities["time"], entities["place"]) 65 | else: 66 | response_text = get_random_response(intent) 67 | return jsonify({"status": "success", "response": response_text}) 68 | # except Exception as e: 69 | # print(e) 70 | # return jsonify({"status": "success", "response": "Sorry I am not trained to do that yet..."}) 71 | 72 | 73 | app.config["DEBUG"] = True 74 | if __name__ == "__main__": 75 | app.run(port=8000) 76 | -------------------------------------------------------------------------------- /bot-application/extract.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import requests 3 | import json 4 | 5 | conn = sqlite3.connect('app.db') 6 | c = conn.cursor() 7 | # print("Opened database successfully") 8 | 9 | conn.execute('''CREATE TABLE IF NOT EXISTS Event 10 | (ID INT NOT NULL , 11 | event_description VARCHAR(40), 12 | date_time DATATIME, 13 | place VARCHAR(40));''') 14 | # print("Table created successfully") 15 | 16 | url = "https://conference.pydelhi.org/api/schedule.json" 17 | r = requests.get(url) 18 | data = r.text 19 | schedule = json.loads(data)["0.0.1"][0] 20 | url2 = "https://conference.pydelhi.org/api/tracks.json" 21 | r2 = requests.get(url2) 22 | data2 = r2.text 23 | tracks = json.loads(data2)["0.0.1"][0] 24 | DATE_ONE = "2017-03-18" 25 | DATE_TWO = "2017-03-19" 26 | 27 | schedule["2017-03-23"] = schedule[DATE_ONE] 28 | del schedule[DATE_ONE] 29 | 30 | schedule["2017-03-24"] = schedule[DATE_TWO] 31 | del schedule[DATE_TWO] 32 | 33 | 34 | DATE_ONE = "2017-03-23" 35 | DATE_TWO = "2017-03-24" 36 | 37 | from datetime import datetime 38 | # DayOne Loop 39 | for events in schedule[DATE_ONE]: 40 | title = events["title"] 41 | talk_id = str(events["talk_id"]) 42 | start_time = events["start_time"] 43 | end_time = events["end_time"] 44 | track = events["track"] 45 | description = tracks[talk_id]["description"] 46 | theTime = datetime.strptime(DATE_ONE + 47 | " " + start_time+" "+("AM" if int(start_time.split(":")[0])>8 else "PM"), 48 | "%Y-%m-%d %I:%M %p") 49 | 50 | place = "AUDI 1" 51 | speaker = '' 52 | if track != "all": 53 | speaker = tracks[talk_id]["speaker"]["name"] 54 | if track == "all": 55 | place = "AUDI 1" 56 | elif track == "1": 57 | place = "AUDI 1" 58 | elif track == "2": 59 | place = "LECTURE HALL 1" 60 | else: 61 | place = "LECTURE HALL 2" 62 | if speaker != '': 63 | title = title + " by " + speaker 64 | c.execute("insert into Event (ID,event_description,date_time,place) values(?,?,?,?)", 65 | (talk_id, title, theTime, place)) 66 | conn.commit() 67 | 68 | # Day2 Loop 69 | for events in schedule[DATE_TWO]: 70 | title = events["title"] 71 | place = "AUDI 1" 72 | speaker = '' 73 | talk_id = str(events["talk_id"]) 74 | start_time = events["start_time"] 75 | end_time = events["end_time"] 76 | track = events["track"] 77 | description = tracks[talk_id]["description"] 78 | if track != "all": 79 | speaker = tracks[talk_id]["speaker"]["name"] 80 | if track == "all": 81 | place = "AUDI 1" 82 | elif track == "1": 83 | place = "AUDI 1" 84 | elif track == "2": 85 | place = "LECTURE HALL 1" 86 | else: 87 | place = "LECTURE HALL 2" 88 | theTime = datetime.strptime(DATE_TWO + 89 | " " + start_time+" "+("AM" if int(start_time.split(":")[0])>8 else "PM"), 90 | "%Y-%m-%d %I:%M %p") 91 | if speaker != '': 92 | title = title + " by " + speaker 93 | conn.execute("insert into Event (ID,event_description,date_time,place) values(?,?,?,?)", 94 | (talk_id, title, theTime, place)) 95 | conn.commit() 96 | 97 | print("all data") 98 | c.execute("select * from Event") 99 | for i in c.fetchall(): 100 | print(i) 101 | 102 | conn.close() 103 | -------------------------------------------------------------------------------- /bot-application/getSchedule.py: -------------------------------------------------------------------------------- 1 | class getSchedule: 2 | def getSchedule(schedule, tracks, table_body): 3 | schedule_rows = [] 4 | for i in range(len(schedule)): 5 | talk_id = schedule[i]["talk_id"] 6 | entity_details = schedule[i] 7 | title = entity_details["title"] 8 | if "speaker" in tracks["talk_id"]: 9 | speaker_name= tracks["talk_id"]["speaker"] 10 | display_title=title+" by "+speaker_name 11 | else: 12 | display_title=title 13 | time_duration = entity_details["start_time"] + ' - ' + entity_details["end_time"] 14 | 15 | try: 16 | current_day_track = schedule[i]["track"] 17 | if current_day_track =='all': 18 | schedule_rows.append([time_duration,display_title]) 19 | except: 20 | schedule_rows.append([time_duration, display_title]) 21 | if current_day_track==1: 22 | # else if (current_day_track == '1') 23 | schedule_rows.append([time_duration, display_title]) 24 | else: 25 | # index_of_last_row = len(schedule_rows) - 1 26 | schedule_rows.append(display_title) 27 | 28 | -------------------------------------------------------------------------------- /bot-application/local_settings.py: -------------------------------------------------------------------------------- 1 | LXD_URL = "http://codecompiler.etpg.in" 2 | MYSQL_PASSWORD = "" 3 | MYSQL_USER = "root" 4 | DEBUG_MODE = True 5 | LXD_USERNAME = "ibo" 6 | LXD_PASSWORD = "ibo@ffi2016" 7 | -------------------------------------------------------------------------------- /bot-application/models.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | # from urllib import quote_plus as urlquote 4 | import urllib.parse 5 | from flask_admin import Admin 6 | from flask_admin.contrib.sqla import ModelView 7 | from flask_migrate import Migrate 8 | 9 | try: 10 | from local_settings import * 11 | except ImportError: 12 | from production_settings import * 13 | 14 | app = Flask(__name__) 15 | app.secret_key = '12345' 16 | app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True 17 | app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///app.db" 18 | db = SQLAlchemy(app) 19 | # Migrate won't work well on sqlite better to use mysql db 20 | migrate = Migrate(app, db) 21 | 22 | 23 | class Event(db.Model): 24 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 25 | event_description = db.Column(db.String(50)) 26 | date_time = db.Column(db.DateTime()) 27 | place = db.Column(db.String(50)) 28 | 29 | def __init__(self, event_description=None, date=None, time=None, place=None): 30 | self.event_description = event_description 31 | self.date = date 32 | self.time = time 33 | self.place = place 34 | 35 | 36 | class MyModelView(ModelView): 37 | def __init__(self, model, session, name=None, category=None, endpoint=None, url=None, **kwargs): 38 | for k, v in kwargs.items(): 39 | setattr(self, k, v) 40 | 41 | super(MyModelView, self).__init__(model, session, name=name, category=category, endpoint=endpoint, url=url) 42 | 43 | 44 | admin = Admin(app, name='rasa-site-bot', template_mode='bootstrap3') 45 | admin.add_view(MyModelView(Event, db.session)) 46 | -------------------------------------------------------------------------------- /bot-application/response.py: -------------------------------------------------------------------------------- 1 | # dict of response for each type of intent 2 | 3 | import datetime 4 | 5 | response = { 6 | "greet": ["hey", "hello", "hi"], 7 | "goodbye": ["bye", "It was nice talking to you", "see you", "ttyl"], 8 | "affirm": ["cool", "I know you would like it"], 9 | "day_preference": ["which day of conference ?"], 10 | "time_preference": ["Do you have any time preference"], 11 | "events_link": [ 12 | 'You can check all the events here PyDelhi events'], 13 | "no_events": ["No events found"], 14 | "intro": ["I am event bot for pydelhi, I can find you event details in minutes"], 15 | "default": ["Sorry I am not trained to answer that yet.", "Oops I didn't understand that sorry"] 16 | } 17 | 18 | mapping = { 19 | "now": datetime.datetime.now(), 20 | "tomorrow": datetime.date.today() + datetime.timedelta(days=1), 21 | "today": datetime.date.today(), 22 | "same time": datetime.datetime.now(), 23 | "second day": datetime.datetime.now() 24 | } 25 | 26 | 27 | def try_parsing_date(text): 28 | """ 29 | Parses time of string format to a time object 30 | """ 31 | for fmt in ('%I %p', '%I %M %p', '%I:%M %p'): 32 | try: 33 | return datetime.datetime.strptime(text, fmt) 34 | except ValueError: 35 | pass 36 | if ":" in text: 37 | return datetime.datetime.strptime(text + " " + 38 | ("AM" if int(text.split(":")[0]) >= 8 else "PM"), '%I:%M %p') 39 | return datetime.datetime.strptime(text + " " + 40 | ("AM" if int(text) >= 8 else "PM"), '%I %p') 41 | 42 | 43 | def get_date_time(day, time): 44 | """ 45 | Maps words like now today tom etc., to corresponding datetime objects 46 | """ 47 | try: 48 | time = mapping[time] 49 | except KeyError: 50 | if not time: 51 | time = datetime.datetime.now() 52 | else: 53 | time = try_parsing_date(time) 54 | try: 55 | date = mapping[day] 56 | except KeyError: 57 | date = datetime.date.today() 58 | 59 | return datetime.datetime.combine(date, time.time()) 60 | -------------------------------------------------------------------------------- /bot-application/static/css/chat_interface.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | background-color: #edeff2; 7 | font-family: "Calibri", "Roboto", sans-serif; 8 | } 9 | 10 | .chat_window { 11 | /*position: absolute;*/ 12 | width: calc(100% - 20px); 13 | max-width: 800px; 14 | height: 500px; 15 | border-radius: 10px; 16 | background-color: #fff; 17 | left: 50%; 18 | top: 50%; 19 | /*transform: translateX(-50%) translateY(-50%);*/ 20 | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15); 21 | background-color: #f8f8f8; 22 | overflow: hidden; 23 | } 24 | 25 | .top_menu { 26 | background-color: #fff; 27 | width: 100%; 28 | padding: 13px 0px; 29 | box-shadow: 0 1px 30px rgba(0, 0, 0, 0.1); 30 | } 31 | .top_menu .buttons { 32 | margin: 3px 0 0 20px; 33 | position: absolute; 34 | } 35 | .top_menu .buttons .button { 36 | width: 16px; 37 | height: 16px; 38 | border-radius: 50%; 39 | display: inline-block; 40 | margin-right: 10px; 41 | position: relative; 42 | } 43 | .top_menu .buttons .button.close { 44 | background-color: #f5886e; 45 | } 46 | .top_menu .buttons .button.minimize { 47 | background-color: #fdbf68; 48 | } 49 | .top_menu .buttons .button.maximize { 50 | background-color: #a3d063; 51 | } 52 | .top_menu .title { 53 | text-align: center; 54 | color: #337ab7; 55 | font-size: 20px; 56 | } 57 | 58 | .messages { 59 | position: relative; 60 | list-style: none; 61 | padding: 20px 10px 0 10px; 62 | margin: 0; 63 | height: 70%; 64 | overflow: scroll; 65 | } 66 | .messages .message { 67 | clear: both; 68 | overflow: hidden; 69 | margin-bottom: 20px; 70 | transition: all 0.5s linear; 71 | opacity: 0; 72 | } 73 | .messages .message.left .avatar { 74 | background-color: #f5886e; 75 | float: left; 76 | } 77 | .messages .message.left .text_wrapper { 78 | background-color: #ffe6cb; 79 | margin-left: 20px; 80 | } 81 | .messages .message.left .text_wrapper::after, .messages .message.left .text_wrapper::before { 82 | right: 100%; 83 | border-right-color: #ffe6cb; 84 | } 85 | .messages .message.left .text { 86 | color: #c48843; 87 | } 88 | .messages .message.right .avatar { 89 | background-color: #fdbf68; 90 | float: right; 91 | } 92 | .messages .message.right .text_wrapper { 93 | background-color: #c7eafc; 94 | margin-right: 20px; 95 | float: right; 96 | } 97 | .messages .message.right .text_wrapper::after, .messages .message.right .text_wrapper::before { 98 | left: 100%; 99 | border-left-color: #c7eafc; 100 | } 101 | .messages .message.right .text { 102 | color: #45829b; 103 | } 104 | .messages .message.appeared { 105 | opacity: 1; 106 | } 107 | .messages .message .avatar { 108 | width: 60px; 109 | height: 60px; 110 | border-radius: 50%; 111 | display: inline-block; 112 | } 113 | .messages .message .text_wrapper { 114 | display: inline-block; 115 | padding: 20px; 116 | border-radius: 6px; 117 | width: calc(100% - 85px); 118 | min-width: 100px; 119 | position: relative; 120 | } 121 | .messages .message .text_wrapper::after, .messages .message .text_wrapper:before { 122 | top: 18px; 123 | border: solid transparent; 124 | content: " "; 125 | height: 0; 126 | width: 0; 127 | position: absolute; 128 | pointer-events: none; 129 | } 130 | .messages .message .text_wrapper::after { 131 | border-width: 13px; 132 | margin-top: 0px; 133 | } 134 | .messages .message .text_wrapper::before { 135 | border-width: 15px; 136 | margin-top: -2px; 137 | } 138 | .messages .message .text_wrapper .text { 139 | font-size: 18px; 140 | font-weight: 300; 141 | } 142 | 143 | .bottom_wrapper { 144 | position: relative; 145 | width: 100%; 146 | background-color: #fff; 147 | padding: 20px 20px; 148 | /*position: absolute;*/ 149 | bottom: 0; 150 | } 151 | .bottom_wrapper .message_input_wrapper { 152 | display: inline-block; 153 | height: 50px; 154 | border-radius: 25px; 155 | border: 1px solid #bcbdc0; 156 | width: calc(100% - 160px); 157 | position: relative; 158 | padding: 0 20px; 159 | } 160 | .bottom_wrapper .message_input_wrapper .message_input { 161 | border: none; 162 | height: 100%; 163 | box-sizing: border-box; 164 | width: calc(100% - 40px); 165 | position: absolute; 166 | outline-width: 0; 167 | color: gray; 168 | } 169 | .bottom_wrapper .send_message { 170 | width: 140px; 171 | height: 50px; 172 | display: inline-block; 173 | border-radius: 50px; 174 | background-color: #a3d063; 175 | border: 2px solid #a3d063; 176 | color: #fff; 177 | cursor: pointer; 178 | transition: all 0.2s linear; 179 | text-align: center; 180 | float: right; 181 | } 182 | .bottom_wrapper .send_message:hover { 183 | color: #a3d063; 184 | background-color: #fff; 185 | } 186 | .bottom_wrapper .send_message .text { 187 | font-size: 18px; 188 | font-weight: 300; 189 | display: inline-block; 190 | line-height: 48px; 191 | } 192 | 193 | .message_template { 194 | display: none; 195 | } 196 | -------------------------------------------------------------------------------- /bot-application/static/css/style.css: -------------------------------------------------------------------------------- 1 | @import url(http://weloveiconfonts.com/api/?family=fontawesome|iconicstroke|typicons); 2 | /* fontawesome */ 3 | [class*="fontawesome-"]:before { 4 | font-family: 'FontAwesome', sans-serif; 5 | } 6 | /* iconicstroke */ 7 | [class*="iconicstroke-"]:before { 8 | font-family: 'IconicStroke', sans-serif; 9 | } 10 | /* typicons */ 11 | [class*="typicons-"]:before { 12 | font-family: 'Typicons', sans-serif; 13 | } 14 | body{ 15 | font-family:arial,sans-serif; 16 | } 17 | .chat-container { 18 | width: 300px; 19 | margin-right: 20px; 20 | float:right; 21 | overflow:hidden; 22 | } 23 | .top-header { 24 | background: #666; 25 | color: white; 26 | padding: 0.2rem; 27 | position: relative; 28 | overflow: hidden; 29 | border-bottom: 4px solid #35ac19; 30 | cursor:pointer; 31 | } 32 | .top-header:hover { 33 | background-color:#35ac19; 34 | } 35 | .top-header-tit { 36 | display: inline; 37 | font-size: 14px; 38 | } 39 | .top-header .typicons-message { 40 | display: inline-block; 41 | padding: 2px 5px 2px 5px; 42 | font-size: 20px; 43 | position: relative; 44 | top: 5px; 45 | } 46 | .top-header .typicons-minus { 47 | position: relative; 48 | top: 3px; 49 | font-size: 15px; 50 | cursor:pointer; 51 | } 52 | .top-header .typicons-plus { 53 | position: relative; 54 | top: 3px; 55 | font-size: 15px; 56 | } 57 | .top-header .typicons-times{ 58 | position: relative; 59 | top: 3px; 60 | font-size: 15px; 61 | } 62 | .top-header .left { 63 | float: left; 64 | } 65 | .top-header .right { 66 | float: right; 67 | padding-top: 5px; 68 | } 69 | .top-header > * { 70 | position: relative; 71 | } 72 | .top-header::before { 73 | content: ''; 74 | position: absolute; 75 | top: -100%; 76 | left: 0; 77 | right: 0; 78 | bottom: -100%; 79 | opacity: 0.25; 80 | background-color: #404040 81 | } 82 | .chat-box { 83 | list-style: none; 84 | background: #e5e5e5; 85 | margin: 0; 86 | padding: 0 0 50px 0; 87 | height: 280px; 88 | overflow-y: auto; 89 | } 90 | .chat-box li { 91 | padding: 0.5rem; 92 | overflow: hidden; 93 | display: flex; 94 | } 95 | .chat-box .avatar-icon { 96 | width: 40px; 97 | position: relative; 98 | } 99 | .chat-box .avatar-icon img { 100 | display: block; 101 | width: 100%; 102 | background-color:#1469A6; 103 | } 104 | .ibo .avatar-icon:after { 105 | content: ''; 106 | position: absolute; 107 | top: 0; 108 | right: 0; 109 | width: 0; 110 | height: 0; 111 | border: 5px solid white; 112 | border-left-color: transparent; 113 | border-bottom-color: transparent; 114 | } 115 | .me { 116 | justify-content: flex-end; 117 | align-items: flex-end; 118 | } 119 | .me .messages { 120 | order: 1; 121 | border-bottom-right-radius: 0; 122 | } 123 | .me .avatar-icon { 124 | order: 2; 125 | } 126 | .me .avatar-icon:after { 127 | content: ''; 128 | position: absolute; 129 | bottom: 0; 130 | left: 0; 131 | width: 0; 132 | height: 0; 133 | border: 5px solid white; 134 | border-right-color: transparent; 135 | border-top-color: transparent; 136 | box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); 137 | } 138 | .messages { 139 | background: white; 140 | padding: 10px; 141 | border-radius: 2px; 142 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); 143 | } 144 | .messages p { 145 | font-size: 0.8rem; 146 | margin: 0 0 0.2rem 0; 147 | } 148 | .messages time { 149 | font-size: 0.7rem; 150 | color: #ccc; 151 | } 152 | .setting{ 153 | background-color: #e5e5e5; 154 | height: 32px; 155 | padding-top: 2px; 156 | border-bottom: 1px solid rgba(0,0,0,.1); 157 | } 158 | .setting .left { 159 | float: left; 160 | } 161 | .setting .right { 162 | float: right; 163 | } 164 | .iconicstroke-user{ 165 | font-size: 22px; 166 | position: relative; 167 | top: 4px; 168 | left: 10px; 169 | color: #414141; 170 | cursor:pointer; 171 | } 172 | .typicons-cog{ 173 | font-size: 23px; 174 | position: relative; 175 | top: 7px; 176 | right: 4px; 177 | color: #414141; 178 | cursor:pointer; 179 | } 180 | .fontawesome-facetime-video{ 181 | font-size: 18px; 182 | position: relative; 183 | top: 3px; 184 | color: #414141; 185 | left: 5px; 186 | cursor:pointer; 187 | } 188 | .iconicstroke-user:hover, .typicons-cog:hover,.fontawesome-facetime-video:hover{ 189 | color:#000000; 190 | } 191 | ::-webkit-scrollbar{height:14px;width:10px;background:#eee;border-left:1px solid #ddd} 192 | ::-webkit-scrollbar-thumb{background:#ddd;border:1px solid #cfcfcf} 193 | ::-webkit-scrollbar-thumb:hover{background:#b2b2b2;border:1px solid #b2b2b2} 194 | ::-webkit-scrollbar-thumb:active{background:#b2b2b2;border:1px solid #b2b2b2} 195 | @-webkit-keyframes pulse { 196 | from { 197 | opacity: 0; 198 | } 199 | to { 200 | opacity: 0.5; 201 | } 202 | } 203 | 204 | /************ 205 | * response * 206 | ************/ 207 | #response { 208 | width:320px; 209 | background-color: rgba(255, 255, 255, 0.8); 210 | } 211 | .say { 212 | width:220px; 213 | padding:8px 15px; 214 | background:rgba(50, 50, 50, 0.2); 215 | border:0px solid #dbdbdb; 216 | } 217 | .saybtn { 218 | position:relative; 219 | padding:6px 15px; 220 | left:-8px; 221 | border:2px solid #207cca; 222 | background-color:#207cca; 223 | color:#fafafa; 224 | } 225 | .saybtn:hover { 226 | background-color:#409cea; 227 | } 228 | 229 | .ace_editor { 230 | border: 1px solid lightgray; 231 | margin: auto; 232 | height: 200px; 233 | width: 80%; 234 | } 235 | .scrollmargin { 236 | height: 80px; 237 | text-align: center; 238 | } 239 | .view{ 240 | border: 1px solid lightgray; 241 | margin: auto; 242 | width: 80%; 243 | } 244 | .view div span{ 245 | margin: 20px; 246 | display: inline-block; 247 | } 248 | .view div span span{ 249 | margin: 0px; 250 | display: inline; 251 | } 252 | .output{ 253 | min-height: 70px; 254 | } 255 | .TitleBar { 256 | margin: auto; 257 | width: 80%; 258 | border: 1px solid lightgray; 259 | height: 30px; 260 | border-bottom: 0px; 261 | background-color: #FCFAFA; 262 | font-size:20px; 263 | } 264 | .TitleBar b{ 265 | margin:15px; 266 | color: #454444; 267 | } 268 | .actionbar{ 269 | margin: auto; 270 | width: 80%; 271 | } 272 | #statusBar { 273 | margin: auto; 274 | width: 80%; 275 | border: 1px solid lightgray; 276 | height: 20px; 277 | border-top: 0px; 278 | } 279 | 280 | .ace_status-indicator { 281 | color: gray; 282 | float:right; 283 | right: 0; 284 | border-left: 1px solid; 285 | } 286 | .submit { 287 | float: right; 288 | border: 1px solid #AAA; 289 | margin-left: 10px; 290 | padding: 4px; 291 | cursor: pointer; 292 | } 293 | 294 | .blinking-cursor { 295 | font-weight: 500; 296 | font-size: 15px; 297 | color: #2E3D48; 298 | -webkit-animation: 1s blink step-end infinite; 299 | -moz-animation: 1s blink step-end infinite; 300 | -ms-animation: 1s blink step-end infinite; 301 | -o-animation: 1s blink step-end infinite; 302 | animation: 1s blink step-end infinite; 303 | } 304 | 305 | @keyframes "blink" { 306 | from, to { 307 | color: transparent; 308 | } 309 | 50% { 310 | color: black; 311 | } 312 | } 313 | 314 | @-moz-keyframes blink { 315 | from, to { 316 | color: transparent; 317 | } 318 | 50% { 319 | color: black; 320 | } 321 | } 322 | 323 | @-webkit-keyframes "blink" { 324 | from, to { 325 | color: transparent; 326 | } 327 | 50% { 328 | color: black; 329 | } 330 | } 331 | 332 | @-ms-keyframes "blink" { 333 | from, to { 334 | color: transparent; 335 | } 336 | 50% { 337 | color: black; 338 | } 339 | } 340 | 341 | @-o-keyframes "blink" { 342 | from, to { 343 | color: transparent; 344 | } 345 | 50% { 346 | color: black; 347 | } 348 | } 349 | #submit:disabled,#SubmitMCQ :disabled { 350 | background-color: white; 351 | } 352 | #submit, #SubmitMCQ { 353 | background: #2cbb0f; 354 | color: white; 355 | } 356 | #submit:hover,#SubmitMCQ:hover{ 357 | background: white; 358 | color: #2cbb0f;} 359 | .submit:hover { 360 | box-shadow: 1px 1px 3px gray; 361 | } 362 | .submit:disabled { 363 | box-shadow: unset; 364 | cursor: unset; 365 | color: lightgrey !important; 366 | background-color: #f6f6f6 !important; 367 | } 368 | #run { 369 | background-color: #4c9ed9; 370 | color: white; 371 | } 372 | #compiler::first-letter { 373 | text-transform: uppercase; 374 | } 375 | @media only screen and (max-height: 480px) { 376 | .chat-box { 377 | height: calc(100vh - 180px); 378 | } 379 | 380 | } 381 | #response{ 382 | width: calc(100% + 20px); 383 | } 384 | @media only screen and (max-Width: 340px) { 385 | .chat-container { 386 | width: calc(100vw - 20px); 387 | max-width: 300px; 388 | margin: auto 10px; 389 | } 390 | .say { 391 | width: calc(100% - 100px); 392 | } 393 | 394 | } 395 | .view { 396 | white-space: pre-wrap; /* Since CSS 2.1 */ 397 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 398 | white-space: -pre-wrap; /* Opera 4-6 */ 399 | white-space: -o-pre-wrap; /* Opera 7 */ 400 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 401 | } 402 | 403 | #QI { 404 | overflow-x: hidden; 405 | } 406 | 407 | .slide { 408 | opacity: 0; 409 | position: relative; 410 | font-family: Arial; 411 | font-size: 14px; 412 | /*line-height: 50px;*/ 413 | right: -100%; 414 | width:100%; 415 | } 416 | 417 | /*.choice { 418 | -webkit-column-count: 2; 419 | -moz-column-count: 2; 420 | column-count: 2; 421 | }*/ 422 | .MCanswer { 423 | display: inline-block; 424 | vertical-align: top; 425 | } 426 | .tab-container{ 427 | background: #f1f1f1; 428 | /* margin: 0; */ 429 | padding: 0; 430 | /* max-height: 35px; */ 431 | /* position: relative; */ 432 | overflow: hidden; 433 | } 434 | 435 | ul.tabs{ 436 | margin: 0; 437 | list-style-type : none; 438 | line-height : 35px; 439 | max-height: 35px; 440 | overflow: hidden; 441 | display: inline-block; 442 | padding: 0; 443 | padding-right: 10px; 444 | padding-left: 10px; 445 | border-bottom: 1px solid #d4d4d4; 446 | width: 100%; 447 | } 448 | 449 | ul.tabs > li.active{ 450 | z-index: 2; 451 | background: white; 452 | } 453 | 454 | ul.tabs > li.active:before{ 455 | border-color : transparent #efefef transparent transparent; 456 | } 457 | 458 | 459 | ul.tabs > li.active:after{ 460 | border-color : transparent transparent transparent #efefef; 461 | } 462 | 463 | ul.tabs > li{ 464 | float: left; 465 | margin : 5px -10px 0; 466 | border-top-right-radius: 25px 170px; 467 | border-top-left-radius: 20px 90px; 468 | padding : 0 30px 0 25px; 469 | height: 170px; 470 | background: #ddd; 471 | position : relative; 472 | box-shadow: 0 10px 20px rgba(0,0,0,.5); 473 | max-width : 200px; 474 | } 475 | 476 | ul.tabs > li > a{ 477 | display: inline-block; 478 | max-width:100%; 479 | overflow: hidden; 480 | text-overflow: ellipsis; 481 | text-decoration: none; 482 | color: #222; 483 | } 484 | 485 | ul.tabs > li:before, ul.tabs > li:after{ 486 | content : ''; 487 | background : transparent; 488 | height: 20px; 489 | width: 20px; 490 | border-radius: 100%; 491 | border-width: 10px; 492 | top: 0px; 493 | border-style : solid; 494 | position : absolute; 495 | } 496 | 497 | ul.tabs > li:before{ 498 | 499 | border-color : transparent #ddd transparent transparent; 500 | left: -23px; 501 | -ms-transform: rotate(48deg); 502 | -webkit-transform : rotate(48deg); 503 | transform: rotate(48deg); 504 | } 505 | 506 | ul.tabs > li:after{ 507 | border-color : transparent transparent transparent #ddd; 508 | -webkit-transform : rotate(-48deg); 509 | -ms-transform: rotate(-48deg); 510 | transform: rotate(-48deg); 511 | right: -17px; 512 | } 513 | 514 | /* Clear Fix took for HTML 5 Boilerlate*/ 515 | .clearfix:after { clear: both; } 516 | .clearfix { zoom: 1; } 517 | .clearfix:after,.clearfix:before{ 518 | -webkit-box-sizing: unset; 519 | -moz-box-sizing: unset; 520 | box-sizing: unset; 521 | } 522 | 523 | *{ 524 | -webkit-box-sizing: unset; 525 | -moz-box-sizing: unset; 526 | box-sizing: unset; 527 | } 528 | body{ 529 | line-height: unset; 530 | } 531 | pre{ 532 | padding: unset; 533 | border-radius:unset; 534 | } 535 | #modal-backdrop{ 536 | height: 100vh; 537 | width: 100vw; 538 | background: rgba(0,0,0,0.53); 539 | z-index: 10000; 540 | position: fixed; 541 | top: 0px; 542 | left: 0px; 543 | } 544 | #modal{ 545 | border-radius: 4px; 546 | background: white; 547 | width: 500px; 548 | margin: auto; 549 | top: 100px; 550 | position: relative; 551 | color: #757575; 552 | overflow: hidden; 553 | 554 | } 555 | #modal-header{ 556 | min-height: 20px; 557 | width: 100%; 558 | font-size: 16px; 559 | font-weight: 100; 560 | border-bottom: 1px solid lightgray; 561 | padding: 12px; 562 | /*text-shadow: 1px 1px 1px rgba(114, 119, 112, 0.8);*/ 563 | } 564 | #modal-body{ 565 | min-height: 20px; 566 | width: 100%; 567 | padding: 5px; 568 | overflow: hidden 569 | } 570 | #modal-footer{ 571 | min-height: 20px; 572 | width: 100%; 573 | border-top: 1px solid lightgray; 574 | padding: 5px; 575 | } 576 | #modal-footer #next{ 577 | cursor: unset; 578 | color: white; 579 | background-color: #4CAF50; 580 | float: right; 581 | margin: 5px; 582 | margin-right: 8px; 583 | border: unset; 584 | padding: 6px; 585 | border-radius: 1px; 586 | } 587 | #modal-footer #next:hover{ 588 | background-color: #ffffff; 589 | color: #4CAF50; 590 | box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 591 | } 592 | #modal-footer #skip{ 593 | cursor: unset; 594 | color: white; 595 | background-color: #FF622C; 596 | float: right; 597 | margin: 5px; 598 | margin-right: 8px; 599 | border: unset; 600 | padding: 6px; 601 | border-radius: 1px; 602 | } 603 | #modal-footer #skip:hover{ 604 | background-color: white; 605 | color: #FF622C; 606 | box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 607 | } 608 | .skip:disabled { 609 | box-shadow: unset; 610 | cursor: unset; 611 | color: lightgrey !important; 612 | background-color: #f6f6f6 !important; 613 | } 614 | .test-text { 615 | background-color: white; 616 | margin-left: 40px; 617 | margin-right: 479px; 618 | min-height: 58px; 619 | 620 | } 621 | #modal-body div { 622 | float: left; 623 | width: 166px; 624 | display: inline-block; 625 | /* possibly also height: 300px; */ 626 | } 627 | #modal-body div p span { 628 | font-family: serif;} -------------------------------------------------------------------------------- /bot-application/static/css/style.css~: -------------------------------------------------------------------------------- 1 | @import url(http://weloveiconfonts.com/api/?family=fontawesome|iconicstroke|typicons); 2 | /* fontawesome */ 3 | [class*="fontawesome-"]:before { 4 | font-family: 'FontAwesome', sans-serif; 5 | } 6 | /* iconicstroke */ 7 | [class*="iconicstroke-"]:before { 8 | font-family: 'IconicStroke', sans-serif; 9 | } 10 | /* typicons */ 11 | [class*="typicons-"]:before { 12 | font-family: 'Typicons', sans-serif; 13 | } 14 | body{ 15 | font-family:arial,sans-serif; 16 | } 17 | .chat-container { 18 | width: 300px; 19 | margin-right: 20px; 20 | float:right; 21 | overflow:hidden; 22 | } 23 | .top-header { 24 | background: #666; 25 | color: white; 26 | padding: 0.2rem; 27 | position: relative; 28 | overflow: hidden; 29 | border-bottom: 4px solid #35ac19; 30 | cursor:pointer; 31 | } 32 | .top-header:hover { 33 | background-color:#35ac19; 34 | } 35 | .top-header-tit { 36 | display: inline; 37 | font-size: 14px; 38 | } 39 | .top-header .typicons-message { 40 | display: inline-block; 41 | padding: 2px 5px 2px 5px; 42 | font-size: 20px; 43 | position: relative; 44 | top: 5px; 45 | } 46 | .top-header .typicons-minus { 47 | position: relative; 48 | top: 3px; 49 | font-size: 15px; 50 | cursor:pointer; 51 | } 52 | .top-header .typicons-plus { 53 | position: relative; 54 | top: 3px; 55 | font-size: 15px; 56 | } 57 | .top-header .typicons-times{ 58 | position: relative; 59 | top: 3px; 60 | font-size: 15px; 61 | } 62 | .top-header .left { 63 | float: left; 64 | } 65 | .top-header .right { 66 | float: right; 67 | padding-top: 5px; 68 | } 69 | .top-header > * { 70 | position: relative; 71 | } 72 | .top-header::before { 73 | content: ''; 74 | position: absolute; 75 | top: -100%; 76 | left: 0; 77 | right: 0; 78 | bottom: -100%; 79 | opacity: 0.25; 80 | background-color: #404040 81 | } 82 | .chat-box { 83 | list-style: none; 84 | background: #e5e5e5; 85 | margin: 0; 86 | padding: 0 0 50px 0; 87 | height: 280px; 88 | overflow-y: auto; 89 | } 90 | .chat-box li { 91 | padding: 0.5rem; 92 | overflow: hidden; 93 | display: flex; 94 | } 95 | .chat-box .avatar-icon { 96 | width: 40px; 97 | position: relative; 98 | } 99 | .chat-box .avatar-icon img { 100 | display: block; 101 | width: 100%; 102 | background-color:#1469A6; 103 | } 104 | .ibo .avatar-icon:after { 105 | content: ''; 106 | position: absolute; 107 | top: 0; 108 | right: 0; 109 | width: 0; 110 | height: 0; 111 | border: 5px solid white; 112 | border-left-color: transparent; 113 | border-bottom-color: transparent; 114 | } 115 | .me { 116 | justify-content: flex-end; 117 | align-items: flex-end; 118 | } 119 | .me .messages { 120 | order: 1; 121 | border-bottom-right-radius: 0; 122 | } 123 | .me .avatar-icon { 124 | order: 2; 125 | } 126 | .me .avatar-icon:after { 127 | content: ''; 128 | position: absolute; 129 | bottom: 0; 130 | left: 0; 131 | width: 0; 132 | height: 0; 133 | border: 5px solid white; 134 | border-right-color: transparent; 135 | border-top-color: transparent; 136 | box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); 137 | } 138 | .messages { 139 | background: white; 140 | padding: 10px; 141 | border-radius: 2px; 142 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); 143 | } 144 | .messages p { 145 | font-size: 0.8rem; 146 | margin: 0 0 0.2rem 0; 147 | } 148 | .messages time { 149 | font-size: 0.7rem; 150 | color: #ccc; 151 | } 152 | .setting{ 153 | background-color: #e5e5e5; 154 | height: 32px; 155 | padding-top: 2px; 156 | border-bottom: 1px solid rgba(0,0,0,.1); 157 | } 158 | .setting .left { 159 | float: left; 160 | } 161 | .setting .right { 162 | float: right; 163 | } 164 | .iconicstroke-user{ 165 | font-size: 22px; 166 | position: relative; 167 | top: 4px; 168 | left: 10px; 169 | color: #414141; 170 | cursor:pointer; 171 | } 172 | .typicons-cog{ 173 | font-size: 23px; 174 | position: relative; 175 | top: 7px; 176 | right: 4px; 177 | color: #414141; 178 | cursor:pointer; 179 | } 180 | .fontawesome-facetime-video{ 181 | font-size: 18px; 182 | position: relative; 183 | top: 3px; 184 | color: #414141; 185 | left: 5px; 186 | cursor:pointer; 187 | } 188 | .iconicstroke-user:hover, .typicons-cog:hover,.fontawesome-facetime-video:hover{ 189 | color:#000000; 190 | } 191 | ::-webkit-scrollbar{height:14px;width:10px;background:#eee;border-left:1px solid #ddd} 192 | ::-webkit-scrollbar-thumb{background:#ddd;border:1px solid #cfcfcf} 193 | ::-webkit-scrollbar-thumb:hover{background:#b2b2b2;border:1px solid #b2b2b2} 194 | ::-webkit-scrollbar-thumb:active{background:#b2b2b2;border:1px solid #b2b2b2} 195 | @-webkit-keyframes pulse { 196 | from { 197 | opacity: 0; 198 | } 199 | to { 200 | opacity: 0.5; 201 | } 202 | } 203 | 204 | /************ 205 | * response * 206 | ************/ 207 | #response { 208 | width:320px; 209 | background-color: rgba(255, 255, 255, 0.8); 210 | } 211 | .say { 212 | width:212px; 213 | padding:8px 15px; 214 | background:rgba(50, 50, 50, 0.2); 215 | border:0px solid #dbdbdb; 216 | } 217 | .saybtn { 218 | position:relative; 219 | padding:6px 15px; 220 | left:-8px; 221 | border:2px solid #207cca; 222 | background-color:#207cca; 223 | color:#fafafa; 224 | } 225 | .saybtn:hover { 226 | background-color:#409cea; 227 | } 228 | 229 | .ace_editor { 230 | border: 1px solid lightgray; 231 | margin: auto; 232 | height: 200px; 233 | width: 80%; 234 | } 235 | .scrollmargin { 236 | height: 80px; 237 | text-align: center; 238 | } 239 | .view{ 240 | border: 1px solid lightgray; 241 | margin: auto; 242 | width: 80%; 243 | } 244 | .view div span{ 245 | margin: 20px; 246 | display: inline-block; 247 | } 248 | .view div span span{ 249 | margin: 0px; 250 | display: inline; 251 | } 252 | .output{ 253 | min-height: 70px; 254 | } 255 | .TitleBar { 256 | margin: auto; 257 | width: 80%; 258 | border: 1px solid lightgray; 259 | height: 30px; 260 | border-bottom: 0px; 261 | background-color: #FCFAFA; 262 | font-size:20px; 263 | } 264 | .TitleBar b{ 265 | margin:15px; 266 | color: #454444; 267 | } 268 | .actionbar{ 269 | margin: auto; 270 | width: 80%; 271 | } 272 | #statusBar { 273 | margin: auto; 274 | width: 80%; 275 | border: 1px solid lightgray; 276 | height: 20px; 277 | border-top: 0px; 278 | } 279 | 280 | .ace_status-indicator { 281 | color: gray; 282 | float:right; 283 | right: 0; 284 | border-left: 1px solid; 285 | } 286 | .submit { 287 | float: right; 288 | border: 1px solid #AAA; 289 | margin-left: 10px; 290 | padding: 4px; 291 | cursor: pointer; 292 | } 293 | 294 | 295 | #custominputfileds { 296 | display:none; 297 | } 298 | 299 | .blinking-cursor { 300 | font-weight: 500; 301 | font-size: 15px; 302 | color: #2E3D48; 303 | -webkit-animation: 1s blink step-end infinite; 304 | -moz-animation: 1s blink step-end infinite; 305 | -ms-animation: 1s blink step-end infinite; 306 | -o-animation: 1s blink step-end infinite; 307 | animation: 1s blink step-end infinite; 308 | } 309 | 310 | @keyframes "blink" { 311 | from, to { 312 | color: transparent; 313 | } 314 | 50% { 315 | color: black; 316 | } 317 | } 318 | 319 | @-moz-keyframes blink { 320 | from, to { 321 | color: transparent; 322 | } 323 | 50% { 324 | color: black; 325 | } 326 | } 327 | 328 | @-webkit-keyframes "blink" { 329 | from, to { 330 | color: transparent; 331 | } 332 | 50% { 333 | color: black; 334 | } 335 | } 336 | 337 | @-ms-keyframes "blink" { 338 | from, to { 339 | color: transparent; 340 | } 341 | 50% { 342 | color: black; 343 | } 344 | } 345 | 346 | @-o-keyframes "blink" { 347 | from, to { 348 | color: transparent; 349 | } 350 | 50% { 351 | color: black; 352 | } 353 | } 354 | #submit:disabled,#SubmitMCQ :disabled { 355 | background-color: white; 356 | } 357 | #submit,#SubmitMCQ { 358 | background: #35ac19; 359 | color: wheat; 360 | } 361 | .submit:hover { 362 | box-shadow: 1px 1px 3px gray; 363 | } 364 | .submit:disabled { 365 | box-shadow: unset; 366 | cursor: unset; 367 | color: lightgrey !important; 368 | background-color: #f6f6f6 !important; 369 | } 370 | #compiler::first-letter { 371 | text-transform: uppercase; 372 | } 373 | @media only screen and (max-height: 480px) { 374 | .chat-box { 375 | height: calc(100vh - 180px); 376 | } 377 | 378 | } 379 | #response{ 380 | width: calc(100% + 20px); 381 | } 382 | @media only screen and (max-Width: 340px) { 383 | .chat-container { 384 | width: calc(100vw - 20px); 385 | max-width: 300px; 386 | margin: auto 10px; 387 | } 388 | .say { 389 | width: calc(100% - 108px); 390 | } 391 | 392 | } 393 | .view { 394 | white-space: pre-wrap; /* Since CSS 2.1 */ 395 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 396 | white-space: -pre-wrap; /* Opera 4-6 */ 397 | white-space: -o-pre-wrap; /* Opera 7 */ 398 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 399 | } 400 | 401 | #QI { 402 | overflow-x: hidden; 403 | } 404 | 405 | .slide { 406 | opacity: 0; 407 | position: relative; 408 | font-family: Arial; 409 | font-size: 14px; 410 | /*line-height: 50px;*/ 411 | right: -100%; 412 | width:100%; 413 | } 414 | 415 | /*.choice { 416 | -webkit-column-count: 2; 417 | -moz-column-count: 2; 418 | column-count: 2; 419 | }*/ 420 | .MCanswer { 421 | display: inline-block; 422 | vertical-align: top; 423 | } 424 | -------------------------------------------------------------------------------- /bot-application/static/css/temporary.css: -------------------------------------------------------------------------------- 1 | .chat_window{ 2 | margin-left: 50%; 3 | height: calc(100vh - 120px); 4 | } 5 | .messages{ 6 | height: calc(100vh - 250px); 7 | } 8 | 9 | .messages .message.left .text { 10 | color: black !important; 11 | font-weight: inherit; 12 | } 13 | 14 | #msg_input{ 15 | color: black; 16 | } 17 | -------------------------------------------------------------------------------- /bot-application/static/js/bind.js: -------------------------------------------------------------------------------- 1 | var data=[]; 2 | 3 | function addBr(text){ 4 | return text.replace(/\n/g, "
"); 5 | 6 | } 7 | var Message; 8 | Message = function (arg) { 9 | this.text = arg.text, this.message_side = arg.message_side; 10 | this.draw = function (_this) { 11 | return function () { 12 | var $message; 13 | $message = $($('.message_template').clone().html()); 14 | $message.addClass(_this.message_side).find('.text').html(addBr(_this.text)); 15 | $('.messages').append($message); 16 | return setTimeout(function () { 17 | return $message.addClass('appeared'); 18 | }, 0); 19 | }; 20 | }(this); 21 | return this; 22 | }; 23 | 24 | 25 | function showBotMessage(msg){ 26 | message = new Message({ 27 | text: msg, 28 | message_side: 'left' 29 | }); 30 | message.draw(); 31 | $messages.animate({ scrollTop: $messages.prop('scrollHeight') }, 300); 32 | } 33 | function showUserMessage(msg){ 34 | $messages = $('.messages'); 35 | message = new Message({ 36 | text: msg, 37 | message_side: 'right' 38 | }); 39 | message.draw(); 40 | $messages.animate({ scrollTop: $messages.prop('scrollHeight') }, 300); 41 | $('#msg_input').val(''); 42 | } 43 | function sayToBot(text){ 44 | document.getElementById("msg_input").placeholder = "Type your messages here..." 45 | $.post("/chat", 46 | { 47 | //csrfmiddlewaretoken:csrf, 48 | text:text, 49 | }, 50 | function(jsondata, status){ 51 | if(jsondata["status"]=="success"){ 52 | response=jsondata["response"]; 53 | 54 | if(response){showBotMessage(response);} 55 | } 56 | }); 57 | 58 | } 59 | 60 | getMessageText = function () { 61 | var $message_input; 62 | $message_input = $('.message_input'); 63 | return $message_input.val(); 64 | }; 65 | 66 | $("#say").keypress(function(e) { 67 | if(e.which == 13) { 68 | $("#saybtn").click(); 69 | } 70 | }); 71 | 72 | $('.send_message').click(function (e) { 73 | msg = getMessageText(); 74 | if(msg){ 75 | showUserMessage(msg); 76 | sayToBot(msg); 77 | $('.message_input').val('');} 78 | }); 79 | 80 | $('.message_input').keyup(function (e) { 81 | if (e.which === 13) { 82 | msg = getMessageText(); 83 | if(msg){ 84 | showUserMessage(msg); 85 | sayToBot(msg); 86 | $('.message_input').val('') ;} 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /bot-application/static/js/jquery.timeago.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Timeago is a jQuery plugin that makes it easy to support automatically 3 | * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). 4 | * 5 | * @name timeago 6 | * @version 1.5.3 7 | * @requires jQuery v1.2.3+ 8 | * @author Ryan McGeary 9 | * @license MIT License - http://www.opensource.org/licenses/mit-license.php 10 | * 11 | * For usage and examples, visit: 12 | * http://timeago.yarp.com/ 13 | * 14 | * Copyright (c) 2008-2015, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) 15 | */ 16 | 17 | (function (factory) { 18 | if (typeof define === 'function' && define.amd) { 19 | // AMD. Register as an anonymous module. 20 | define(['jquery'], factory); 21 | } else if (typeof module === 'object' && typeof module.exports === 'object') { 22 | factory(require('jquery')); 23 | } else { 24 | // Browser globals 25 | factory(jQuery); 26 | } 27 | }(function ($) { 28 | $.timeago = function(timestamp) { 29 | if (timestamp instanceof Date) { 30 | return inWords(timestamp); 31 | } else if (typeof timestamp === "string") { 32 | return inWords($.timeago.parse(timestamp)); 33 | } else if (typeof timestamp === "number") { 34 | return inWords(new Date(timestamp)); 35 | } else { 36 | return inWords($.timeago.datetime(timestamp)); 37 | } 38 | }; 39 | var $t = $.timeago; 40 | 41 | $.extend($.timeago, { 42 | settings: { 43 | refreshMillis: 60000, 44 | allowPast: true, 45 | allowFuture: false, 46 | localeTitle: false, 47 | cutoff: 0, 48 | autoDispose: true, 49 | strings: { 50 | prefixAgo: null, 51 | prefixFromNow: null, 52 | suffixAgo: "ago", 53 | suffixFromNow: "from now", 54 | inPast: 'any moment now', 55 | seconds: "less than a minute", 56 | minute: "about a minute", 57 | minutes: "%d minutes", 58 | hour: "about an hour", 59 | hours: "about %d hours", 60 | day: "a day", 61 | days: "%d days", 62 | month: "about a month", 63 | months: "%d months", 64 | year: "about a year", 65 | years: "%d years", 66 | wordSeparator: " ", 67 | numbers: [] 68 | } 69 | }, 70 | 71 | inWords: function(distanceMillis) { 72 | if (!this.settings.allowPast && ! this.settings.allowFuture) { 73 | throw 'timeago allowPast and allowFuture settings can not both be set to false.'; 74 | } 75 | 76 | var $l = this.settings.strings; 77 | var prefix = $l.prefixAgo; 78 | var suffix = $l.suffixAgo; 79 | if (this.settings.allowFuture) { 80 | if (distanceMillis < 0) { 81 | prefix = $l.prefixFromNow; 82 | suffix = $l.suffixFromNow; 83 | } 84 | } 85 | 86 | if (!this.settings.allowPast && distanceMillis >= 0) { 87 | return this.settings.strings.inPast; 88 | } 89 | 90 | var seconds = Math.abs(distanceMillis) / 1000; 91 | var minutes = seconds / 60; 92 | var hours = minutes / 60; 93 | var days = hours / 24; 94 | var years = days / 365; 95 | 96 | function substitute(stringOrFunction, number) { 97 | var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; 98 | var value = ($l.numbers && $l.numbers[number]) || number; 99 | return string.replace(/%d/i, value); 100 | } 101 | 102 | var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || 103 | seconds < 90 && substitute($l.minute, 1) || 104 | minutes < 45 && substitute($l.minutes, Math.round(minutes)) || 105 | minutes < 90 && substitute($l.hour, 1) || 106 | hours < 24 && substitute($l.hours, Math.round(hours)) || 107 | hours < 42 && substitute($l.day, 1) || 108 | days < 30 && substitute($l.days, Math.round(days)) || 109 | days < 45 && substitute($l.month, 1) || 110 | days < 365 && substitute($l.months, Math.round(days / 30)) || 111 | years < 1.5 && substitute($l.year, 1) || 112 | substitute($l.years, Math.round(years)); 113 | 114 | var separator = $l.wordSeparator || ""; 115 | if ($l.wordSeparator === undefined) { separator = " "; } 116 | return $.trim([prefix, words, suffix].join(separator)); 117 | }, 118 | 119 | parse: function(iso8601) { 120 | var s = $.trim(iso8601); 121 | s = s.replace(/\.\d+/,""); // remove milliseconds 122 | s = s.replace(/-/,"/").replace(/-/,"/"); 123 | s = s.replace(/T/," ").replace(/Z/," UTC"); 124 | s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 125 | s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 126 | return new Date(s); 127 | }, 128 | datetime: function(elem) { 129 | var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); 130 | return $t.parse(iso8601); 131 | }, 132 | isTime: function(elem) { 133 | // jQuery's `is()` doesn't play well with HTML5 in IE 134 | return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); 135 | } 136 | }); 137 | 138 | // functions that can be called via $(el).timeago('action') 139 | // init is default when no action is given 140 | // functions are called with context of a single element 141 | var functions = { 142 | init: function() { 143 | var refresh_el = $.proxy(refresh, this); 144 | refresh_el(); 145 | var $s = $t.settings; 146 | if ($s.refreshMillis > 0) { 147 | this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); 148 | } 149 | }, 150 | update: function(timestamp) { 151 | var date = (timestamp instanceof Date) ? timestamp : $t.parse(timestamp); 152 | $(this).data('timeago', { datetime: date }); 153 | if ($t.settings.localeTitle) { 154 | $(this).attr("title", date.toLocaleString()); 155 | } 156 | refresh.apply(this); 157 | }, 158 | updateFromDOM: function() { 159 | $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); 160 | refresh.apply(this); 161 | }, 162 | dispose: function () { 163 | if (this._timeagoInterval) { 164 | window.clearInterval(this._timeagoInterval); 165 | this._timeagoInterval = null; 166 | } 167 | } 168 | }; 169 | 170 | $.fn.timeago = function(action, options) { 171 | var fn = action ? functions[action] : functions.init; 172 | if (!fn) { 173 | throw new Error("Unknown function name '"+ action +"' for timeago"); 174 | } 175 | // each over objects here and call the requested function 176 | this.each(function() { 177 | fn.call(this, options); 178 | }); 179 | return this; 180 | }; 181 | 182 | function refresh() { 183 | var $s = $t.settings; 184 | 185 | //check if it's still visible 186 | if ($s.autoDispose && !$.contains(document.documentElement,this)) { 187 | //stop if it has been removed 188 | $(this).timeago("dispose"); 189 | return this; 190 | } 191 | 192 | var data = prepareData(this); 193 | 194 | if (!isNaN(data.datetime)) { 195 | if ( $s.cutoff === 0 || Math.abs(distance(data.datetime)) < $s.cutoff) { 196 | $(this).text(inWords(data.datetime)); 197 | } else { 198 | if ($(this).attr('title').length > 0) { 199 | $(this).text($(this).attr('title')); 200 | } 201 | } 202 | } 203 | return this; 204 | } 205 | 206 | function prepareData(element) { 207 | element = $(element); 208 | if (!element.data("timeago")) { 209 | element.data("timeago", { datetime: $t.datetime(element) }); 210 | var text = $.trim(element.text()); 211 | if ($t.settings.localeTitle) { 212 | element.attr("title", element.data('timeago').datetime.toLocaleString()); 213 | } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { 214 | element.attr("title", text); 215 | } 216 | } 217 | return element.data("timeago"); 218 | } 219 | 220 | function inWords(date) { 221 | return $t.inWords(distance(date)); 222 | } 223 | 224 | function distance(date) { 225 | return (new Date().getTime() - date.getTime()); 226 | } 227 | 228 | // fix for IE6 suckage 229 | document.createElement("abbr"); 230 | document.createElement("time"); 231 | })); 232 | -------------------------------------------------------------------------------- /bot-application/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% block header %}{% endblock %} 17 | 18 | 19 | 20 |
21 | {% block content %}{% endblock %} 22 |
23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /bot-application/templates/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block header %} 4 | 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 |
11 |
12 |
13 |
14 |
    15 |
    16 |
    17 | 18 |
    19 |
    20 |
    send
    21 |
    22 |
    23 |
    24 |
    25 |
  • 26 |
    27 |
    28 |
    29 |
    30 |
  • 31 |
    32 |
    33 |
    34 |
    35 | 36 | {% endblock %} 37 | 38 | {% block other_footers %} 39 | 40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | > The bot is outdated and not maintained anymore 2 | 3 | # Site bot 4 | A site bot build using [rasa-nlu](http://rasa.ai). 5 | 6 | ## Setup 7 | 1. if you are using Ubuntu 8 | `pip install -r requirements.txt` 9 | 10 | 2. If you are using windows machine 11 | `pip install -r requirements.txt` 12 | The above command will fail for few packages like `mitie`. 13 | So you have to install the following 14 | `pip install numpy,scipy,sklearn,spacy` 15 | If you have error while downloading any of these packages download whl files from http://www.lfd.uci.edu/~gohlke/pythonlibs/ 16 | 17 | 2. You will have two parts in this projects 18 | 1. AI-Engine 19 | 20 | The AI Engine part takes care of Natural language understanding 21 | It is built using a open source NLU agent called rasa-nlu 22 | 23 | 2. Bot application 24 | 25 | The bot application is a flask application that has a Client(Simple UI chat interface), 26 | a backend that fetches event details pydelhi conference website 27 | 28 | 3. Initially you need to train your bot to do that you need two json files `config` and 'training_data'. 29 | 30 | 4. To train your model you can use either 'spacy' or 'mitie' algorithm. For my application I am using `spacy`. 31 | 32 | If you are using `mitie` you should download a `.dat` file from 33 | https://github.com/mit-nlp/MITIE/releases/download/v0.4/MITIE-models-v0.2.tar.bz2 34 | 35 | If you're using spacy run the following before training 36 | 37 | ``` 38 | python -m spacy download en_core_web_md 39 | python -m spacy link en_core_web_md en 40 | ``` 41 | 42 | 5. To train your ML model run. The training will take some time. 43 | 44 | ``` 45 | python -m rasa_nlu.train -c AI-engine/config_spacy.json --data AI-engine/data/sitebot-data.json 46 | ``` 47 | 48 | 5. Once the training is done you will have a `models` folder created with a timestamp 49 | 50 | 6. Now you have to host this model for your bot application to use 51 | 52 | `python -m rasa_nlu.server -c AI-engine/config_spacy.json --path ./models/nlu/` 53 | 54 | 7. Now that we have the AI-Engine up and running.Let's setup the knowledge base for the bot run `extract.py` under bot_applications 55 | 56 | `python bot-applicaiton/extract.py` 57 | You will have a sqlite `app.db` created 58 | 59 | 8. To run the application run 60 | 61 | `python app.py` 62 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | Flask-Admin 3 | Flask-Migrate 4 | Flask-Script 5 | Flask-SQLAlchemy 6 | gevent 7 | numpy 8 | rasa-nlu 9 | requests 10 | spacy 11 | sklearn==0.19.1 12 | sklearn_crfsuite --------------------------------------------------------------------------------