Come creare un bot di analisi del sentimento dell'e-mail: un tutorial NLP
Pubblicato: 2022-03-11Le tecnologie di elaborazione del linguaggio naturale sono diventate piuttosto sofisticate negli ultimi anni. Dai giganti della tecnologia agli hobbisti, molti si stanno affrettando a costruire interfacce avanzate in grado di analizzare, comprendere e rispondere al linguaggio naturale. Alexa di Amazon, Cortana di Microsoft, Google Home di Google e Siri di Apple mirano tutti a cambiare il modo in cui interagiamo con i computer.
L'analisi del sentimento, un sottocampo dell'elaborazione del linguaggio naturale, consiste in tecniche che determinano il tono di un testo o di un discorso. Oggi, con l'apprendimento automatico e grandi quantità di dati raccolti dai social media e dai siti di recensioni, possiamo addestrare modelli per identificare il sentimento di un passaggio del linguaggio naturale con discreta precisione.
In questo tutorial imparerai come creare un bot in grado di analizzare il sentimento delle e-mail che riceve e informarti sulle e-mail che potrebbero richiedere la tua attenzione immediatamente.
Analisi del sentimento nelle email
Il bot verrà creato utilizzando un mix di sviluppo Java e Python. I due processi comunicheranno tra loro usando Thrift. Se non hai familiarità con una o entrambe queste lingue, puoi comunque continuare a leggere poiché i concetti fondamentali di questo articolo valgono anche per altre lingue.
Per determinare se un'e-mail richiede la tua attenzione, il bot la analizzerà e determinerà se c'è un forte tono negativo. Invierà quindi un avviso di testo, se necessario.
Useremo Sendgrid per connetterci alla nostra casella di posta e Twilio per inviare avvisi di testo.
Analisi del sentimento: un problema apparentemente semplice
Ci sono parole che associamo a emozioni positive, come amore, gioia e piacere. E ci sono parole che associamo alle emozioni negative, come odio, tristezza e dolore. Perché non addestrare il modello a riconoscere queste parole e contare la frequenza relativa e la forza di ogni parola positiva e negativa?
Bene, ci sono un paio di problemi con questo.
In primo luogo, c'è un problema di negazione. Ad esempio, una frase come "La pesca non è cattiva" implica un'emozione positiva usando una parola che il più delle volte associamo all'essere negativo. Un semplice modello a sacco di parole non sarà in grado di riconoscere la negazione in questa frase.
Inoltre, i sentimenti contrastanti si rivelano ancora un altro problema con l'analisi ingenua del sentimento. Ad esempio, una frase come "La pesca non è cattiva, ma la mela è veramente terribile" contiene sentimenti contrastanti di intensità contrastanti che interagiscono tra loro. Un approccio semplice non sarà in grado di risolvere i sentimenti combinati, la diversa intensità o le interazioni tra i sentimenti.
Analisi del sentimento utilizzando una rete di tensori neurali ricorsivi
La libreria Stanford Natural Language Processing per l'analisi del sentiment risolve questi problemi utilizzando una Recursive Neural Tensor Network (RNTN).
L'algoritmo RNTN prima divide una frase in singole parole. Quindi costruisce una rete neurale in cui i nodi sono le singole parole. Infine, viene aggiunto uno strato tensore in modo che il modello possa adattarsi correttamente alle interazioni tra le parole e le frasi.
Puoi trovare una dimostrazione visiva dell'algoritmo sul loro sito ufficiale.
Il gruppo di Stanford NLP ha addestrato la Recursive Neural Tensor Network utilizzando recensioni di film IMDB contrassegnate manualmente e ha scoperto che il loro modello è in grado di prevedere il sentimento con un'accuratezza molto buona.
Bot che riceve email
La prima cosa che vuoi fare è impostare l'integrazione della posta elettronica in modo che i dati possano essere inviati al tuo bot.
Ci sono molti modi per farlo, ma per semplicità, configuriamo un semplice server web e usiamo l'hook di analisi in entrata di Sendgrid per inviare e-mail al server. Possiamo inoltrare e-mail all'indirizzo di analisi in entrata di Sendgrid. Sendgrid invierà quindi una richiesta POST al nostro server web e saremo quindi in grado di elaborare i dati tramite il nostro server.
Per costruire il server useremo Flask, un semplice framework web per Python.
Oltre a creare il server web, vorremo connettere il servizio web a un dominio. Per brevità, salteremo scrivendo su questo nell'articolo. Tuttavia, puoi leggere di più a riguardo qui.
Costruire un server web in Flask è incredibilmente semplice.
Crea semplicemente un app.py
e aggiungi questo al file:
from flask import Flask, request import datetime app = Flask(__name__) @app.route('/analyze', methods=['POST']) def analyze(): with open('logfile.txt', 'a') as fp_log: fp_log.write('endpoint hit %s \n' % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) return "Got it" app.run(host='0.0.0.0')
Se distribuiamo questa app dietro un nome di dominio e raggiungiamo l'endpoint "/analyze" dell'endpoint, dovresti vedere qualcosa del genere:
> >> requests.post('http://sentiments.shanglunwang.com:5000/analyze').text 'Got it'
Successivamente, vogliamo inviare e-mail a questo endpoint.
Puoi trovare più documentazione qui, ma essenzialmente vuoi configurare Sendgrid come il tuo elaboratore di posta elettronica e fare in modo che Sendgrid inoltri le e-mail al nostro server web.
Ecco la mia configurazione su Sendgrid. Questo inoltrerà le e-mail a @sentibot.shanglunwang.com
come richieste POST a "http://sentiments.shanglunwang.com/analyze":
Puoi utilizzare qualsiasi altro servizio che supporti l'invio di email in entrata tramite webhook.
Dopo aver impostato tutto, prova a inviare un'e-mail al tuo indirizzo Sendgrid, dovresti vedere qualcosa del genere nei registri:
endpoint hit 2017-05-25 14:35:46
È fantastico! Ora hai un bot in grado di ricevere e-mail. Questa è la metà di quello che stiamo cercando di fare.
Ora, vuoi dare a questo bot la possibilità di analizzare i sentimenti nelle e-mail.
Analisi del sentiment tramite posta elettronica con Stanford NLP
Poiché la libreria Stanford NLP è scritta in Java, vorremo costruire il motore di analisi in Java.
Iniziamo scaricando la libreria e i modelli NLP di Stanford in Maven. Crea un nuovo progetto Java, aggiungi quanto segue alle tue dipendenze Maven e importa:
<dependency> <groupId>edu.stanford.nlp</groupId> <artifactId>stanford-corenlp</artifactId> <version>3.6.0</version> </dependency>
È possibile accedere al motore di analisi del sentimento di Stanford NLP specificando l'annotatore del sentimento nel codice di inizializzazione della pipeline. L'annotazione può quindi essere recuperata come struttura ad albero.
Ai fini di questo tutorial, vogliamo solo conoscere il sentimento generale di una frase, quindi non avremo bisogno di analizzare l'albero. Abbiamo solo bisogno di guardare il nodo base.
Questo rende il codice principale relativamente semplice:
package seanwang; import edu.stanford.nlp.pipeline.*; import edu.stanford.nlp.util.CoreMap; import edu.stanford.nlp.ling.CoreAnnotations; import edu.stanford.nlp.sentiment.SentimentCoreAnnotations; import java.util.*; public class App { public static void main( String[] args ) { Properties pipelineProps = new Properties(); Properties tokenizerProps = new Properties(); pipelineProps.setProperty("annotators", "parse, sentiment"); pipelineProps.setProperty("parse.binaryTrees", "true"); pipelineProps.setProperty("enforceRequirements", "false"); tokenizerProps.setProperty("annotators", "tokenize ssplit"); StanfordCoreNLP tokenizer = new StanfordCoreNLP(tokenizerProps); StanfordCoreNLP pipeline = new StanfordCoreNLP(pipelineProps); String line = "Amazingly grateful beautiful friends are fulfilling an incredibly joyful accomplishment. What an truly terrible idea."; Annotation annotation = tokenizer.process(line); pipeline.annotate(annotation); // normal output for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) { String output = sentence.get(SentimentCoreAnnotations.SentimentClass.class); System.out.println(output); } } }
Prova alcune frasi e dovresti vedere le annotazioni appropriate. L'esecuzione del codice di esempio genera:
Very Positive Negative
Integrazione del Bot e del motore di analisi
Quindi abbiamo un programma di analisi del sentimento scritto in Java e un bot di posta elettronica scritto in Python. Come facciamo a farli parlare tra loro?
Ci sono molte possibili soluzioni a questo problema, ma qui useremo Thrift. Faremo girare Sentiment Analyzer come server dell'usato e il bot di posta elettronica come client dell'usato.
Thrift è un generatore di codice e un protocollo utilizzato per consentire a due applicazioni, spesso scritte in linguaggi diversi, di comunicare tra loro utilizzando un protocollo definito. I team Polyglot utilizzano Thrift per creare reti di microservizi per sfruttare al meglio ogni linguaggio che utilizzano.
Per utilizzare Thrift, avremo bisogno di due cose: un file .thrift
per definire gli endpoint del servizio e un codice generato per utilizzare il protocollo definito nel file .proto
. Per il servizio di analisi, sentiment.thrift
il seguente aspetto:

namespace java sentiment namespace py sentiment service SentimentAnalysisService { string sentimentAnalyze(1:string sentence), }
Possiamo generare codice client e server utilizzando questo file .thrift. Correre:
thrift-0.10.0.exe --gen py sentiment.thrift thrift-0.10.0.exe --gen java sentiment.thrift
Nota: ho generato il codice su una macchina Windows. Ti consigliamo di utilizzare il percorso appropriato per l'eseguibile Thrift nel tuo ambiente.
Ora apportiamo le modifiche appropriate al motore di analisi per creare un server. Il tuo programma Java dovrebbe assomigliare a questo:
SentimentHandler.java
package seanwang; public class SentimentHandler implements SentimentAnalysisService.Iface { SentimentAnalyzer analyzer; SentimentHandler() { analyzer = new SentimentAnalyzer(); } public String sentimentAnalyze(String sentence) { System.out.println("got: " + sentence); return analyzer.analyze(sentence); } }
Questo gestore è il punto in cui riceviamo la richiesta di analisi tramite il protocollo Thrift.
SentimentAnalyzer.java
package seanwang; // ... public class SentimentAnalyzer { StanfordCoreNLP tokenizer; StanfordCoreNLP pipeline; public SentimentAnalyzer() { Properties pipelineProps = new Properties(); Properties tokenizerProps = new Properties(); pipelineProps.setProperty("annotators", "parse, sentiment"); pipelineProps.setProperty("parse.binaryTrees", "true"); pipelineProps.setProperty("enforceRequirements", "false"); tokenizerProps.setProperty("annotators", "tokenize ssplit"); tokenizer = new StanfordCoreNLP(tokenizerProps); pipeline = new StanfordCoreNLP(pipelineProps); } public String analyze(String line) { Annotation annotation = tokenizer.process(line); pipeline.annotate(annotation); String output = ""; for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) { output += sentence.get(SentimentCoreAnnotations.SentimentClass.class); output += "\n"; } return output; } }
L'analizzatore utilizza la libreria Stanford NLP per determinare il sentimento del testo e produce una stringa contenente le annotazioni del sentimento per ogni frase nel testo.
SentimentServer.java
package seanwang; // ... public class SentimentServer { public static SentimentHandler handler; public static SentimentAnalysisService.Processor processor; public static void main(String [] args) { try { handler = new SentimentHandler(); processor = new SentimentAnalysisService.Processor(handler); Runnable simple = new Runnable() { public void run() { simple(processor); } }; new Thread(simple).start(); } catch (Exception x) { x.printStackTrace(); } } public static void simple(SentimentAnalysisService.Processor processor) { try { TServerTransport serverTransport = new TServerSocket(9090); TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); System.out.println("Starting the simple server..."); server.serve(); } catch (Exception e) { e.printStackTrace(); } } }
Nota che non ho incluso il file SentimentAnalysisService.java
qui poiché è un file generato. Ti consigliamo di mettere il codice generato in un luogo in cui il resto del tuo codice può accedervi.
Ora che abbiamo il server attivo, scriviamo un client Python per utilizzare il server.
cliente.py
from sentiment import SentimentAnalysisService from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol class SentimentClient: def __init__(self, server='localhost', socket=9090): transport = TSocket.TSocket(server, socket) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) self.transport = transport self.client = SentimentAnalysisService.Client(protocol) self.transport.open() def __del__(self): self.transport.close() def analyze(self, sentence): return self.client.sentimentAnalyze(sentence) if __name__ == '__main__': client = SentimentClient() print(client.analyze('An amazingly wonderful sentence'))
Esegui questo e dovresti vedere:
Very Positive
Grande! Ora che il server è in esecuzione e parla con il client, integriamolo con il bot di posta elettronica istanziando un client e inserendo l'e-mail in esso.
import client # ... @app.route('/analyze', methods=['POST']) def analyze(): sentiment_client = client.SentimentClient() with open('logfile.txt', 'a') as fp_log: fp_log.write(str(request.form.get('text'))) fp_log.write(request.form.get('text')) fp_log.write(sentiment_client.analyze(request.form.get('text'))) return "Got it"
Ora distribuisci il tuo servizio Java sulla stessa macchina su cui stai eseguendo il server Web, avvia il servizio e riavvia l'app. Invia un'e-mail al bot con una frase di prova e dovresti vedere qualcosa del genere nel file di registro:
Amazingly wonderfully positive and beautiful sentence. Very Positive
Analisi dell'e-mail
Va bene! Ora abbiamo un bot di posta elettronica in grado di eseguire analisi del sentiment! Possiamo inviare un'e-mail e ricevere un tag di sentimento per ogni frase che abbiamo inviato. Ora, esploriamo come possiamo rendere fruibile l'intelligence.
Per semplificare le cose, concentriamoci sulle e-mail in cui c'è un'alta concentrazione di frasi negative e molto negative. Usiamo un semplice sistema di punteggio e diciamo che se un'e-mail contiene più del 75% di frasi di sentimento negativo, lo contrassegneremo come una potenziale e-mail di allarme che potrebbe richiedere una risposta immediata. Implementiamo la logica di punteggio nel percorso di analisi:
@app.route('/analyze', methods=['POST']) def analyze(): text = str(request.form.get('text')) sentiment_client = client.SentimentClient() text.replace('\n', '') # remove all new lines sentences = text.rstrip('.').split('.') # remove the last period before splitting negative_sentences = [ sentence for sentence in sentences if sentiment_client.analyze(sentence).rstrip() in ['Negative', 'Very negative'] # remove newline char ] urgent = len(negative_sentences) / len(sentences) > 0.75 with open('logfile.txt', 'a') as fp_log: fp_log.write("Received: %s" % (request.form.get('text'))) fp_log.write("urgent = %s" % (str(urgent))) return "Got it"
Il codice sopra fa alcune ipotesi ma funzionerà a scopo dimostrativo. Invia un paio di email al tuo bot e dovresti vedere l'analisi delle email nei log:
Received: Here is a test for the system. This is supposed to be a non-urgent request. It's very good! For the most part this is positive or neutral. Great things are happening! urgent = False Received: This is an urgent request. Everything is truly awful. This is a disaster. People hate this tasteless mail. urgent = True
Invio di un avviso
Abbiamo quasi finito!
Abbiamo creato un bot e-mail in grado di ricevere e-mail, eseguire analisi del sentiment e determinare se un'e-mail richiede un'attenzione immediata. Ora non ci resta che inviare un SMS di avviso quando un'e-mail è particolarmente negativa.
Useremo Twilio per inviare un avviso di testo. La loro API Python, che è documentata qui, è piuttosto semplice. Modifichiamo il percorso di analisi per inviare una richiesta quando riceve una richiesta urgente.
def send_message(body): twilio_client.messages.create( to=on_call, from_=os.getenv('TWILIO_PHONE_NUMBER'), body=body ) app = Flask(__name__) @app.route('/analyze', methods=['POST']) def analyze(): text = str(request.form.get('text')) sentiment_client = client.SentimentClient() text.replace('\n', '') # remove all new lines sentences = text.rstrip('.').split('.') # remove the last period before splitting negative_sentences = [ sentence for sentence in sentences if sentiment_client.analyze(sentence).rstrip() in ['Negative', 'Very negative'] # remove newline char ] urgent = len(negative_sentences) / len(sentences) > 0.75 if urgent: send_message('Highly negative email received. Please take action') with open('logfile.txt', 'a') as fp_log: fp_log.write("Received: " % request.form.get('text')) fp_log.write("urgent = %s" % (str(urgent))) fp_log.write("\n") return "Got it"
Dovrai impostare le tue variabili di ambiente sulle credenziali del tuo account Twilio e impostare il numero di chiamata su un telefono che puoi controllare. Dopo averlo fatto, invia un'e-mail all'endpoint di analisi e dovresti vedere un SMS inviato al numero di telefono in questione.
E abbiamo finito!
Elaborazione del linguaggio naturale semplificata con Stanford NLP
In questo articolo, hai appreso come creare un bot di analisi del sentiment e-mail utilizzando la libreria NLP di Stanford. La libreria aiuta ad astrarre tutti i dettagli essenziali dell'elaborazione del linguaggio naturale e consente di utilizzarla come elemento costitutivo per le applicazioni NLP.
Spero che questo post abbia dimostrato una delle tante straordinarie potenziali applicazioni dell'analisi dei sentimenti e che questo ti ispiri a creare una tua applicazione NLP.
Puoi trovare il codice per il bot di analisi del sentiment email da questo tutorial NLP su GitHub.