diff --git a/EmotionDetection/__init__.py b/EmotionDetection/__init__.py new file mode 100644 index 000000000..c533aa331 --- /dev/null +++ b/EmotionDetection/__init__.py @@ -0,0 +1,5 @@ +# __init__.py +# The initialization of the Package + +# from . emotion_detection import emotion_detector +from . import emotion_detection diff --git a/EmotionDetection/emotion_detection.py b/EmotionDetection/emotion_detection.py new file mode 100644 index 000000000..aa2c916e7 --- /dev/null +++ b/EmotionDetection/emotion_detection.py @@ -0,0 +1,71 @@ +# emotion_detection.py + +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" +} + +# 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}} + + 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") + # if there is emotion predictions, export the text + if "emotionPredictions" in response_data and response_data["emotionPredictions"]: + emotions = response_data["emotionPredictions"][0]["emotion"] + + # 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 {"error": f"Watson API Error: {response.status_code}, {response.text}"} + + + except requests.exceptions.RequestException as e: + return f"Request failed: {str(e)}" + + 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/). diff --git a/server.py b/server.py new file mode 100644 index 000000000..6ac25da1c --- /dev/null +++ b/server.py @@ -0,0 +1,59 @@ +''' +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') + + 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') + + if response_none_data['dominant_emotion'] is None: + return "Invalid text! Please try again." + + # 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(response), 500 + + 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(): + """ + Start Web Page with the index.html file in the templates folder. + """ + return render_template('index.html') + +if __name__ == '__main__': + app.run(host="0.0.0.0", port=5000, debug=True) + \ No newline at end of file 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()