Minh Q. Le commited on
Commit
df89157
1 Parent(s): 93fc4e0

Merged COSMIC and GPT UI

Browse files
Files changed (6) hide show
  1. README.md +1 -1
  2. app/__init__.py +1 -0
  3. app/cosmic_view.py +40 -15
  4. app.py → app/gpt_view.py +145 -168
  5. app/utils.py +110 -17
  6. main.py +3 -2
README.md CHANGED
@@ -5,7 +5,7 @@ colorFrom: green
5
  colorTo: pink
6
  sdk: gradio
7
  sdk_version: 4.7.1
8
- app_file: app/app.py
9
  pinned: false
10
  ---
11
 
 
5
  colorTo: pink
6
  sdk: gradio
7
  sdk_version: 4.7.1
8
+ app_file: main.py
9
  pinned: false
10
  ---
11
 
app/__init__.py CHANGED
@@ -29,6 +29,7 @@ roberta = RobertaModel.from_pretrained(
29
  )
30
  roberta.eval()
31
 
 
32
  comet = CSKFeatureExtractor(dir=EXTRACTORS_PATH, device="cpu")
33
 
34
  cosmic_args = parse_cosmic_args()
 
29
  )
30
  roberta.eval()
31
 
32
+ # decide = 0 for running with gpu, device="cpu" for running with gpu
33
  comet = CSKFeatureExtractor(dir=EXTRACTORS_PATH, device="cpu")
34
 
35
  cosmic_args = parse_cosmic_args()
app/cosmic_view.py CHANGED
@@ -3,10 +3,14 @@ import pickle
3
  import tempfile
4
  import gradio as gr
5
  from tqdm import tqdm
6
- from views.utils import (
7
  create_input_instruction,
8
  format_prediction_ouptut,
9
  remove_temp_dir,
 
 
 
 
10
  EXAMPLE_CONVERSATIONS,
11
  )
12
  from fairseq.data.data_utils import collate_tokens
@@ -15,7 +19,7 @@ import sys
15
 
16
  sys.path.insert(0, "../") # neccesary to load modules outside of app
17
 
18
- from views import roberta, comet, COSMIC_MODEL, cosmic_args
19
  from preprocessing import preprocess
20
  from Model.COSMIC.erc_training.predict_epik import predict, get_valid_dataloader
21
 
@@ -148,9 +152,11 @@ def cosmic_classifier(input):
148
 
149
  # Assuming that there's only one conversation
150
  conv_id = ids[0]
151
- output = format_prediction_ouptut(
152
- speakers[conv_id], sentences[conv_id], predictions[0]
153
- )
 
 
154
 
155
  print()
156
  print("======= Removing Temporary Directory =======")
@@ -190,9 +196,9 @@ def cosmic_ui():
190
  conversation_input = gr.TextArea(
191
  value="",
192
  label="Input you conversation",
193
- placeholder="Plese input your conversation here.\n\n\n\nMaximum number of lines: 200",
194
- lines=5,
195
- max_lines=200,
196
  )
197
 
198
  def on_example_change(input):
@@ -207,15 +213,34 @@ def cosmic_ui():
207
  outputs=conversation_input,
208
  )
209
 
210
- submit_btn = gr.Button(value="Submit")
211
-
212
  with gr.Column():
213
- gr.Markdown(
214
- '</br></br></br></br><h3 style="text-align: center;">Predicted Sentiment Labels for the Conversation</h3></br>'
 
 
 
 
215
  )
216
- output = gr.Markdown(value="", label="Output")
 
217
 
218
- submit_btn.click(cosmic_classifier, conversation_input, output)
 
219
 
220
- conversation_input.change(lambda x: "", conversation_input, output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  return cosmic_model
 
3
  import tempfile
4
  import gradio as gr
5
  from tqdm import tqdm
6
+ from app.utils import (
7
  create_input_instruction,
8
  format_prediction_ouptut,
9
  remove_temp_dir,
10
+ decode_numeric_label,
11
+ decode_speaker_role,
12
+ display_sentiment_score_table,
13
+ sentiment_flow_plot,
14
  EXAMPLE_CONVERSATIONS,
15
  )
16
  from fairseq.data.data_utils import collate_tokens
 
19
 
20
  sys.path.insert(0, "../") # neccesary to load modules outside of app
21
 
22
+ from app import roberta, comet, COSMIC_MODEL, cosmic_args
23
  from preprocessing import preprocess
24
  from Model.COSMIC.erc_training.predict_epik import predict, get_valid_dataloader
25
 
 
152
 
153
  # Assuming that there's only one conversation
154
  conv_id = ids[0]
155
+ speaker_roles = [
156
+ decode_speaker_role(numeric_role) for numeric_role in speakers[conv_id]
157
+ ]
158
+ labels = [decode_numeric_label(pred) for pred in predictions[0]]
159
+ output = format_prediction_ouptut(speaker_roles, sentences[conv_id], labels)
160
 
161
  print()
162
  print("======= Removing Temporary Directory =======")
 
196
  conversation_input = gr.TextArea(
197
  value="",
198
  label="Input you conversation",
199
+ placeholder="Plese input your conversation here",
200
+ lines=15,
201
+ max_lines=15,
202
  )
203
 
204
  def on_example_change(input):
 
213
  outputs=conversation_input,
214
  )
215
 
 
 
216
  with gr.Column():
217
+ output = gr.Textbox(
218
+ value="",
219
+ label="Predicted Sentiment Labels",
220
+ lines=22,
221
+ max_lines=22,
222
+ interactive=False,
223
  )
224
+ submit_btn = gr.Button(value="Submit")
225
+ submit_btn.click(cosmic_classifier, conversation_input, output)
226
 
227
+ # reset the output whenever a change in the input is detected
228
+ conversation_input.change(lambda x: "", conversation_input, output)
229
 
230
+ gr.Markdown("# Sentiment Flow Plot")
231
+ with gr.Row():
232
+ with gr.Column(scale=1):
233
+ display_sentiment_score_table()
234
+ with gr.Column(scale=2):
235
+ plot_box = gr.Plot(label="Analysis Plot")
236
+
237
+ plot_btn = gr.Button(value="Plot Sentiment Flow")
238
+ plot_btn.click(sentiment_flow_plot, inputs=[output], outputs=[plot_box])
239
+
240
+ # reset all outputs whenever a change in the input is detected
241
+ conversation_input.change(
242
+ lambda x: ("", None),
243
+ conversation_input,
244
+ outputs=[output, plot_box],
245
+ )
246
  return cosmic_model
app.py → app/gpt_view.py RENAMED
@@ -1,14 +1,17 @@
1
- import os
2
- import openai
3
- import seaborn as sns
4
  from openai import OpenAI
5
- from dotenv import load_dotenv
 
 
 
 
 
 
6
 
7
- import re
8
- import matplotlib.pyplot as plt
9
 
10
- sample_input = \
11
- """
12
  Visitor: Heyyy
13
  Visitor: How are you this evening
14
  Agent: better now ;) call me
@@ -51,8 +54,7 @@ Agent: well, i gotta run. watch that video i sent and i will definitely be prayi
51
  He is good and He hears you. You are loved by Him, brother. Good night
52
  """
53
 
54
- sample_output = \
55
- """
56
  Visitor: Heyyy
57
  [Greeting]
58
  Visitor: How are you this evening
@@ -128,7 +130,7 @@ Agent: well, i gotta run. watch that video i sent and i will definitely be prayi
128
  He is good and He hears you. You are loved by Him, brother. Good night
129
  [Openness]
130
 
131
- Sentiment Flow Analysis on the Visitor's side:
132
 
133
  The Visitor begins the conversation with a friendly and casual tone, expressing a desire for company and showing interest in the Agent. \
134
  However, as the Agent provides information about the harsh realities of the commercial sex industry, the Visitor's sentiment shifts to acceptance of the information \
@@ -143,8 +145,42 @@ The Visitor openly takes the Agent's information and the conversation flows smoo
143
  show openness toward each other.
144
  """
145
 
146
- def get_completion(conversation, model="gpt-4-1106-preview"):
147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  prompt = f"""
149
  The EPIK Project is about mobilizing male allies \
150
  to disrupt the commercial sex market, \
@@ -182,169 +218,110 @@ def get_completion(conversation, model="gpt-4-1106-preview"):
182
 
183
  Here is a sample input delimited by triple backticks
184
 
185
- ```{sample_input}```
186
 
187
  Here is a same output that you should try to aim for delimited by sqaure brackets
188
 
189
- [{sample_output}]
190
  """
191
-
192
- client = OpenAI()
193
-
194
- messages = [{"role": "user", "content": prompt}]
195
- response = client.chat.completions.create(
196
- model=model,
197
- messages=messages,
198
- temperature=0, # this is the degree of randomness of the model's output
199
- )
200
-
201
- analysis = response.choices[0].message.content
202
-
203
- def extract_conv_with_labels(analysis):
204
- analysis = analysis.replace("\n", " ")
205
- BETWEEN_BACKTICKS = "\\`\\`\\`(.*?)\\`\\`\\`"
206
- match = re.search(BETWEEN_BACKTICKS, analysis)
207
- if match:
208
- conv_with_labels = match.group()[4:-4]
209
- else:
210
- return "OUTPUT IS IN WRONG FORMAT"
211
-
212
- # just reformatting it for better format
213
- conv_with_labels = conv_with_labels.split('] ')
214
- temp = [utterance + ']' for utterance in conv_with_labels[:-1]]
215
- conv_with_labels = temp + [conv_with_labels[-1]]
216
- return conv_with_labels
217
-
218
- grouped_sentiments = {
219
- 'Acceptance': 3,
220
- 'Openness': 3,
221
- 'Interest': 2,
222
- 'Curiosity': 2,
223
- 'Informative': 1,
224
- 'Greeting': 0,
225
- 'None': 0,
226
- 'Uninterested': -1,
227
- 'Anxious': -2,
228
- 'Confused': -2,
229
- 'Annoyed': -2,
230
- 'Remorse': -2,
231
- 'Disapproval': -3,
232
- 'Accusatory': -3,
233
- 'Denial': -3,
234
- 'Obscene': -3
235
- }
236
-
237
-
238
- def sentiment_flow_plot(conv):
239
- conv_with_labels = extract_conv_with_labels(analysis)
240
- num_utterances = len(conv_with_labels)
241
-
242
- visitor_Y = [''] * num_utterances
243
- agent_Y = [''] * num_utterances
244
-
245
- for i in range(num_utterances):
246
- utterance = conv_with_labels[i]
247
- match = re.search(r'\[(.*?)\]$', utterance)
248
- if match:
249
- label = match.group(1)
250
- else:
251
- print("OUTPUT IS IN WRONG FORMAT")
252
- break
253
-
254
- if utterance.startswith('Visitor'):
255
- visitor_Y[i] = label
256
- if i == 0:
257
- agent_Y[i] = 'None'
258
- else:
259
- agent_Y[i] = agent_Y[i-1]
260
- elif utterance.startswith('Agent'):
261
- agent_Y[i] = label
262
- if i == 0:
263
- visitor_Y[i] = 'None'
264
- else:
265
- visitor_Y[i] = visitor_Y[i-1]
266
-
267
- X = range(1,num_utterances+1)
268
- visitor_Y_converted = [grouped_sentiments[visitor_Y[i]] for i in range(num_utterances)]
269
- agent_Y_converted = [grouped_sentiments[agent_Y[i]] for i in range(num_utterances)]
270
-
271
-
272
- fig, ax = plt.subplots()
273
- sns.set(style="whitegrid")
274
-
275
- ax.plot(X, visitor_Y_converted, label='Visitor', color='blue', marker='o')
276
- ax.plot(X, agent_Y_converted, label='Agent', color='green', marker='o')
277
-
278
- plt.legend(loc='upper left', bbox_to_anchor=(1,1))
279
- plt.subplots_adjust(right=0.8)
280
-
281
- plt.yticks(ticks=[-3,-2,-1,0,1,2,3])
282
-
283
- # y_labels = {-3: 'Disapproval/Accusatory/Denial/Obscene', -2: 'Anxious/Confused\nAnnoyed/Remorse', -1: 'Uninterested', 0: 'Greeting/None',
284
- # 1: 'Informative', 2: 'Interest/Curiosity', 3: 'Acceptance/Openness'}
285
-
286
- # cell_text = [[label] for label in y_labels.values()]
287
- # plt.table(cellText=cell_text, rowLabels=list(y_labels.keys()), loc='left')
288
-
289
- # plt.tick_params(axis='y', labelsize=10)
290
-
291
- plt.xlabel('Timestamp')
292
- plt.ylabel('Sentiment Score')
293
- plt.title('Sentiment Flow Plot')
294
-
295
- plt.close(fig)
296
-
297
- return fig
298
-
299
- fig = sentiment_flow_plot(analysis)
300
 
301
- return response.choices[0].message.content, fig
302
 
303
  def set_key(key):
304
- os.environ['OPENAI_API_KEY'] = key
305
- load_dotenv()
306
  return
307
 
308
- aligned_markdown_table = """
309
- <div style='text-align: right; font-size: small;'>
310
-
311
- | Sentiment Score | Sentiment Label |
312
- |:---------------:|:---------------:|
313
- | 3 | Acceptance, Openness |
314
- | 2 | Interest, Curiosity |
315
- | 1 | Informative |
316
- | 0 | Greeting |
317
- | -1 | Uninterested |
318
- | -2 | Anxious, Confused, Annoyed, Remorse |
319
- | -3 | Disapproval, Accusatory, Denial, Obscene |
320
-
321
- </div>
322
- """
323
-
324
- import gradio as gr
325
 
326
- with gr.Blocks() as gpt_analysis:
327
- gr.Markdown("## Conversation Sentiment Analysis Report")
328
- gr.Markdown(
329
- "This is a custom GPT model designed to provide \
330
- a report on overall sentiment flow of the conversation on the \
331
- volunteer's perspective. It also provies a live plot analysis of sentiments throughout the conversation.<br /><br />Click on them and submit them to the model to see how it works.")
332
- api_key = gr.Textbox(label="Key", lines=1)
333
- btn_key = gr.Button(value="Submit Key")
334
- btn_key.click(set_key, inputs=api_key)
335
- with gr.Row():
336
- with gr.Column():
337
- conversation = gr.Textbox(label="Input", lines=4)
338
- with gr.Column():
339
- output_box = gr.Textbox(value="", label="Output",lines=4)
340
- btn = gr.Button(value="Submit")
341
- with gr.Row():
342
- with gr.Column(scale=2):
343
- gr.Markdown(aligned_markdown_table)
344
- with gr.Column(scale=2):
345
- plot_box = gr.Plot(label="Analysis Plot")
346
-
347
-
348
- btn.click(get_completion, inputs=conversation, outputs=[output_box, plot_box])
349
-
350
- gr.TabbedInterface([gpt_analysis], ["GPT Anlysis"]).launch(inline=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import gradio as gr
 
3
  from openai import OpenAI
4
+ from app.utils import (
5
+ format_prediction_ouptut,
6
+ create_input_instruction,
7
+ sentiment_flow_plot,
8
+ display_sentiment_score_table,
9
+ EXAMPLE_CONVERSATIONS,
10
+ )
11
 
12
+ openai_args = {"api_key": ""}
 
13
 
14
+ SAMPLE_INPUT = """
 
15
  Visitor: Heyyy
16
  Visitor: How are you this evening
17
  Agent: better now ;) call me
 
54
  He is good and He hears you. You are loved by Him, brother. Good night
55
  """
56
 
57
+ SAMPLE_OUTPUT = """
 
58
  Visitor: Heyyy
59
  [Greeting]
60
  Visitor: How are you this evening
 
130
  He is good and He hears you. You are loved by Him, brother. Good night
131
  [Openness]
132
 
133
+ # Conversation Sentiment Analysis Report
134
 
135
  The Visitor begins the conversation with a friendly and casual tone, expressing a desire for company and showing interest in the Agent. \
136
  However, as the Agent provides information about the harsh realities of the commercial sex industry, the Visitor's sentiment shifts to acceptance of the information \
 
145
  show openness toward each other.
146
  """
147
 
 
148
 
149
+ def gpt_process_response(resp) -> list:
150
+ """Preprocess the response from GPT into lists of speakers, messages, labels, and
151
+ the summary of the conversation.
152
+
153
+ Args:
154
+ resp (str): response from gpt
155
+
156
+ Raises:
157
+ gr.Error: if GPT produces response with invalid format.
158
+
159
+ Returns:
160
+ list: list of messages with label
161
+ """
162
+ response_pattern = "```(.*)```(.*)"
163
+
164
+ try:
165
+ labeled_conv, summary = re.search(response_pattern, resp, re.DOTALL).groups()
166
+ labeled_conv = labeled_conv.strip()
167
+ summary = summary.strip()
168
+
169
+ msg_pattern = r"(Agent|Visitor): (.*)\n\[(.*)\]"
170
+ labeled_messages = re.findall(msg_pattern, labeled_conv)
171
+
172
+ speakers, messages, labels = [], [], []
173
+ for speaker, message, label in labeled_messages:
174
+ speakers.append(speaker)
175
+ messages.append(message)
176
+ labels.append(label)
177
+
178
+ return speakers, messages, labels, summary
179
+ except:
180
+ raise gr.Error("GPT produced output in wrong format!")
181
+
182
+
183
+ def get_completion(conversation, model="gpt-4-1106-preview"):
184
  prompt = f"""
185
  The EPIK Project is about mobilizing male allies \
186
  to disrupt the commercial sex market, \
 
218
 
219
  Here is a sample input delimited by triple backticks
220
 
221
+ ```{SAMPLE_INPUT}```
222
 
223
  Here is a same output that you should try to aim for delimited by sqaure brackets
224
 
225
+ [{SAMPLE_OUTPUT}]
226
  """
227
+ try:
228
+ client = OpenAI(api_key=openai_args["api_key"])
229
+ messages = [{"role": "user", "content": prompt}]
230
+ response = client.chat.completions.create(
231
+ model=model,
232
+ messages=messages,
233
+ temperature=0, # this is the degree of randomness of the model's output
234
+ )
235
+
236
+ speakers, sentences, labels, summary = gpt_process_response(
237
+ response.choices[0].message.content
238
+ )
239
+ return format_prediction_ouptut(speakers, sentences, labels), summary
240
+ except BaseException:
241
+ raise gr.Error("Can't connect to GPT! Please input a valid OpenAI's API key.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
 
243
 
244
  def set_key(key):
245
+ openai_args["api_key"] = key
 
246
  return
247
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
+ def gpt_ui():
250
+ with gr.Blocks() as gpt_model:
251
+ gr.Markdown("# GPT 4.0")
252
+ gr.Markdown(
253
+ "This is a custom GPT model designed to provide \
254
+ a report on overall sentiment flow of the conversation on the \
255
+ volunteer's perspective. It also provies a live plot analysis of sentiments throughout the conversation.<br /><br />Click on them and submit them to the model to see how it works."
256
+ )
257
+ api_key = gr.Textbox(label="Key", lines=1, type="password")
258
+ btn_key = gr.Button(value="Submit Key")
259
+ btn_key.click(set_key, inputs=api_key)
260
+
261
+ create_input_instruction()
262
+ with gr.Row():
263
+ with gr.Column():
264
+ example_dropdown = gr.Dropdown(
265
+ choices=["-- Not Selected --"] + list(EXAMPLE_CONVERSATIONS.keys()),
266
+ value="-- Not Selected --",
267
+ label="Select an example",
268
+ )
269
+
270
+ gr.Markdown('<p style="text-align: center;color: gray;">--- OR ---</p>')
271
+
272
+ conversation_input = gr.Textbox(
273
+ label="Input your conversation",
274
+ placeholder="Plese input your conversation here",
275
+ lines=15,
276
+ max_lines=15,
277
+ )
278
+
279
+ def on_example_change(input):
280
+ if input in EXAMPLE_CONVERSATIONS:
281
+ return EXAMPLE_CONVERSATIONS[input]
282
+
283
+ return ""
284
+
285
+ example_dropdown.input(
286
+ on_example_change,
287
+ inputs=example_dropdown,
288
+ outputs=conversation_input,
289
+ )
290
+
291
+ with gr.Column():
292
+ output_box = gr.Textbox(
293
+ value="",
294
+ label="Predicted Sentiment Labels",
295
+ lines=22,
296
+ max_lines=22,
297
+ interactive=False,
298
+ )
299
+
300
+ btn = gr.Button(value="Submit")
301
+ report_md = gr.Markdown(value="")
302
+
303
+ btn.click(
304
+ get_completion,
305
+ inputs=conversation_input,
306
+ outputs=[output_box, report_md],
307
+ )
308
+
309
+ gr.Markdown("# Sentiment Flow Plot")
310
+ with gr.Row():
311
+ with gr.Column(scale=1):
312
+ display_sentiment_score_table()
313
+ with gr.Column(scale=2):
314
+ plot_box = gr.Plot(label="Analysis Plot")
315
+
316
+ plot_btn = gr.Button(value="Plot Sentiment Flow")
317
+
318
+ plot_btn.click(sentiment_flow_plot, inputs=[output_box], outputs=[plot_box])
319
+
320
+ # reset all outputs whenever a change in the input is detected
321
+ conversation_input.change(
322
+ lambda x: ("", "", None),
323
+ conversation_input,
324
+ outputs=[output_box, report_md, plot_box],
325
+ )
326
+
327
+ return gpt_model
app/utils.py CHANGED
@@ -1,38 +1,34 @@
1
  import gradio as gr
2
  import os
3
- import sys
4
-
 
5
  from preprocessing.preprocess import decode_numeric_label, decode_speaker_role
6
 
7
 
8
  def create_input_instruction():
9
  gr.Markdown(
10
  """
11
- # Instructions
12
  Get started by inputting the conversation into the text box below. The
13
  conversation should be in the format of `<speaker>:<message>` where speaker is
14
  either Visitor or Agent. There should only be one message per line.
15
 
16
  <b>For example:</b><br/>
17
- &nbsp;&nbsp;&nbsp;&nbsp;Visitor:Hi! How are you?<br/>
18
- &nbsp;&nbsp;&nbsp;&nbsp;Visitor:Are you there?</br>
19
- &nbsp;&nbsp;&nbsp;&nbsp;Agent:Hi! I'm good. And you?
20
 
21
  You can also choose from one of the examples below to get a quickstart.
22
  """
23
  )
24
 
25
 
26
- def format_prediction_ouptut(numeric_roles, messages, numeric_labels):
27
  output = ""
28
 
29
- for numeric_role, message, numeric_label in zip(
30
- numeric_roles, messages, numeric_labels
31
- ):
32
- label = decode_numeric_label(numeric_label)
33
- role = decode_speaker_role(numeric_role)
34
-
35
- output += f"<span style='color:blue;'>[{label}]</span> {role}:{message}\n\n"
36
 
37
  return output
38
 
@@ -54,8 +50,105 @@ def remove_temp_dir(temp_dir):
54
  os.rmdir(temp_dir)
55
 
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  EXAMPLE_CONVERSATIONS = {
58
- "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",
59
- "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 w\n\nVisitor:hat 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 reall\n\nVisitor:y 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",
60
- "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",
61
  }
 
1
  import gradio as gr
2
  import os
3
+ import re
4
+ import seaborn as sns
5
+ import matplotlib.pyplot as plt
6
  from preprocessing.preprocess import decode_numeric_label, decode_speaker_role
7
 
8
 
9
  def create_input_instruction():
10
  gr.Markdown(
11
  """
12
+ # Predict Sentiment Labels
13
  Get started by inputting the conversation into the text box below. The
14
  conversation should be in the format of `<speaker>:<message>` where speaker is
15
  either Visitor or Agent. There should only be one message per line.
16
 
17
  <b>For example:</b><br/>
18
+ Visitor: Hi! How are you?<br/>
19
+ Visitor: Are you there?</br>
20
+ Agent: Hi! I'm good. And you?
21
 
22
  You can also choose from one of the examples below to get a quickstart.
23
  """
24
  )
25
 
26
 
27
+ def format_prediction_ouptut(roles, messages, labels):
28
  output = ""
29
 
30
+ for role, message, label in zip(roles, messages, labels):
31
+ output += f"{role}: {message}\n[{label}]\n\n"
 
 
 
 
 
32
 
33
  return output
34
 
 
50
  os.rmdir(temp_dir)
51
 
52
 
53
+ SENTIMENT_GROUP_MAPPING = {
54
+ "Acceptance": 3,
55
+ "Openness": 3,
56
+ "Interest": 2,
57
+ "Curiosity": 2,
58
+ "Informative": 1,
59
+ "Greeting": 0,
60
+ "None": 0,
61
+ "Uninterested": -1,
62
+ "Anxious": -2,
63
+ "Confused": -2,
64
+ "Annoyed": -2,
65
+ "Remorse": -2,
66
+ "Disapproval": -3,
67
+ "Accusatory": -3,
68
+ "Denial": -3,
69
+ "Obscene": -3,
70
+ }
71
+
72
+
73
+ def sentiment_flow_plot(labeled_conv):
74
+ """Generate the sentiment flow plot using the output from the label predecting
75
+
76
+ Args:
77
+ labeled_conv (str): the displayed output of a sentiment-label prediction.
78
+
79
+ Returns:
80
+ _The sentiment flow plot figure.
81
+ """
82
+ msg_pattern = r"(Agent|Visitor): (.*)\n\[(.*)\]"
83
+ # find the components of each message, including the speaker, message, and label
84
+ component_lst = re.findall(msg_pattern, labeled_conv)
85
+
86
+ visitor_Y = []
87
+ agent_Y = []
88
+
89
+ for speaker, _, label in component_lst:
90
+ if speaker == "Visitor":
91
+ visitor_Y.append(label)
92
+ if agent_Y == []:
93
+ agent_Y.append("None")
94
+ else:
95
+ agent_Y.append(agent_Y[-1])
96
+ else:
97
+ agent_Y.append(label)
98
+ if visitor_Y == []:
99
+ visitor_Y.append("None")
100
+ else:
101
+ visitor_Y.append(visitor_Y[-1])
102
+
103
+ X = range(1, len(agent_Y) + 1)
104
+ visitor_Y_converted = [SENTIMENT_GROUP_MAPPING[visitor_Y[i]] for i in range(len(X))]
105
+ agent_Y_converted = [SENTIMENT_GROUP_MAPPING[agent_Y[i]] for i in range(len(X))]
106
+
107
+ fig, ax = plt.subplots()
108
+ sns.set(style="whitegrid")
109
+
110
+ ax.plot(X, visitor_Y_converted, label="Visitor", color="blue", marker="o")
111
+ ax.plot(X, agent_Y_converted, label="Agent", color="green", marker="o")
112
+
113
+ plt.legend(loc="upper left", bbox_to_anchor=(1, 1))
114
+ plt.subplots_adjust(right=0.8)
115
+
116
+ plt.yticks(ticks=[-3, -2, -1, 0, 1, 2, 3])
117
+
118
+ plt.xlabel("Timestamp")
119
+ plt.ylabel("Sentiment Score")
120
+ plt.title("Sentiment Flow Plot")
121
+ plt.close(fig)
122
+
123
+ return fig
124
+
125
+
126
+ SENTIMENT_SCORE_TABLE = """
127
+ <div align="center" style='font-size: small;'>
128
+
129
+ | Sentiment Score | Sentiment Label |
130
+ | :---------------: | :---------------: |
131
+ | 3 | Acceptance, Openness |
132
+ | 2 | Interest, Curiosity |
133
+ | 1 | Informative |
134
+ | 0 | Greeting |
135
+ | -1 | Uninterested |
136
+ | -2 | Anxious, Confused, Annoyed, Remorse |
137
+ | -3 | Disapproval, Accusatory, Denial, Obscene |
138
+
139
+ </div>
140
+ """
141
+
142
+
143
+ def display_sentiment_score_table():
144
+ gr.Markdown(
145
+ "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:"
146
+ )
147
+ gr.Markdown(SENTIMENT_SCORE_TABLE)
148
+
149
+
150
  EXAMPLE_CONVERSATIONS = {
151
+ "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",
152
+ "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 w\n\nVisitor: hat 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 reall\n\nVisitor: y 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",
153
+ "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",
154
  }
main.py CHANGED
@@ -4,10 +4,11 @@
4
  #
5
 
6
  import gradio as gr
7
- from views import cosmic_view
8
 
9
  cosmic_model = cosmic_view.cosmic_ui()
10
- demo = gr.TabbedInterface([cosmic_model], ["COSMIC"])
 
11
 
12
  if __name__ == "__main__":
13
  demo.launch()
 
4
  #
5
 
6
  import gradio as gr
7
+ from app import cosmic_view, gpt_view
8
 
9
  cosmic_model = cosmic_view.cosmic_ui()
10
+ gpt_model = gpt_view.gpt_ui()
11
+ demo = gr.TabbedInterface([cosmic_model, gpt_model], ["COSMIC", "GPT Analysis"])
12
 
13
  if __name__ == "__main__":
14
  demo.launch()