Skip to content

Emotionallity Detection update #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions classifiers/text_analysis/emotionality_detection/__init__.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import requests
from extractors.util.spacy import SpacySingleton
from pydantic import BaseModel
from LeXmo import LeXmo

INPUT_EXAMPLE = {
"text": """As Harry went inside the Chamber of Secrets, he discovered the Basilisk's layer. Before him stood Tom
Riddle, with his wand. Harry was numb for a second as if he had seen a ghost. Moments later the giant
snake attacked Harry but fortunately, Harry dodged and ran into one of the sewer lines while the serpent
followed. The Basilisk couldn't be killed with bare hands but only with a worthy weapon."""
"text": "I did not know that you were coming! I am very glad to see you. If you would tell me sooner, I would have baked some cookies, though.",
"apiKey": "<API_KEY_GOES_HERE>"
}


class EmotionalityDetectionModel(BaseModel):
text: str
apiKey: str
text: str

class Config:
schema_example = {"example": INPUT_EXAMPLE}
class Config:
schema_example = {"example": INPUT_EXAMPLE}

def emotionality_detection(req: EmotionalityDetectionModel):
"""BERT model for emotion detection"""
headers = {"Authorization": f"Bearer {req.apiKey}"}
data = {"inputs": req.text}
try:
response = requests.post("https://api-inference.huggingface.co/models/j-hartmann/emotion-english-distilroberta-base", headers=headers, json=data)
response_json = response.json()
ner_positions = []

def emotionality_detection(request: EmotionalityDetectionModel):
"""Fetches emotions from a given text"""
nlp = SpacySingleton.get_nlp("en_core_web_sm")
doc = nlp(req.text)

text = request.text
try:
emo = LeXmo.LeXmo(text)
del emo["text"]
del emo["positive"]
del emo["negative"]
unique = dict(zip(emo.values(), emo.keys()))
if len(unique) == 1:
return "Cannot determine emotion"
else:
emo = max(emo, key=emo.get)
return {"emotion": emo}
except ValueError:
return "Valid text required"
for item in response_json:
start = item["start"]
end = item["end"]
span = doc.char_span(start, end, alignment_mode="expand")
ner_positions.append((item["entity_group"], span.start, span.end))
return {"entities": ner_positions}
except Exception as e:
return f"That didn't work. Did you provide a valid API key? Go error: {e} and message: {response_json}"
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
```python
from LeXmo import LeXmo

def emotionality_detection(text:str) -> str:
"""
@param text: text to check
@return: either 'anger', 'fear', 'anticipation', 'trust', 'surprise', 'sadness', 'joy' or 'disgust' depending on the score
"""
emo = LeXmo.LeXmo(text)
del emo["text"]
del emo["positive"]
del emo["negative"]
emo = max(emo, key=emo.get)
return emo

import requests
import spacy

def emotionality_detection(text, api_key):
headers = {"Authorization": f"Bearer {api_key}"}
data = {"inputs": text}
try:
response = requests.post("https://api-inference.huggingface.co/models/j-hartmann/emotion-english-distilroberta-base", headers=headers, json=data)
response_json = response.json()
ner_positions = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is supposed to be a classification brick and not an extraction one. This code tries to extract entities from a text and yield them, which is not how this model works. The output of the model returns a list containing a dict like this: [[{'label': 'disgust', 'score': 0.8062547445297241}, {'label': 'sadness', 'score': 0.107185959815979}, {'label': 'anger', 'score': 0.06451956927776337}, {'label': 'fear', 'score': 0.014504954218864441}, {'label': 'neutral', 'score': 0.0030063888989388943}, {'label': 'joy', 'score': 0.0026550842449069023}, {'label': 'surprise', 'score': 0.0018732782918959856}]]

Doing NER won't work.


nlp = spacy.load("en_core_web_sm")
doc = nlp(text)

for item in response_json:
start = item["start"]
end = item["end"]
span = doc.char_span(start, end, alignment_mode="expand")
ner_positions.append((item["entity_group"], span.start, span.end))
return ner_positions
except Exception as e:
return f"That didn't work. Did you provide a valid API key? Go error: {e} and message: {response_json}"

# ↑ necessary bricks function
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Common code should be like this:

Suggested change
nlp = spacy.load("en_core_web_sm")
doc = nlp(text)
for item in response_json:
start = item["start"]
end = item["end"]
span = doc.char_span(start, end, alignment_mode="expand")
ner_positions.append((item["entity_group"], span.start, span.end))
return ner_positions
except Exception as e:
return f"That didn't work. Did you provide a valid API key? Go error: {e} and message: {response_json}"
# ↑ necessary bricks function
import requests
def emotionality_detection(text, api_key):
headers = {"Authorization": f"Bearer {api_key}"}
data = {"inputs": text}
try:
response = requests.post("https://api-inference.huggingface.co/models/j-hartmann/emotion-english-distilroberta-base", headers=headers, json=data)
response_json = response.json()
# flatten the list of lists
flat_list = [item for sublist in response_json for item in sublist]
# find the item with the highest score
max_item = max(flat_list, key=lambda x: x["score"])
# retrieve the label of the item with the highest score
max_label = max_item["label"]
return max_label
except Exception as e:
return f"That didn't work. Did you provide a valid API key? Go error: {e} and message: {response_json}"
# ↑ necessary bricks function
# -----------------------------------------------------------------------------------------
# ↓ example implementation
def example_integration():
hf_api_key = "<API_KEY_GOES_HERE>"
texts = ["What a great day to go to the beach.", "Sorry to hear that. CAn I help you?", "Why the hell would you do that?"]
for text in texts:
output = emotionality_detection(text, api_key=hf_api_key)
print(output)
example_integration()

# -----------------------------------------------------------------------------------------
# ↓ example implementation

def example_integration():
texts = ["I am scared to continue.", "Oh my goodness it was the best evening ever, hype!"]
for text in texts:
print(f"\"{text}\" has emotion: {emotionality_detection(text)}")
def emotionality_detection():
hf_api_key = "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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SvenjaKern Please watch out to never include API keys in your git commits. Please deactivate this API key and generate a new one. This is a public repository, which are often scanned for keys like this which can then be abused.

texts = ["What a great day to go to the beach.", "Sorry to hear that. CAn I help you?", "Why the hell would you do that?"]
for text in texts:
output = emotion_detection(text, api_key=hf_api_key)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name of the function call doesn't match up to the actual function.

print(output)

example_integration()
```
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
```python
#expects labeling task to have labels ["anger", "fear", "anticipation", "trust", "surprise", "sadness", "joy", "disgust"]
from LeXmo import LeXmo
import requests

ATTRIBUTE: str = "text" # only text attributes
ATTRIBUTE: str = "text"
API_KEY: str = "<API_KEY_GOES_HERE>"

def emotionality_detection(record):
text = record[ATTRIBUTE].text # SpaCy document, hence we need to call .text to get the string
emo = LeXmo.LeXmo(text)
del emo["text"]
del emo["positive"]
del emo["negative"]
emo = max(emo, key=emo.get)

return emo
headers = {"Authorization": f"Bearer {API_KEY}"}
data = {"inputs": record[ATTRIBUTE].text}
try:
response = requests.post("https://api-inference.huggingface.co/models/j-hartmann/emotion-english-distilroberta-base", headers=headers, json=data)
response_json = response.json()
ner_positions = []
for item in response_json:
start = item["start"]
end = item["end"]
span = record[ATTRIBUTE].char_span(start, end, alignment_mode="expand")
yield item["entity_group"], span.start, span.end
except Exception as e:
return f"That didn't work. Did you provide a valid API key? Go error: {e} and message: {response_json}"
```
37 changes: 20 additions & 17 deletions classifiers/text_analysis/emotionality_detection/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,31 @@ def get_config():
"text_analysis",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would add this to the "llm" category as well as this is using a roberta model from HuggingFace.

], # first entry should be parent directory
# bricks integrator information
integrator_inputs={
integrator_inputs={
"name": "emotionality_detection",
"refineryDataType": RefineryDataType.TEXT.value,
"globalComment": "Only for english text.\nWorks best with longer texts since scores for each word are accumulated.",
"outputs": [
"anger",
"fear",
"anticipation",
"trust",
"surprise",
"sadness",
"joy",
"disgust",
"anger",
"disgust",
"fear",
"joy",
"sadness",
"neutral",
"suprise"
],
"variables": {
"ATTRIBUTE": {
"selectionType": SelectionType.CHOICE.value,
"addInfo": [
"API_KEY": {
"selectionType": SelectionType.STRING.value,
"defaultValue": "<API_KEY_GOES_HERE>",
"addInfo": [BricksVariableType.GENERIC_STRING.value],
},
"ATTRIBUTE": {
"selectionType": SelectionType.CHOICE.value,
"addInfo": [
BricksVariableType.ATTRIBUTE.value,
BricksVariableType.GENERIC_STRING.value,
],
}
],
},
},
},
)
},
)