Hey,
I am doing a basic Twitter sentiment analysis using a pre canned BERT model in hugging face.
The process itself is pretty straight forward.
I am using this python client:
It all works and I can see the python client scoring the tweet. When I pass the variable back it doesn’t seem to. There is the process variables at the point highlighted in the diagram
The tweetScore variable is the one in question. It should be set at this stage due to the success condition of the python job passing it in
return task.complete({output_variable_name: sentiment_scores })
The output_variable_name in that line is passed in and is retrieved correctly as “tweetScore”
It seems to be making the sentiment_scores variable null, when it is not. Its value is
{‘positive’: 0.9864804148674011, ‘neutral’: 0.011598006822168827, ‘negative’: 0.0019216355867683887}
This is the full python script.
import time
from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker
from transformers import AutoModelForSequenceClassification
from transformers import TFAutoModelForSequenceClassification
from transformers import AutoTokenizer
import numpy as np
from scipy.special import softmax
import csv
import urllib.request
task='sentiment'
MODEL = f"cardiffnlp/twitter-roberta-base-{task}"
labels=[]
model = ""
tokenizer = ""
# Required Input Variables
# textToAnalyze: The tweet text to analyze
# outputVariableName: The name of the variable to store the sentiment scores in
# configuration for the Client
default_config = {
"maxTasks": 1,
"lockDuration": 10000,
"asyncResponseTimeout": 5000,
"retries": 3,
"retryTimeout": 5000,
"sleepSeconds": 30
}
def handle_task(task: ExternalTask) -> TaskResult:
textToAnalyze = task.get_variable("textToAnalyze")
print("Analyzing sentiment for task: {}".format(textToAnalyze))
output_variable_name = task.get_variable("outputVariableName")
sentiment_scores = get_sentiment_score(textToAnalyze)
print("Storing " + output_variable_name)
return task.complete({output_variable_name: sentiment_scores })
def get_sentiment_score(text):
encoded_input = tokenizer(text, return_tensors='tf')
output = model(encoded_input)
scores = output[0][0].numpy()
scores = softmax(scores)
ranking = np.argsort(scores)
ranking = ranking[::-1]
ret_val = {}
for i in range(scores.shape[0]):
ret_val[labels[ranking[i]]] = float(scores[ranking[i]])
return ret_val
def preprocess(text):
new_text = []
for t in text.split(" "):
t = '@user' if t.startswith('@') and len(t) > 1 else t
t = 'http' if t.startswith('http') else t
new_text.append(t)
return " ".join(new_text)
if __name__ == '__main__':
tokenizer = AutoTokenizer.from_pretrained(MODEL)
# download label mapping
mapping_link = f"https://raw.githubusercontent.com/cardiffnlp/tweeteval/main/datasets/{task}/mapping.txt"
with urllib.request.urlopen(mapping_link) as f:
html = f.read().decode('utf-8').split("\n")
csvreader = csv.reader(html, delimiter='\t')
labels = [row[1] for row in csvreader if len(row) > 1]
# # TF
model = TFAutoModelForSequenceClassification.from_pretrained(MODEL)
model.save_pretrained(MODEL)
test_scores = get_sentiment_score("This is awesome")
print(test_scores)
ExternalTaskWorker(worker_id="1", config=default_config).subscribe("tweet_sentiment_analyzer", handle_task)
The BPMN
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.11.0">
<bpmn:process id="negativeTweetResponder" name="Negative Tweet Responser" isExecutable="true">
<bpmn:startEvent id="StartEventProcessStarted" name="Process Started">
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="StartEventProcessStarted" targetRef="Activity_0x3e3vj" />
<bpmn:serviceTask id="Activity_0gc0qih" name="Get Toyota Tweets" camunda:class="ai.rubberhose.twitterDelegates.SearchTwitterDelegate">
<bpmn:extensionElements>
<camunda:field name="searchTerm">
<camunda:string>Toyota</camunda:string>
</camunda:field>
<camunda:field name="outputVariableName">
<camunda:string>tweets</camunda:string>
</camunda:field>
<camunda:field name="maxTweets">
<camunda:expression>${20}</camunda:expression>
</camunda:field>
<camunda:inputOutput>
<camunda:outputParameter name="tweetsToReplyTo">
<camunda:list />
</camunda:outputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1k267ki</bpmn:incoming>
<bpmn:outgoing>Flow_13ypp5w</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:subProcess id="Activity_1ymeepj">
<bpmn:incoming>Flow_13ypp5w</bpmn:incoming>
<bpmn:outgoing>Flow_00fqby9</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics isSequential="true" camunda:collection="tweets" camunda:elementVariable="textToAnalyze" />
<bpmn:startEvent id="Event_08v2q0t" name="Being Scoring Tweet">
<bpmn:outgoing>Flow_060esas</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:serviceTask id="Activity_0xn9jd4" name="Score Tweet" camunda:asyncBefore="true" camunda:asyncAfter="true" camunda:type="external" camunda:topic="tweet_sentiment_analyzer">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="outputVariableName">tweetScore</camunda:inputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_060esas</bpmn:incoming>
<bpmn:outgoing>Flow_1n9p4rp</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:sequenceFlow id="Flow_060esas" sourceRef="Event_08v2q0t" targetRef="Activity_0xn9jd4" />
<bpmn:exclusiveGateway id="Gateway_00q2hxz" name="Is Tweet Highly Negative" camunda:asyncBefore="true" camunda:asyncAfter="true">
<bpmn:incoming>Flow_1458fiy</bpmn:incoming>
<bpmn:outgoing>Flow_0c8fo2c</bpmn:outgoing>
<bpmn:outgoing>Flow_1ry48uw</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_1n9p4rp" sourceRef="Activity_0xn9jd4" targetRef="Activity_0ak6b6x" />
<bpmn:sequenceFlow id="Flow_0c8fo2c" name="Yes" sourceRef="Gateway_00q2hxz" targetRef="Activity_0e8i02v">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${tweetScore[negative] >= 0.95}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:endEvent id="Event_0i3h2is" name="End Tweet Scoring">
<bpmn:incoming>Flow_0by99ym</bpmn:incoming>
</bpmn:endEvent>
<bpmn:exclusiveGateway id="Gateway_0hms6y2">
<bpmn:incoming>Flow_1ry48uw</bpmn:incoming>
<bpmn:incoming>Flow_0ngk2kg</bpmn:incoming>
<bpmn:outgoing>Flow_0by99ym</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0by99ym" sourceRef="Gateway_0hms6y2" targetRef="Event_0i3h2is" />
<bpmn:sequenceFlow id="Flow_1ry48uw" name="No" sourceRef="Gateway_00q2hxz" targetRef="Gateway_0hms6y2">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${tweetScore[negative] < 0.95}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_0ngk2kg" sourceRef="Activity_0e8i02v" targetRef="Gateway_0hms6y2" />
<bpmn:scriptTask id="Activity_0e8i02v" name="Collect Tweet" scriptFormat="javascript" camunda:resultVariable="tweetsToReplyTo">
<bpmn:incoming>Flow_0c8fo2c</bpmn:incoming>
<bpmn:outgoing>Flow_0ngk2kg</bpmn:outgoing>
<bpmn:script>var negativeTweetList = tweetsToReplyTo;
negativeTweetList.add({
'tweet': tweet,
'tweetScore': tweetScore});
negativeTweetList;</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_1458fiy" sourceRef="Activity_0ak6b6x" targetRef="Gateway_00q2hxz" />
<bpmn:userTask id="Activity_0ak6b6x" name="Review">
<bpmn:incoming>Flow_1n9p4rp</bpmn:incoming>
<bpmn:outgoing>Flow_1458fiy</bpmn:outgoing>
</bpmn:userTask>
</bpmn:subProcess>
<bpmn:sequenceFlow id="Flow_13ypp5w" sourceRef="Activity_0gc0qih" targetRef="Activity_1ymeepj" />
<bpmn:sequenceFlow id="Flow_00fqby9" sourceRef="Activity_1ymeepj" targetRef="Gateway_0k49rj6" />
<bpmn:sequenceFlow id="Flow_1ngopv2" sourceRef="Activity_06e52nv" targetRef="Activity_1c35f5m" />
<bpmn:endEvent id="Event_1d5i362" name="End">
<bpmn:incoming>Flow_040bxts</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_091z49q" sourceRef="Activity_1c35f5m" targetRef="Gateway_12dre90" />
<bpmn:exclusiveGateway id="Gateway_0k49rj6" name="Are there tweets to respond to?">
<bpmn:incoming>Flow_00fqby9</bpmn:incoming>
<bpmn:outgoing>Flow_047ap8g</bpmn:outgoing>
<bpmn:outgoing>Flow_1avm0ph</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_047ap8g" name="Yes" sourceRef="Gateway_0k49rj6" targetRef="Activity_06e52nv">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${tweetsToReplyTo.size() > 0}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:exclusiveGateway id="Gateway_12dre90">
<bpmn:incoming>Flow_091z49q</bpmn:incoming>
<bpmn:incoming>Flow_1avm0ph</bpmn:incoming>
<bpmn:outgoing>Flow_040bxts</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_040bxts" sourceRef="Gateway_12dre90" targetRef="Event_1d5i362" />
<bpmn:sequenceFlow id="Flow_1avm0ph" name="No" sourceRef="Gateway_0k49rj6" targetRef="Gateway_12dre90">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${tweetsToReplyTo.size() == 0}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:userTask id="Activity_06e52nv" name="Compose Responses">
<bpmn:incoming>Flow_047ap8g</bpmn:incoming>
<bpmn:outgoing>Flow_1ngopv2</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1k267ki" sourceRef="Activity_0x3e3vj" targetRef="Activity_0gc0qih" />
<bpmn:userTask id="Activity_0x3e3vj" name="Capture Search Term">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="capturedSearchTerm" label="Search Term" type="string" defaultValue="#Toyota" />
</camunda:formData>
<camunda:inputOutput>
<camunda:outputParameter name="tweets">
<camunda:list />
</camunda:outputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
<bpmn:outgoing>Flow_1k267ki</bpmn:outgoing>
</bpmn:userTask>
<bpmn:userTask id="Activity_1c35f5m" name="Send Responses">
<bpmn:incoming>Flow_1ngopv2</bpmn:incoming>
<bpmn:outgoing>Flow_091z49q</bpmn:outgoing>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="negativeTweetResponder">
<bpmndi:BPMNEdge id="Flow_1k267ki_di" bpmnElement="Flow_1k267ki">
<di:waypoint x="380" y="200" />
<di:waypoint x="440" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1avm0ph_di" bpmnElement="Flow_1avm0ph">
<di:waypoint x="1530" y="160" />
<di:waypoint x="1530" y="90" />
<di:waypoint x="1910" y="90" />
<di:waypoint x="1910" y="160" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1713" y="72" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_040bxts_di" bpmnElement="Flow_040bxts">
<di:waypoint x="1935" y="185" />
<di:waypoint x="1972" y="185" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_047ap8g_di" bpmnElement="Flow_047ap8g">
<di:waypoint x="1555" y="185" />
<di:waypoint x="1600" y="185" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1569" y="167" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_091z49q_di" bpmnElement="Flow_091z49q">
<di:waypoint x="1840" y="185" />
<di:waypoint x="1885" y="185" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ngopv2_di" bpmnElement="Flow_1ngopv2">
<di:waypoint x="1700" y="185" />
<di:waypoint x="1740" y="185" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_00fqby9_di" bpmnElement="Flow_00fqby9">
<di:waypoint x="1460" y="185" />
<di:waypoint x="1505" y="185" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_13ypp5w_di" bpmnElement="Flow_13ypp5w">
<di:waypoint x="540" y="200" />
<di:waypoint x="600" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_08va5r8_di" bpmnElement="SequenceFlow1">
<di:waypoint x="218" y="200" />
<di:waypoint x="280" y="200" />
<bpmndi:BPMNLabel>
<dc:Bounds x="337.5" y="110" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEventProcessStarted">
<dc:Bounds x="182" y="182" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="161" y="218" width="79" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1wnud1q_di" bpmnElement="Activity_0gc0qih">
<dc:Bounds x="440" y="160" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1d5i362_di" bpmnElement="Event_1d5i362">
<dc:Bounds x="1972" y="167" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1980" y="210" width="20" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0k49rj6_di" bpmnElement="Gateway_0k49rj6" isMarkerVisible="true">
<dc:Bounds x="1505" y="160" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1490" y="217" width="81" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_12dre90_di" bpmnElement="Gateway_12dre90" isMarkerVisible="true">
<dc:Bounds x="1885" y="160" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0chbcvq_di" bpmnElement="Activity_06e52nv">
<dc:Bounds x="1600" y="145" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_09xenqo_di" bpmnElement="Activity_1c35f5m">
<dc:Bounds x="1740" y="145" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1ymeepj_di" bpmnElement="Activity_1ymeepj" isExpanded="true">
<dc:Bounds x="600" y="80" width="860" height="210" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0ngk2kg_di" bpmnElement="Flow_0ngk2kg">
<di:waypoint x="1200" y="200" />
<di:waypoint x="1245" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ry48uw_di" bpmnElement="Flow_1ry48uw">
<di:waypoint x="1020" y="175" />
<di:waypoint x="1020" y="120" />
<di:waypoint x="1270" y="120" />
<di:waypoint x="1270" y="175" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1138" y="102" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0by99ym_di" bpmnElement="Flow_0by99ym">
<di:waypoint x="1295" y="200" />
<di:waypoint x="1352" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0c8fo2c_di" bpmnElement="Flow_0c8fo2c">
<di:waypoint x="1045" y="200" />
<di:waypoint x="1100" y="200" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1059" y="182" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1n9p4rp_di" bpmnElement="Flow_1n9p4rp">
<di:waypoint x="810" y="200" />
<di:waypoint x="850" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_060esas_di" bpmnElement="Flow_060esas">
<di:waypoint x="676" y="200" />
<di:waypoint x="710" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1458fiy_di" bpmnElement="Flow_1458fiy">
<di:waypoint x="950" y="200" />
<di:waypoint x="995" y="200" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_08v2q0t_di" bpmnElement="Event_08v2q0t">
<dc:Bounds x="640" y="182" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="624" y="225" width="69" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0ecggil_di" bpmnElement="Activity_0xn9jd4">
<dc:Bounds x="710" y="160" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_00q2hxz_di" bpmnElement="Gateway_00q2hxz" isMarkerVisible="true">
<dc:Bounds x="995" y="175" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="983" y="232" width="75" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0i3h2is_di" bpmnElement="Event_0i3h2is">
<dc:Bounds x="1352" y="182" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1344" y="225" width="52" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0hms6y2_di" bpmnElement="Gateway_0hms6y2" isMarkerVisible="true">
<dc:Bounds x="1245" y="175" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0h4tugi_di" bpmnElement="Activity_0e8i02v">
<dc:Bounds x="1100" y="160" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1y6wwtk_di" bpmnElement="Activity_0ak6b6x">
<dc:Bounds x="850" y="160" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0n23jl7_di" bpmnElement="Activity_0x3e3vj">
<dc:Bounds x="280" y="160" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>