From 6890c1412db642b96b74e1145b3e5f1342b30a06 Mon Sep 17 00:00:00 2001 From: Kai Du Date: Sat, 19 Nov 2016 14:41:10 +0000 Subject: [PATCH 1/7] Skeleton --- generate_reply.py | 76 +---------------------------------------------- 1 file changed, 1 insertion(+), 75 deletions(-) diff --git a/generate_reply.py b/generate_reply.py index 2ef42c8..b343025 100644 --- a/generate_reply.py +++ b/generate_reply.py @@ -1,77 +1,3 @@ -import random -from linguistic import getPOS -from sentiment import getSentiment - -greetings = [ "hi", "hello", "hey", "yo", "greetings" ] -greetings_responses = [ "Hi there." , "Greetings human.", "Hello there.", "Hey." ] - -# Returns JJ if sentence structure is You Are {word}+ JJ {word}+. -def findYouAreJJ(pos): - foundYou = False - foundAre = False - - for e in pos: - if e[0].lower() == 'you': - foundYou = True - continue - if e[0].lower() == 'are': - foundAre = True - continue - if foundYou and not foundAre: - return False - if foundAre and e[1] == 'JJ': - return e[0] - return False - -# Returns JJ if sentence structure is I Am {word}+ JJ {word}+. -def findIAmJJ(pos): - foundYou = False - foundAre = False - - for e in pos: - if e[0].lower() == 'i': - foundYou = True - continue - if e[0].lower() == 'am': - foundAre = True - continue - if foundYou and not foundAre: - return False - if foundAre and e[1] == 'JJ': - return e[0] - return False - # Generates a bot response from a user message def generateReply(message): - pos = getPOS(message) - tokens = message.split(" ") - sentiment = getSentiment(message) - - # If first word of message is an element of greetings - if len(tokens) > 0 and tokens[0].lower() in greetings: - return random.choice(greetings_responses) # Then respond with a greeting - - # If user said 'You are ... {adjective} ...' - youAreJJ = findYouAreJJ(pos) - if youAreJJ: - if sentiment >= 0.5: - return "Thank you, I know I'm "+youAreJJ+"." - else: - return "No! I'm not "+youAreJJ+"!" - - # If user said 'I am ... {adjective} ...' - IAmJJ = findIAmJJ(pos) - if IAmJJ: - if sentiment >= 0.5: - return "I'm happy for you that you're "+IAmJJ+"." - else: - return "Don't be mean on yourself. I'm sure you're not really "+IAmJJ+"!" - - if sentiment >= 0.5: - return "I'm happy to hear that!" - else: - return "I feel sad about that." - -print(generateReply("I am cool")) - - + return "I don't understand." # Otherwise the bot doesn't understand what the user said \ No newline at end of file From 166645c6f2d84cd9db6798df9c34446a3e823761 Mon Sep 17 00:00:00 2001 From: Kai Du Date: Mon, 21 Nov 2016 14:08:02 +0000 Subject: [PATCH 2/7] Minor fix --- README.md | 7 ++++--- generate_reply_completed.py | 18 +++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c2596a3..374cda3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# cbot +#### The Project A chatbot project, aimed at students building there first hack attempt using Microsoft Cognitive Services and the Python SDK. The chatbot is far from realistic, but hopefully will give you more an idea of what Microsoft Cognitive Services can be used for. -Prerequisites: -sudo pip install git+https://github.com/dpallot/simple-websocket-server.git \ No newline at end of file +#### Prerequisites: +- Python 3 installed +- https://github.com/dpallot/simple-websocket-server \ No newline at end of file diff --git a/generate_reply_completed.py b/generate_reply_completed.py index 8779b4e..b332f12 100644 --- a/generate_reply_completed.py +++ b/generate_reply_completed.py @@ -12,7 +12,7 @@ def generateReply(message): # If error occurred getting POS if not pos: - return "I am not functioning at the moment." + return "I am not functioning at the moment. Perhaps check your API keys." # If user greeted if pos[0][0] in greetings: @@ -49,7 +49,7 @@ def findYouAreJJ(pos): if e[0].lower() == 'you': foundYou = True continue - if e[0].lower() == 'are': + if e[0].lower() == 'are' and foundYou: foundAre = True continue if foundYou and not foundAre: @@ -61,18 +61,18 @@ def findYouAreJJ(pos): # Returns JJ if sentence structure is I Am {word}+ JJ {word}+. def findIAmJJ(pos): - foundYou = False - foundAre = False + foundI = False + foundAm = False for e in pos: if e[0].lower() == 'i': - foundYou = True + foundI = True continue - if e[0].lower() == 'am': - foundAre = True + if e[0].lower() == 'am' and foundI: + foundAm = True continue - if foundYou and not foundAre: + if foundI and not foundAm: return False - if foundAre and e[1] == 'JJ': + if foundAm and e[1] == 'JJ': return e[0] return False \ No newline at end of file From d4835799b0fdb414cdd65ab123aee4d9b22f4f45 Mon Sep 17 00:00:00 2001 From: Kai Du Date: Mon, 21 Nov 2016 19:14:04 +0000 Subject: [PATCH 3/7] Minor refactoring --- generate_reply_completed.py | 51 ++++++++++------------ index.html | 83 ++++++++++++++++++++++++++++++------ linguistic.pyc | Bin 0 -> 1180 bytes 3 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 linguistic.pyc diff --git a/generate_reply_completed.py b/generate_reply_completed.py index b332f12..0dc0ba6 100644 --- a/generate_reply_completed.py +++ b/generate_reply_completed.py @@ -5,6 +5,22 @@ greetings = [ "hi", "hello", "hey", "yo", "greetings" ] greetings_responses = [ "Hi there." , "Greetings human.", "Hello there.", "Hey." ] +# Returns JJ if sentence structure is You Are {word}+ JJ {word}+. +def findYouAreJJ(pos): + foundYou = False + foundYouAre = False + + for e in pos: + if e[0].lower() == 'you': + foundYou = True + elif e[0].lower() == 'are' and foundYou: + foundYouAre = True + elif foundYou and not foundYouAre: + foundYou = False + elif foundYouAre and e[1] == 'JJ': + return e[0] + return False + # Generates a bot response from a user message def generateReply(message): pos = getPOS(message) @@ -15,7 +31,7 @@ def generateReply(message): return "I am not functioning at the moment. Perhaps check your API keys." # If user greeted - if pos[0][0] in greetings: + if pos[0][0].lower() in greetings: return random.choice(greetings_responses) # If user said 'You are ... {adjective} ...' @@ -40,39 +56,18 @@ def generateReply(message): return "I feel sad about that." -# Returns JJ if sentence structure is You Are {word}+ JJ {word}+. -def findYouAreJJ(pos): - foundYou = False - foundAre = False - - for e in pos: - if e[0].lower() == 'you': - foundYou = True - continue - if e[0].lower() == 'are' and foundYou: - foundAre = True - continue - if foundYou and not foundAre: - return False - if foundAre and e[1] == 'JJ': - return e[0] - return False - - # Returns JJ if sentence structure is I Am {word}+ JJ {word}+. def findIAmJJ(pos): foundI = False - foundAm = False + foundIAm = False for e in pos: if e[0].lower() == 'i': foundI = True - continue - if e[0].lower() == 'am' and foundI: - foundAm = True - continue - if foundI and not foundAm: - return False - if foundAm and e[1] == 'JJ': + elif e[0].lower() == 'am' and foundI: + foundIAm = True + elif foundI and not foundIAm: + foundI = False + elif foundIAm and e[1] == 'JJ': return e[0] return False \ No newline at end of file diff --git a/index.html b/index.html index 4286728..452b21f 100644 --- a/index.html +++ b/index.html @@ -12,24 +12,36 @@ ws.close(); }); - ws.onerror= function(event) { + ws.onerror = function(event) { location.reload(); } ws.onmessage = function(event) { - var message_received = event.data; - chat_add_message("Bot", message_received); + var message_received = event.data; + chat_add_message(message_received, false); }; // Add a message to the chat history - function chat_add_message(name, message) { - chat_add_html(""+name+": "+message+"
"); + function chat_add_message(message, isUser) { + var class_suffix = isUser ? '_user' : ''; + + var html = '\ +
\ +
\ +
\ + '+message+'\ +
\ +
\ + '; + chat_add_html(html); } + // Add HTML to the chat history function chat_add_html(html) { - $("#chat_log").append(html); - chat_scrolldown(); + $("#chat_log").append(html); + chat_scrolldown(); } + // Scrolls the chat history to the bottom function chat_scrolldown() { $("#chat_log").animate({ scrollTop: $("#chat_log")[0].scrollHeight }, 500); @@ -41,7 +53,7 @@ if (event.which === 13 && $(this).val() != ""){ var message = $(this).val(); $(this).val(""); - chat_add_message("User", message); + chat_add_message(message, true); ws.send(message); } }); @@ -53,15 +65,21 @@ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; } + body { + font-family: Helvetica; + } #chat_container { - outline: 1px solid black; - margin: 15px; + overflow: hidden; + border-radius: 15px; + border: 1px solid black; + margin: 40px 80px 0px 80px; } #chat_log { + background-color: #718392; padding: 10px; - outline: 1px solid black; + border-bottom: 1px solid black; overflow-y: scroll; - height: 200px; + height: 300px; font-size: 26px; } #chat_input_container { @@ -69,9 +87,48 @@ } #chat_input { padding: 2px; - font-size: 14px; + font-size: 18px; width: 100%; } + + .chat_line { + overflow: hidden; + width: 100%; + margin: 2px 0 12px 0; + } + .chat_triangle, .chat_triangle_user { + position: absolute; + top: 0; + width: 0; + height: 0; + border-style: solid; + left: -18px; + border-width: 0 18px 13px 0; + border-color: transparent #ffffff transparent transparent; + } + .chat_triangle_user { + left: auto; + right: -18px; + border-width: 13px 18px 0 0; + border-color: #234b9b transparent transparent transparent; + } + .chat_bubble, .chat_bubble_user { + position: relative; + float: left; + background-color: #FFF; + margin-top: 10px; + line-height: 35px; + padding: 10px 25px 10px 25px; + margin-left: 20px; + font-size: 27px; + } + .chat_bubble_user { + float: right; + margin-left: 0px; + margin-right: 20px; + background-color: #234b9b; + color: #FFF; + } diff --git a/linguistic.pyc b/linguistic.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfb7be4a191c70f03913ef649c5ff84591674ee5 GIT binary patch literal 1180 zcmZ`&OK;Oa5T3Q2XP*=hsyIL;4!Pt(nx;Jf0#(pPptg#GsB)=Xdz;#IY~$TPgOXGE zA^a^a{0V*le6wxo2}?UWv-A9B#`f=}>Px?M?9<9>~!0uY=)P)sxwx4cC|>z21^ zXy5V<4IRT<6c=b*q+yXn2vb-%)RhiJB?=1E9hNC5(s#tHaB#O)LZa{wzJr9U^g7~3nWBkfMrn^HIBfc%o$Rn#<`&B57I=Dpa>X>bR}qR(afR(7p<-2UQ&0 zY+9f@gH@UpjDL}4MRGqS>*VNrbWx@JCy99p*-Nyyuh+;u#@O820w5k}3lvRa@UfSS zCf-P@XAs(LuY0<^wNvl3TW9soc4w=;<8Au&PIqT>%j<6Yt)Q(rgqL{n^qb6kfdXQT zM_y|6fE8KT$nrFjzD_UC(mZH*p|LnRbO&Z0%{WBHQ0dTD%`eXzt>#Uz5boSFqFky; ztZVmK=IG~IXGY=2A&GeVxRfN;7lz?AG|Ye*-p;c;9V?v!owgxn zsnQkPZ!djmcFyE^=fz6axbdc>F;*GPH-S#mU}_j2sLX8sRmhnGPkUx?zV1I_e_mf% z10h4y61cnGHnOQff#7I8&rCf9Az_P>sEVp>i#72?EQ-gFHpD|w7AvA4YK+8mh@0NH zZg`)Y+vga4GZPju=#vXM)yv?yDGmNP8{CyXUatSw550rEk3DzL+wF64{SA=2g8x@_ Z8CEaGX)uZ9E5@j}q?TB Date: Mon, 21 Nov 2016 19:14:18 +0000 Subject: [PATCH 4/7] removed redundant files --- linguistic.pyc | Bin 1180 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 linguistic.pyc diff --git a/linguistic.pyc b/linguistic.pyc deleted file mode 100644 index cfb7be4a191c70f03913ef649c5ff84591674ee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1180 zcmZ`&OK;Oa5T3Q2XP*=hsyIL;4!Pt(nx;Jf0#(pPptg#GsB)=Xdz;#IY~$TPgOXGE zA^a^a{0V*le6wxo2}?UWv-A9B#`f=}>Px?M?9<9>~!0uY=)P)sxwx4cC|>z21^ zXy5V<4IRT<6c=b*q+yXn2vb-%)RhiJB?=1E9hNC5(s#tHaB#O)LZa{wzJr9U^g7~3nWBkfMrn^HIBfc%o$Rn#<`&B57I=Dpa>X>bR}qR(afR(7p<-2UQ&0 zY+9f@gH@UpjDL}4MRGqS>*VNrbWx@JCy99p*-Nyyuh+;u#@O820w5k}3lvRa@UfSS zCf-P@XAs(LuY0<^wNvl3TW9soc4w=;<8Au&PIqT>%j<6Yt)Q(rgqL{n^qb6kfdXQT zM_y|6fE8KT$nrFjzD_UC(mZH*p|LnRbO&Z0%{WBHQ0dTD%`eXzt>#Uz5boSFqFky; ztZVmK=IG~IXGY=2A&GeVxRfN;7lz?AG|Ye*-p;c;9V?v!owgxn zsnQkPZ!djmcFyE^=fz6axbdc>F;*GPH-S#mU}_j2sLX8sRmhnGPkUx?zV1I_e_mf% z10h4y61cnGHnOQff#7I8&rCf9Az_P>sEVp>i#72?EQ-gFHpD|w7AvA4YK+8mh@0NH zZg`)Y+vga4GZPju=#vXM)yv?yDGmNP8{CyXUatSw550rEk3DzL+wF64{SA=2g8x@_ Z8CEaGX)uZ9E5@j}q?TB Date: Mon, 21 Nov 2016 19:14:33 +0000 Subject: [PATCH 5/7] Changed .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 072ca34..4f71bae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **/.DS_Store api_keys.py __pycache__ -__pycache__/* \ No newline at end of file +__pycache__/* +*.pyc \ No newline at end of file From a292bb41e71037b4b1aac5332f2c1fa2ce42e490 Mon Sep 17 00:00:00 2001 From: Kai Du Date: Mon, 28 Nov 2016 17:28:23 +0000 Subject: [PATCH 6/7] Readme updated --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 374cda3..4513ced 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ A chatbot project, aimed at students building there first hack attempt using Mic The chatbot is far from realistic, but hopefully will give you more an idea of what Microsoft Cognitive Services can be used for. +Tutorial Link: https://blogs.msdn.microsoft.com/uk_faculty_connection/2016/11/28/creating-my-first-chatbot-using-microsoft-cognitive-services-and-python/ + +If you have any questions, please don't hesitate to email me at alanduu50[at]gmail[dot]com. + #### Prerequisites: - Python 3 installed - https://github.com/dpallot/simple-websocket-server \ No newline at end of file From 6e7b2ec1f2fa30ea2f504e352ce5a2ab828fdfc3 Mon Sep 17 00:00:00 2001 From: Kai Du Date: Mon, 28 Nov 2016 17:29:27 +0000 Subject: [PATCH 7/7] Minor readme change --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4513ced..1671571 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,5 @@ If you have any questions, please don't hesitate to email me at alanduu50[at]gma #### Prerequisites: - Python 3 installed -- https://github.com/dpallot/simple-websocket-server \ No newline at end of file +- Simple Websocket Server: https://github.com/dpallot/simple-websocket-server +- Microsoft Cognitive Services (free): https://www.microsoft.com/cognitive-services/en-US/subscriptions?mode=NewTrials \ No newline at end of file