Skip to content

Commit

Permalink
Update evaluate_narrative_persuasiveness.py
Browse files Browse the repository at this point in the history
pylint + PEP8 anyway it must be checked more.. :)

```
Your code has been rated at 7.54/10 (previous run: 5.80/10, +1.74)
```
  • Loading branch information
fabriziosalmi authored May 30, 2024
1 parent eb4b5d4 commit 5c15059
Showing 1 changed file with 87 additions and 28 deletions.
115 changes: 87 additions & 28 deletions evaluate_narrative_persuasiveness.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Module for evaluating narrative and persuasiveness metrics in text.
"""

import json
import nltk
from nltk.tokenize import word_tokenize, sent_tokenize
Expand All @@ -9,65 +13,118 @@
nltk.download("stopwords", quiet=True)

# Define words indicative of narrative and persuasive content in both languages
# Define words indicative of narrative and persuasive content in both languages
narrative_keywords = {
'en': ["story", "narrative", "tale", "plot", "character", "setting", "theme", "conflict", "resolution", "event", "incident", "account", "chronicle", "saga", "anecdote", "fable", "legend", "myth", "parable", "recital", "yarn", "adventure", "episode", "journey", "quest", "scene", "sequence", "drama", "storyline", "memoir", "novel", "fable", "mythology", "biography", "autobiography", "fairy tale", "narration", "short story", "novella", "folktale"],
'it': ["storia", "racconto", "trama", "narrazione", "personaggio", "ambientazione", "tema", "conflitto", "risoluzione", "evento", "incidente", "cronaca", "saga", "aneddoto", "favola", "leggenda", "mito", "parabola", "recital", "filone", "avventura", "episodio", "viaggio", "quest", "scena", "sequenza", "dramma", "linea narrativa", "memoria", "romanzo", "favola", "mitologia", "biografia", "autobiografia", "fiaba", "narrazione", "racconto breve", "novella", "racconto popolare"]
NARRATIVE_KEYWORDS = {
'en': ["story", "narrative", "tale", "plot", "character", "setting", "theme", "conflict",
"resolution", "event", "incident", "account", "chronicle", "saga", "anecdote", "fable",
"legend", "myth", "parable", "recital", "yarn", "adventure", "episode", "journey", "quest",
"scene", "sequence", "drama", "storyline", "memoir", "novel", "mythology", "biography",
"autobiography", "fairy tale", "narration", "short story", "novella", "folktale"],
'it': ["storia", "racconto", "trama", "narrazione", "personaggio", "ambientazione", "tema",
"conflitto", "risoluzione", "evento", "incidente", "cronaca", "saga", "aneddoto", "favola",
"leggenda", "mito", "parabola", "recital", "filone", "avventura", "episodio", "viaggio",
"scena", "sequenza", "dramma", "linea narrativa", "memoria", "romanzo", "mitologia",
"biografia", "autobiografia", "fiaba", "racconto breve", "novella", "racconto popolare"]
}

argument_keywords = {
'en': ["because", "therefore", "thus", "hence", "since", "consequently", "as a result", "for this reason", "due to", "accordingly", "thereby", "ergo", "for", "because of", "on account of", "owing to", "seeing that", "inasmuch as", "as", "so", "henceforth", "thusly", "thereupon", "wherefore", "considering that", "due to the fact that", "in light of", "as a consequence", "resulting from", "reason being", "for the purpose of", "on these grounds", "by reason of", "in view of"],
'it': ["perché", "quindi", "così", "pertanto", "poiché", "di conseguenza", "come risultato", "per questa ragione", "a causa di", "di conseguenza", "pertanto", "ergo", "per", "a causa di", "a motivo di", "dato che", "in quanto", "poiché", "visto che", "dunque", "da ciò", "perciò", "da allora", "per conseguenza", "considerando che", "a causa del fatto che", "alla luce di", "come conseguenza", "risultante da", "ragione essendo", "allo scopo di", "su queste basi", "per ragione di", "in vista di"]
ARGUMENT_KEYWORDS = {
'en': ["because", "therefore", "thus", "hence", "since", "consequently", "as a result",
"for this reason", "due to", "accordingly", "thereby", "ergo", "for", "because of",
"on account of", "owing to", "seeing that", "inasmuch as", "as", "so", "henceforth",
"thusly", "thereupon", "wherefore", "considering that", "due to the fact that",
"in light of", "as a consequence", "resulting from", "reason being", "for the purpose of",
"on these grounds", "by reason of", "in view of"],
'it': ["perché", "quindi", "così", "pertanto", "poiché", "di conseguenza", "come risultato",
"per questa ragione", "a causa di", "di conseguenza", "pertanto", "ergo", "per", "a causa di",
"a motivo di", "dato che", "in quanto", "visto che", "dunque", "da ciò", "perciò", "da allora",
"per conseguenza", "considerando che", "a causa del fatto che", "alla luce di",
"come conseguenza", "risultante da", "ragione essendo", "allo scopo di", "su queste basi",
"per ragione di", "in vista di"]
}

persuasive_keywords = {
'en': ["must", "should", "need", "important", "significant", "imperative", "essential", "vital", "crucial", "necessary", "require", "obligatory", "mandatory", "compulsory", "unavoidable", "key", "pivotal", "critical", "urgent", "indispensable", "pressing", "requisite", "paramount", "vital", "decisive", "weighty", "fundamental", "integral", "major", "substantial", "consequential", "compelling", "imperative", "prerequisite", "salient", "urgent", "mandatory"],
'it': ["deve", "dovrebbe", "bisogno", "importante", "significativo", "imperativo", "essenziale", "vitale", "cruciale", "necessario", "richiedere", "obbligatorio", "mandatorio", "compulsorio", "inevitabile", "chiave", "fondamentale", "critico", "urgente", "indispensabile", "pressante", "requisito", "paramount", "vitale", "decisivo", "pesante", "fondamentale", "integrale", "maggiore", "sostanziale", "conseguente", "convincente", "imperativo", "prerequisito", "saliente", "urgente", "mandatorio"]
PERSUASIVE_KEYWORDS = {
'en': ["must", "should", "need", "important", "significant", "imperative", "essential",
"vital", "crucial", "necessary", "require", "obligatory", "mandatory", "compulsory",
"unavoidable", "key", "pivotal", "critical", "urgent", "indispensable", "pressing",
"requisite", "paramount", "decisive", "weighty", "fundamental", "integral", "major",
"substantial", "consequential", "compelling", "prerequisite", "salient"],
'it': ["deve", "dovrebbe", "bisogno", "importante", "significativo", "imperativo", "essenziale",
"vitale", "cruciale", "necessario", "richiedere", "obbligatorio", "mandatorio", "compulsorio",
"inevitabile", "chiave", "fondamentale", "critico", "urgente", "indispensabile", "pressante",
"requisito", "vitale", "decisivo", "pesante", "integrale", "maggiore", "sostanziale",
"convincente", "prerequisito", "saliente"]
}

engaging_keywords = {
'en': ["exciting", "interesting", "fascinating", "amazing", "incredible", "gripping", "compelling", "captivating", "thrilling", "enthralling", "spellbinding", "riveting", "absorbing", "arresting", "engaging", "mesmerizing", "stirring", "stimulating", "enchanting", "bewitching", "intriguing", "thought-provoking", "immersive", "enticing", "alluring", "dynamic", "electrifying", "invigorating", "exhilarating", "intoxicating", "engrossing", "bewildering", "eye-opening", "excitative", "inviting", "fascinative"],
'it': ["eccitante", "interessante", "affascinante", "stupefacente", "incredibile", "avvincente", "coinvolgente", "accattivante", "emozionante", "entusiasmante", "incantevole", "travolgente", "assorbente", "sorprendente", "affascinante", "stimolante", "incantatore", "affascinante", "intrigante", "provocante", "immersivo", "allettante", "allettatore", "dinamico", "elettrizzante", "rinvigorente", "esilarante", "incantevole", "avventuroso", "inebriante", "accattivante", "affascinante", "ipnotico", "occhio-aprente", "eccitante", "invitante"]
ENGAGING_KEYWORDS = {
'en': ["exciting", "interesting", "fascinating", "amazing", "incredible", "gripping",
"compelling", "captivating", "thrilling", "enthralling", "spellbinding", "riveting",
"absorbing", "arresting", "engaging", "mesmerizing", "stirring", "stimulating",
"enchanting", "bewitching", "intriguing", "thought-provoking", "immersive", "enticing",
"alluring", "dynamic", "electrifying", "invigorating", "exhilarating", "intoxicating",
"engrossing", "bewildering", "eye-opening", "inviting"],
'it': ["eccitante", "interessante", "affascinante", "stupefacente", "incredibile", "avvincente",
"coinvolgente", "accattivante", "emozionante", "entusiasmante", "incantevole", "travolgente",
"assorbente", "sorprendente", "stimolante", "incantatore", "intrigante", "provocante",
"immersivo", "allettante", "dinamico", "elettrizzante", "rinvigorente", "esilarante",
"avventuroso", "inebriante", "ipnotico", "occhio-aprente"]
}

def detect_language(text):
# Simple heuristic to detect the language based on common stopwords
"""
Detect the language of the provided text.
"""
words = word_tokenize(text.lower())
if any(word in words for word in nltk.corpus.stopwords.words('english')):
return 'en'
elif any(word in words for word in nltk.corpus.stopwords.words('italian')):
if any(word in words for word in nltk.corpus.stopwords.words('italian')):
return 'it'
else:
return 'it' # Default to Italian
return 'it' # Default to Italian

def narrative_index(text, lang):
"""
Calculate the narrative index of the text.
"""
sentences = sent_tokenize(text)
keywords = narrative_keywords[lang]
keywords = NARRATIVE_KEYWORDS[lang]
narrative_score = sum(1 for sentence in sentences if any(word in word_tokenize(sentence.lower()) for word in keywords))
return narrative_score / len(sentences) if sentences else 0

def argument_strength(text, lang):
"""
Calculate the argument strength of the text.
"""
sentences = sent_tokenize(text)
keywords = argument_keywords[lang]
keywords = ARGUMENT_KEYWORDS[lang]
argument_score = sum(1 for sentence in sentences if any(word in word_tokenize(sentence.lower()) for word in keywords))
return argument_score / len(sentences) if sentences else 0

def persuasiveness_score(text, lang):
"""
Calculate the persuasiveness score of the text.
"""
words = word_tokenize(text)
keywords = persuasive_keywords[lang]
keywords = PERSUASIVE_KEYWORDS[lang]
persuasive_score = sum(1 for word in words if word.lower() in keywords)
return persuasive_score / len(words) if words else 0

def engagement_score(text, lang):
"""
Calculate the engagement score of the text.
"""
sentences = sent_tokenize(text)
keywords = engaging_keywords[lang]
keywords = ENGAGING_KEYWORDS[lang]
engagement_score = sum(1 for sentence in sentences if any(word in word_tokenize(sentence.lower()) for word in keywords))
return engagement_score / len(sentences) if sentences else 0

def normalize_score(score, max_score):
"""
Normalize the score by the maximum possible score.
"""
return score / max_score if max_score != 0 else 0

def evaluate_narrative_persuasiveness_metrics(text):
"""
Evaluate narrative and persuasiveness metrics in the text.
"""
lang = detect_language(text)
metrics = {
"Narrative Index": normalize_score(narrative_index(text, lang), 1),
Expand All @@ -85,12 +142,15 @@ def evaluate_narrative_persuasiveness_metrics(text):
}

aggregated_score = sum(metrics[metric] * weights[metric] for metric in metrics) * 100

return metrics, aggregated_score

def main(file_path):
with open(file_path, 'r') as f:
data = json.load(f)
"""
Main function to read JSON file, evaluate metrics, and save results.
"""
with open(file_path, 'r', encoding="utf-8") as file:
data = json.load(file)
text = data.get("content", "")

if not text:
Expand All @@ -109,10 +169,9 @@ def main(file_path):
print(f"{metric}: {score:.4f}")
print(f"Aggregated Narrative and Persuasiveness Score: {aggregated_score:.4f}")


# Export results to JSON
output_file_path = file_path.replace(".json", "_metrics_narrative_persuasiveness.json")
with open(output_file_path, 'w') as out_file:
with open(output_file_path, 'w', encoding="utf-8") as out_file:
json.dump(output, out_file, indent=4)
print(f"Metrics exported to {output_file_path}")

Expand All @@ -121,5 +180,5 @@ def main(file_path):
print("Usage: python evaluate_narrative_persuasiveness.py <file_path>")
sys.exit(1)

file_path = sys.argv[1]
main(file_path)
FILE_PATH = sys.argv[1]
main(FILE_PATH)

0 comments on commit 5c15059

Please sign in to comment.