From b352f80392b20e43308ce44d50ebf441e3a94713 Mon Sep 17 00:00:00 2001 From: soF0S Date: Wed, 5 Feb 2025 10:37:36 -0500 Subject: [PATCH 01/10] Added emotion_detection.py file --- emotion_detection.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 emotion_detection.py diff --git a/emotion_detection.py b/emotion_detection.py new file mode 100644 index 000000000..56f750c21 --- /dev/null +++ b/emotion_detection.py @@ -0,0 +1,34 @@ +# emotion_detection.py +’’’ +Task 2: Create an emotion detection application + using the Watson NLP library. +’’’ +import requests +import json + +URL = "https://sn-watson-emotion.labs.skills.network/v1/watson.runtime.nlp.v1/NlpService/EmotionPredict" + +HEADERS = { + "grpc-metadata-mm-model-id": "emotion_aggregated-workflow_lang_en_stock", + "Content-Type": "application/json" +} + +# Here is my emotion_detector() function. I use the Watson NLP library. +def emotion_detector(text_to_analyse): + # JSON payload + jsonPayload = {"raw_document": {"text": text_to_analyse}} + + try: + response = requests.post(URL, headers=HEADERS, json=jsonPayload) + + # response check + if response.status_code == 200: + response_data = response.json() + return response_data.get("text", "No text found in response") + else: + return f"Error: {response.status_code}, {response.text}" + + except requests.exceptions.RequestException as e: + return f"Request failed: {str(e)}" + + From e6e9d95301ae3a0fcb1a074b5b92036a8e8958bf Mon Sep 17 00:00:00 2001 From: soF0S Date: Wed, 5 Feb 2025 15:18:08 -0500 Subject: [PATCH 02/10] Modified emotion_detection.py file --- emotion_detection.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/emotion_detection.py b/emotion_detection.py index 56f750c21..34a5759bb 100644 --- a/emotion_detection.py +++ b/emotion_detection.py @@ -1,8 +1,7 @@ # emotion_detection.py -’’’ -Task 2: Create an emotion detection application - using the Watson NLP library. -’’’ +# Task 2: Create an emotion detection application +# using the Watson NLP library. + import requests import json @@ -13,7 +12,7 @@ "Content-Type": "application/json" } -# Here is my emotion_detector() function. I use the Watson NLP library. +# Here is my emotion_detector function. I use the Watson NLP library. def emotion_detector(text_to_analyse): # JSON payload jsonPayload = {"raw_document": {"text": text_to_analyse}} @@ -21,14 +20,24 @@ def emotion_detector(text_to_analyse): try: response = requests.post(URL, headers=HEADERS, json=jsonPayload) + # This is to Check ALL Raw Response + # print("Raw Response:", response.text) + # response check if response.status_code == 200: response_data = response.json() - return response_data.get("text", "No text found in response") + + #return response_data.get("text", "No text found in response") + # if there is emotion predictions, export the text + if "emotionPredictions" in response_data and response_data["emotionPredictions"]: + return response_data["emotionPredictions"][0]["emotionMentions"][0]["span"]["text"] + + return "No emotion predictions found" + else: return f"Error: {response.status_code}, {response.text}" except requests.exceptions.RequestException as e: return f"Request failed: {str(e)}" - + From 3d653da0488fce3c3c0f865b4ea617e31b748997 Mon Sep 17 00:00:00 2001 From: soF0S Date: Wed, 5 Feb 2025 16:57:36 -0500 Subject: [PATCH 03/10] I format the output of emotion_detector function. --- emotion_detection.py | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/emotion_detection.py b/emotion_detection.py index 34a5759bb..aa2c916e7 100644 --- a/emotion_detection.py +++ b/emotion_detection.py @@ -1,6 +1,4 @@ # emotion_detection.py -# Task 2: Create an emotion detection application -# using the Watson NLP library. import requests import json @@ -12,7 +10,7 @@ "Content-Type": "application/json" } -# Here is my emotion_detector function. I use the Watson NLP library. +# Task 2: Here is my emotion_detector function. I use the Watson NLP library. def emotion_detector(text_to_analyse): # JSON payload jsonPayload = {"raw_document": {"text": text_to_analyse}} @@ -30,12 +28,42 @@ def emotion_detector(text_to_analyse): #return response_data.get("text", "No text found in response") # if there is emotion predictions, export the text if "emotionPredictions" in response_data and response_data["emotionPredictions"]: - return response_data["emotionPredictions"][0]["emotionMentions"][0]["span"]["text"] + emotions = response_data["emotionPredictions"][0]["emotion"] - return "No emotion predictions found" + # Task 3: Set emotions & Scores + anger_score = emotions.get("anger", 0.0) + disgust_score = emotions.get("disgust", 0.0) + fear_score = emotions.get("fear", 0.0) + joy_score = emotions.get("joy", 0.0) + sadness_score = emotions.get("sadness", 0.0) + + # Task 3: Finding of dominant emotion + emotion_scores = { + "anger": anger_score, + "disgust": disgust_score, + "fear": fear_score, + "joy": joy_score, + "sadness": sadness_score + } + dominant_emotion = max(emotion_scores, key=emotion_scores.get) + + # Task 3: Creation of final dictionary + result = { + "anger": anger_score, + "disgust": disgust_score, + "fear": fear_score, + "joy": joy_score, + "sadness": sadness_score, + "dominant_emotion": dominant_emotion + } + + return result # Task 3: Format the output of the application. + + return {"error": "No emotion predictions found"} else: - return f"Error: {response.status_code}, {response.text}" + return {"error": f"Watson API Error: {response.status_code}, {response.text}"} + except requests.exceptions.RequestException as e: return f"Request failed: {str(e)}" From a3c4d65cf3e5e7e34293b8cceaf7db69cf878b31 Mon Sep 17 00:00:00 2001 From: soF0S Date: Thu, 6 Feb 2025 09:06:55 -0500 Subject: [PATCH 04/10] Packaged EmotionDetection. --- EmotionDetection/__init__.py | 4 ++++ emotion_detection.py => EmotionDetection/emotion_detection.py | 0 2 files changed, 4 insertions(+) create mode 100644 EmotionDetection/__init__.py rename emotion_detection.py => EmotionDetection/emotion_detection.py (100%) diff --git a/EmotionDetection/__init__.py b/EmotionDetection/__init__.py new file mode 100644 index 000000000..242f5008c --- /dev/null +++ b/EmotionDetection/__init__.py @@ -0,0 +1,4 @@ +# __init__.py +# The initialization of the Package + +from . emotion_detection import emotion_detector diff --git a/emotion_detection.py b/EmotionDetection/emotion_detection.py similarity index 100% rename from emotion_detection.py rename to EmotionDetection/emotion_detection.py From 314fa44657e8128e8fe4e55c172ef9c920fedd8e Mon Sep 17 00:00:00 2001 From: soF0S Date: Thu, 6 Feb 2025 11:38:27 -0500 Subject: [PATCH 05/10] UnitTest emotion detection. --- EmotionDetection/__init__.py | 3 ++- test_emotion_detection.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test_emotion_detection.py diff --git a/EmotionDetection/__init__.py b/EmotionDetection/__init__.py index 242f5008c..c533aa331 100644 --- a/EmotionDetection/__init__.py +++ b/EmotionDetection/__init__.py @@ -1,4 +1,5 @@ # __init__.py # The initialization of the Package -from . emotion_detection import emotion_detector +# from . emotion_detection import emotion_detector +from . import emotion_detection diff --git a/test_emotion_detection.py b/test_emotion_detection.py new file mode 100644 index 000000000..aef51c666 --- /dev/null +++ b/test_emotion_detection.py @@ -0,0 +1,29 @@ +# test_emotion_detection.py + +from EmotionDetection.emotion_detection import emotion_detector +import unittest + +class TestEmotionDetector(unittest.TestCase): + + def test_joy(self): + result = emotion_detector("I am glad this happened.") + self.assertEqual(result['dominant_emotion'], 'joy') + + def test_anger(self): + result = emotion_detector("I am really mad about this.") + self.assertEqual(result['dominant_emotion'], 'anger') + + def test_disgust(self): + result = emotion_detector("I feel disgusted just hearing about this.") + self.assertEqual(result['dominant_emotion'], 'disgust') + + def test_sadness(self): + result = emotion_detector("I am so sad about this.") + self.assertEqual(result['dominant_emotion'], 'sadness') + + def test_fear(self): + result = emotion_detector("I am really afraid that this will happen.") + self.assertEqual(result['dominant_emotion'], 'fear') + +if __name__ == '__main__': + unittest.main() From d7e0780feb7da30d73f129b24129d987cf0c8aee Mon Sep 17 00:00:00 2001 From: soF0S Date: Thu, 6 Feb 2025 16:12:01 -0500 Subject: [PATCH 06/10] Web Flask EmotionDetection. --- server.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 server.py diff --git a/server.py b/server.py new file mode 100644 index 000000000..1f0d30eee --- /dev/null +++ b/server.py @@ -0,0 +1,34 @@ +# server.py +# Emotion detection Flask application from text input. + +from flask import Flask, render_template, request, jsonify +from EmotionDetection.emotion_detection import emotion_detector + +app = Flask("Emotion Detector") + +@app.route('/emotionDetector', methods=['GET']) +def detect_emotion(): + # Endpoint to analyse the emotions of the given text. + text_to_analyse = request.args.get('textToAnalyze') + + # Call the emotion_detector function + response = emotion_detector(text_to_analyse) + + formatted_response = ( + f"For the given statement, the system response is " f"'anger': {response['anger']}, " + f"'disgust': {response['disgust']}, " + f"'fear': {response['fear']}, " + f"'joy': {response['joy']} and " + f"'sadness': {response['sadness']}. " + f"The dominant emotion is {response['dominant_emotion']}." + ) + return formatted_response # jsonify({"response": formatted_response}) + +@app.route("/") +def render_index_page(): + + return render_template('index.html') + +if __name__ == '__main__': + app.run(host="0.0.0.0", port=5000, debug=True) + From fded02d7d46abb3299d98e6b2fbca8250cf16c89 Mon Sep 17 00:00:00 2001 From: soF0S Date: Thu, 6 Feb 2025 17:13:50 -0500 Subject: [PATCH 07/10] Web Flask EmotionDetection ERR 400. --- server.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index 1f0d30eee..8acda101b 100644 --- a/server.py +++ b/server.py @@ -9,11 +9,29 @@ @app.route('/emotionDetector', methods=['GET']) def detect_emotion(): # Endpoint to analyse the emotions of the given text. - text_to_analyse = request.args.get('textToAnalyze') + text_to_analyse = request.args.get('textToAnalyze') + if not text_to_analyse: # if NO text, return status 400 with None to all fields. + response_none_data = { + "anger": None, + "disgust": None, + "fear": None, + "joy": None, + "sadness": None, + "dominant_emotion": None + } + # Bad Request + app.logger.warning('GET/ emotionDetector?textToAnalyze= HTTP/1.1 400 - Bad Request') + + return jsonify(response_none_data) + # Call the emotion_detector function response = emotion_detector(text_to_analyse) + # Give error if there is problem with API ! + if "error" in response: + return jsonify(emotion_result), 500 + formatted_response = ( f"For the given statement, the system response is " f"'anger': {response['anger']}, " f"'disgust': {response['disgust']}, " @@ -31,4 +49,7 @@ def render_index_page(): if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, debug=True) - + + + + From dadf72781bfb010d0876e9c5b3a0116d483c9cee Mon Sep 17 00:00:00 2001 From: soF0S Date: Thu, 6 Feb 2025 17:26:32 -0500 Subject: [PATCH 08/10] Web Flask EmotionDetection ERR Msg: Invalid text! Please try again! --- server.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index 8acda101b..740ece44d 100644 --- a/server.py +++ b/server.py @@ -22,9 +22,10 @@ def detect_emotion(): } # Bad Request app.logger.warning('GET/ emotionDetector?textToAnalyze= HTTP/1.1 400 - Bad Request') + + if response_none_data['dominant_emotion'] is None: + return "Invalid text! Please try again." - return jsonify(response_none_data) - # Call the emotion_detector function response = emotion_detector(text_to_analyse) From ff5eb49059877b4ef51afee9ce0814515215c32a Mon Sep 17 00:00:00 2001 From: soF0S Date: Thu, 6 Feb 2025 18:11:28 -0500 Subject: [PATCH 09/10] PyLint server.py code has been rated at 10/10 --- server.py | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/server.py b/server.py index 740ece44d..6ac25da1c 100644 --- a/server.py +++ b/server.py @@ -1,6 +1,7 @@ -# server.py -# Emotion detection Flask application from text input. - +''' +server.py +Emotion detection Flask application from text input. +''' from flask import Flask, render_template, request, jsonify from EmotionDetection.emotion_detection import emotion_detector @@ -8,7 +9,9 @@ @app.route('/emotionDetector', methods=['GET']) def detect_emotion(): - # Endpoint to analyse the emotions of the given text. + ''' + Endpoint to analyse the emotions of the given text. + ''' text_to_analyse = request.args.get('textToAnalyze') if not text_to_analyse: # if NO text, return status 400 with None to all fields. @@ -21,36 +24,36 @@ def detect_emotion(): "dominant_emotion": None } # Bad Request - app.logger.warning('GET/ emotionDetector?textToAnalyze= HTTP/1.1 400 - Bad Request') - + app.logger.warning('GET/ emotionDetector?textToAnalyze= HTTP/1.1 400 - Bad Request') + if response_none_data['dominant_emotion'] is None: - return "Invalid text! Please try again." + return "Invalid text! Please try again." # Call the emotion_detector function - response = emotion_detector(text_to_analyse) + response = emotion_detector(text_to_analyse) # Give error if there is problem with API ! - if "error" in response: - return jsonify(emotion_result), 500 + if "error" in response: + return jsonify(response), 500 - formatted_response = ( + formatted_response = ( f"For the given statement, the system response is " f"'anger': {response['anger']}, " - f"'disgust': {response['disgust']}, " - f"'fear': {response['fear']}, " - f"'joy': {response['joy']} and " - f"'sadness': {response['sadness']}. " - f"The dominant emotion is {response['dominant_emotion']}." + f"'disgust': {response['disgust']}, " + f"'fear': {response['fear']}, " + f"'joy': {response['joy']} and " + f"'sadness': {response['sadness']}. " + f"The dominant emotion is {response['dominant_emotion']}." ) - return formatted_response # jsonify({"response": formatted_response}) + return formatted_response # jsonify({"response": formatted_response}) @app.route("/") -def render_index_page(): - + +def render_index_page(): + """ + Start Web Page with the index.html file in the templates folder. + """ return render_template('index.html') -if __name__ == '__main__': +if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, debug=True) - - - - + \ No newline at end of file From 2e12b471731a696267a106c0aa54719c3107c51b Mon Sep 17 00:00:00 2001 From: ARISTOTLE the GREEK Date: Fri, 7 Feb 2025 07:48:02 +0100 Subject: [PATCH 10/10] Update README.md --- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f22b4324..3f882c342 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ -# Repository for final project +# Repository Subject : AI-based Text Emotion Detector Web Application + +Emotion Detector Web App + +This repository contains an AI-based Text Emotion Detector Web Application created as part of IBM's Developing AI Applications Course with Python and Flask. Emotion detection extends the analysis by extracting the emotional percentages of the phrase given for feelings of joy, sadness, anger, disgust, fear and extracts the prevailing emotion, going beyond the typical polarity provided by the basic emotion analysis. + +### > Course Info +Project Title: Developing AI Applications with Python and Flask + +Project Type: Final Project + +Course Advance Certification Provider: IBM + +### > Technologies Used + +- GIT (Cloud) +- HTML +- CSS +- JavaScript +- Python +- Watson NLP Library +- Flask + +### > Features + +- Create an Emotion Detection application using the Watson NLP library +- Format the output of the application +- Packaging the application +- Run Unit tests on your application +- Porting the application to a web environment using Flask Server +- Incorporate full error handling +- Complete static code analysis 10/10 + +### > Getting Started + +Clone or download the repository to your local machine and explore the codebase to understand the AI-based Text Emotion Detector Web Application. + +### > Contact Me + +If you have any questions, please feel free to reach out via my [email](S0F0S@hotmail.com) or [LinkedIn](https://www.linkedin.com/in/antonios-papathanasiou-33a3661b4/).