File size: 16,792 Bytes
a446b0b
df89157
40cd566
 
 
df89157
40cd566
df89157
ed47213
 
40cd566
 
a446b0b
 
 
 
 
df89157
a446b0b
 
 
 
 
df89157
 
 
a446b0b
 
 
 
 
 
df89157
a446b0b
 
df89157
 
a446b0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df89157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed47213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df89157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40cd566
df89157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40cd566
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df89157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a446b0b
df89157
40cd566
df89157
a446b0b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
import os
import re
import nltk
import gradio as gr
import pandas as pd
import seaborn as sns
from statistics import mean
import matplotlib.pyplot as plt
from collections import Counter
from wordcloud import WordCloud
from nltk.sentiment import SentimentIntensityAnalyzer
from preprocessing.preprocess import process_user_input


def create_input_instruction():
    gr.Markdown(
        """
        # Predict Sentiment Labels
        Get started by inputting the conversation into the text box below. The
        conversation should be in the format of `<speaker>:<message>` where speaker is
        either Visitor or Agent. There should only be one message per line.
        
        <b>For example:</b><br/>
       Visitor:  Hi! How are you?<br/>
       Visitor:  Are you there?</br>
       Agent:  Hi! I'm good. And you?
            
        You can also choose from one of the examples below to get a quickstart.
        """
    )


def format_prediction_ouptut(roles, messages, labels):
    output = ""

    for role, message, label in zip(roles, messages, labels):
        output += f"{role}: {message}\n[{label}]\n\n"

    return output


def remove_temp_dir(temp_dir):
    # List all files in the temporary directory
    files = os.listdir(temp_dir)

    # Remove each file within the directory
    for file in files:
        file_path = os.path.join(temp_dir, file)
        if os.path.isfile(file_path):
            os.remove(file_path)
            print(f"=== File '{file}' has been removed.")
        else:
            remove_temp_dir(file_path)
            print(f"=== Directory '{file}' has been removed.")

    os.rmdir(temp_dir)


SENTIMENT_GROUP_MAPPING = {
    "Acceptance": 3,
    "Openness": 3,
    "Interest": 2,
    "Curiosity": 2,
    "Informative": 1,
    "Greeting": 0,
    "None": 0,
    "Uninterested": -1,
    "Anxious": -2,
    "Confused": -2,
    "Annoyed": -2,
    "Remorse": -2,
    "Disapproval": -3,
    "Accusatory": -3,
    "Denial": -3,
    "Obscene": -3,
}

def label_analysis(labeled_conv):
    msg_pattern = r"(Agent|Visitor): (.*)\n\[(.*)\]"
    # find the components of each message, including the speaker, message, and label
    component_lst = re.findall(msg_pattern, labeled_conv)

    labels=[]

    for speaker, _, label in component_lst:
        labels.append(label)
        
    label_counts = Counter(labels)

    # Create a bar plot
    fig1, ax = plt.subplots(figsize=(12, 6))
    sns.barplot(x=list(label_counts.keys()), y=list(label_counts.values()), ax=ax)
    
    plt.title('Label Frequency Distribution')
    plt.xlabel('Labels')
    plt.ylabel('Frequency')
    plt.xticks(rotation=45, ha='right')
    
    labels_text = " ".join(labels)
    wordcloud = WordCloud(width=800, height=400, background_color='white').generate(labels_text)

    # Create a new figure for the word cloud
    fig2, ax2 = plt.subplots(figsize=(10, 5))
    ax2.imshow(wordcloud, interpolation='bilinear')
    ax2.axis('off')  # Turn off the axis

    return fig1,fig2    

def sentiment_flow_plot(labeled_conv):
    """Generate the sentiment flow plot using the output from the label predecting

    Args:
        labeled_conv (str): the displayed output of a sentiment-label prediction.

    Returns:
        _The sentiment flow plot figure.
    """
    msg_pattern = r"(Agent|Visitor): (.*)\n\[(.*)\]"
    # find the components of each message, including the speaker, message, and label
    component_lst = re.findall(msg_pattern, labeled_conv)

    visitor_Y = []
    agent_Y = []

    for speaker, _, label in component_lst:
        if speaker == "Visitor":
            visitor_Y.append(label)
            if agent_Y == []:
                agent_Y.append("None")
            else:
                agent_Y.append(agent_Y[-1])
        else:
            agent_Y.append(label)
            if visitor_Y == []:
                visitor_Y.append("None")
            else:
                visitor_Y.append(visitor_Y[-1])

    X = range(1, len(agent_Y) + 1)
    visitor_Y_converted = [SENTIMENT_GROUP_MAPPING[visitor_Y[i]] for i in range(len(X))]
    agent_Y_converted = [SENTIMENT_GROUP_MAPPING[agent_Y[i]] for i in range(len(X))]

    fig, ax = plt.subplots()
    sns.set(style="whitegrid")

    ax.plot(X, visitor_Y_converted, label="Visitor", color="red", marker="o")
    ax.plot(X, agent_Y_converted, label="Agent", color="green", marker="o")

    plt.legend(loc="upper left", bbox_to_anchor=(1, 1))
    plt.subplots_adjust(right=0.8)

    plt.yticks(ticks=[-3, -2, -1, 0, 1, 2, 3])

    plt.xlabel("Timestamp")
    plt.ylabel("Sentiment Score")
    plt.title("Sentiment Flow Plot")
    plt.close(fig)

    return fig


def sentiment_intensity_analysis(input):
    def analyze_sentiment(text):
        sia = SentimentIntensityAnalyzer()
        scores = [
            sia.polarity_scores(sentence)["compound"]
            for sentence in nltk.sent_tokenize(text)
        ]
        return mean(scores)

    result = process_user_input(input)

    if not result["success"]:
        raise gr.Error(result["message"])

    data = result["data"]
    speakers = [item[1] for item in data]
    messages = [item[2] for item in data]

    df = pd.DataFrame(columns=["Speaker", "Sentiment Intensity", "Timestamp"])

    visitor_previous = {
        "Speaker": ["Visitor"],
        "Sentiment Intensity": [0],
        "Timestamp": [0],
    }
    agent_previous = {
        "Speaker": ["Agent"],
        "Sentiment Intensity": [0],
        "Timestamp": [0],
    }
    for i in range(len(messages)):
        new_row = {
            "Speaker": [speakers[i]],
            "Sentiment Intensity": [analyze_sentiment(messages[i])],
            "Timestamp": [i + 1],
        }
        df = pd.concat([df, pd.DataFrame(new_row)], ignore_index=True)

        # Duplicate the sentiment of the person that does not speak at this duration
        if speakers[i] == "Agent":
            # Agent speak this turn, duplicate the sentiment of the visitor
            visitor_previous["Timestamp"] = [i + 1]
            df = pd.concat([df, pd.DataFrame(visitor_previous)], ignore_index=True)
            agent_previous = new_row
        else:
            # Visitor speak, duplicate the sentiment of the agent
            agent_previous["Timestamp"] = [i + 1]
            df = pd.concat([df, pd.DataFrame(agent_previous)], ignore_index=True)
            visitor_previous = new_row

    return gr.LinePlot(
        df,
        label="Intensity Plot",
        x="Timestamp",
        y="Sentiment Intensity",
        color="Speaker",
        color_legend_position="right",
        title="Conversation Sentiment Intensity",
        tooltip=["Speaker", "Sentiment Intensity"],
        y_lim=[-1, 1],
        height=400,
        width=400,
    )


SENTIMENT_SCORE_TABLE = """
<div align="center" style='font-size: small;'>

|  Sentiment Score  |  Sentiment Label  |
| :---------------: | :---------------: |
|         3         | Acceptance, Openness |
|         2         | Interest, Curiosity |
|         1         | Informative  |
|         0         | Greeting  |
|        -1         | Uninterested |
|        -2         | Anxious, Confused, Annoyed, Remorse |
|        -3         | Disapproval, Accusatory, Denial, Obscene |

</div>
"""


def display_sentiment_score_table():
    gr.Markdown(
        "After submit the conversation and run the model to predict the sentiment labels from the above, we can generate the plot of the sentimen labels found in this conversation to see how the sentiment flow changes over time.\nThe sentiment labels are grouped into corresponding scores below:"
    )
    gr.Markdown(SENTIMENT_SCORE_TABLE)


EXAMPLE_CONVERSATIONS = {
    "Example 1": "Visitor: Hey Jess, available for outcall tonight?\n\nAgent: hey hey what you looking for luv?\n\nVisitor: Some company in El Segundo\n\nAgent: out with friends or just the two of us?\n\nVisitor: Just the two\n\nAgent: looking for some connection then...\n\nVisitor: Yes\n\nAgent: I get it. Looking for companionship, it's a very legit need. I'll level with you. We're a group of guys trying to show other men the harms of the sex trade industry, both to buyers and sellers. You up for a little conversation? No pressure... no judgement.\n\nVisitor: No, but interested in the harms in companionship?\n\nAgent: The truth is nearly all of the women on these sites are not in this career by choice. We work with survivors. Their money goes to pimps.. their lives are controlled.\n\nVisitor: Really?\n\nVisitor: Even when they say \"independent\"?\n\nAgent: Yes. It's all part of the human trafficking system... pimps find & recruit nearly all women who are doing this, they are very, very good at manipulation and control, and working in the background. Sadly, this modern day slavery will be with us as long as there are willing buyers. That's why we are trying to work this angle. The more men that know the truth, the fewer will want to exploit someone in this way.\n\nAgent: I need to move on, but just consider what I've told you tonight. Polarisproject.org is a great resource to learn more... it's nothing like what Hollywood shows ya. We work with the women & some guys who have escaped out of this lifestyle. It is modern-day slavery, straight up. Thanks for the chat. Good night!\n\nVisitor: Thanks, fyi it worked. Hung it up, I'm to old to me messin around in this crazy stuff take care\n\nAgent: I am so glad to hear this friend. You calling this number tonight was not just a coincidence. Take care also!!\n\n",
    "Example 2": "Visitor: What's up sexy\n\nAgent: Thank you! I'm hangin\n\nVisitor: Are you available at the moment\n\nAgent: what's your name\n\nVisitor: David ... Yours\n\nAgent: Dakota is not available right now, but my name is Jeff and I'm working with a bunch of guys trying to curb the demand for victims of human trafficking. Did you ever consider that Dakota could be a victim of trafficking?\n\nVisitor: Fuck no I just wanted to get some pussy .... Bye\n\nAgent: Just so you know your number is in our system now. Understand that next time you click on one of these ads you could be walking into an undercover cop and many of these girls are underage. That is a crime that will follow you the rest of your life!\n\nVisitor: . You think the predators your looking for going to fall into your lap? Lol your not a cop stop trying to be one ... You want to help?\n\nVisitor: Just so you know I don't give no fucks about you or no fucking cops... Threatening me will not get you shit from me ,no info no nothing you stupid cunt..\n\nAgent: Hey man, I did not want to threaten you. I want you to be aware of the risks. Have you heard that most women in prostitution do it against their will, and many are minors?\n\nVisitor: I never fuck with minors that's for sure cause you can tell if they are not of age\n\nAgent: Yeah, many people think it's harmless and these women are in complete control. But, the truth is, most of these women are enslaved, forced to sell themselves by pimps who take 100% of their money. I hope you can see these women in a different light.\n\nVisitor: I know most are blacks living off a woman cause they can't get no job ... I won't see a female if she has a guy around\n\nAgent: I'm curious, is there something missing inside of you, or are you angry about something not right in your life that causes you to seek out connection with these girls?\n\nVisitor: No actually I am on gps monitor and can't go out and meet no one so I got needs and feel sometimes hooking up with one of these girls here and there is what works for my situation....but I'm not disrespectful to them or be doing ugly things ... My ex wife cheated on me after 8yrs of marriage I don't really trust women like enough for a relationship\n\nVisitor: I'm being honest with you cause even tho I don't know u I believe in doing the right thing and your movement with alot of work is going to save lives so\n\nVisitor: that's good\n\nAgent: Hey David, I'm very sorry for your situation and the pain you must be in. Were you raised with any faith perspective?\n\nVisitor: Yes I actually was baptized for the first time in my life in 2018 and have made some drastic changes to my life.... I'm not perfect but I am working hard\n\nAgent: Okay, David. That's great news. We're all a work in progress. God is faithful to forgive us of our sins if we just ask him. Read 1 John 1:9. Can I direct you to some resources to help you overcome this urge to buy sex?\n\nVisitor: Honestly I'm not ready for that is all I can say at the moment.... Sorry but I don't like to lie\n\nAgent: Hey, no worries. When you're ready, check out www.celebraterecovery.com as they have a lot of resources that might help. I will be praying for you, David. I've had a lot of pain in my life and only in my relationship with Jesus have I found true peace that surpasses my understanding. I pray that for you too.\n\nVisitor: What kinda pain ? Do you mind sharing?\n\nVisitor: And what are y'all doing to put those pieces of shit in prison who are hurting these women\n\nAgent: I've had several people close to me pass away tragically in the past few years. Thanks for asking. I'm just trusting God each day trusting he's in control.\n\nAgent: Hey, honestly, the best way we can solve this problem of evil pieces of shit harming these girls is to dry up the demand for these girls by encouraging men like us to stop calling these ads. If the demand dries up, evil predatory scums' business with die.\n\nAgent: Can I get your commitment to do your part and stop engaging these girls on their escort ads?\n\nVisitor: Yes I will but I can promise you that it will not stop matter of fact it will get worse ... They will beat them more and make them do it more only way is\n\nVisitor: to put the pimps in prison for alot of years....\n\nAgent: Hey, I'll be praying for you. Feel free to call me any time if you need to talk. My number is (615) 628-7545. God bless you, brother.\n\nVisitor: Thank u\n\n",
    "Example 3": "Visitor: Heyyy\n\nVisitor: How are you this evening\n\nAgent: better now ;) call me\n\nVisitor: Iam at work for now ,be off around 10pm\n\nVisitor: Need some company\n\nVisitor: Are you independent honey\n\nAgent: well since you arent available at the moment ill just come out and say-these sites are bad news. did you know that most of the girls on here are here against their will? Most of them got dragged into this lifestyle by an abuser, oftentimes before they were of legal consenting age. isnt that sad?\n\nAgent: we are with some guys who are trying to spread awareness of the realities of this \"industry\".\n\nAgent: https://exoduscry.com/choice/\n\nVisitor: Thanks\n\nAgent: i encourage you to watch this video. it is jarring to think about how bad someone else's options must be to choose to be on these sites\n\nVisitor: Ooohhh\n\nAgent: selling their body to make ends meet or appease a pimp\n\nVisitor: That's really awful\n\nAgent: it is. you seem like the kind of guy who wouldnt wont to proliferate that kind of harmful lifestyle. am i right in thinking that?\n\nVisitor: Well iam just looking for attention\n\nVisitor: My marriage is not going well lol\n\nAgent: i know that it is hard to find ourselves lonely and without much alternative to meet that perceived need but its humbling to think that our needs can force someone else into such a dark place\n\nAgent: hey, thanks for sharing that my man. i know it can be hard\n\nAgent: marraige is the most humbling of relationships, isnt it?\n\nVisitor: She leaves with her friends n no time for me\n\nAgent: ive been there my guy. i know that it is alot easier to numb that loneliness for sure\n\nVisitor: I want to be faithful\n\nAgent: does your wife know how you feel when she chooses her friends instead of you?\n\nVisitor: I been drinking lately\n\nVisitor: Yes , she takes pills\n\nAgent: if so, i hope you are praying for her to realize the hurt she is causing and to seek change\n\nVisitor: She had surgery 4 yes ago n it's been hard for her n her addiction on pills\n\nVisitor: Yes for now iam looking for a female friend to talk n see what can we do for each other\n\nAgent: that is hard my man. physical pain is a huge obstacle in life for sure so i hear you\n\nVisitor: Well chat later .thanks\n\nAgent: have you considered pursuing other men who can encourage you instead of looking for the easy way out?\n\nAgent: what is your name my friend? i will be praying for you by name if you wouldnt mind sharing it\n\nAgent: well, i gotta run. watch that video i sent and i will definitely be praying for you. I hope you pray for yourself and for your wife - God can definitely intervene and cause complete change in the situation if He wills it. He is good and He hears you. You are loved by Him, brother. Good night\n\n",
}